几点说明:
1.线性方程组的输入采用矩阵形式,以 “," 分割,写入 txt 文本中;
2. .Net 读取文本,以 ”,“ 拆分存入二维数组中,再将数组传递给 Fortran DLL 进行求逆、求解;
3.求解( A x = b )方法采用系数矩阵 A 求逆与 b 列阵相乘取得解列阵 x 。
4.开发平台: VS2008 + CVF6
5. Debug 文件夹清单:
—— Debug
———— EXAMPLES (文件夹——存放算例)
———— FORTRANCAL (文件夹——存放 Fortran Dll 文件)
—————— LinearEquation.dll (动态链接库——求解线性方程组的类)
—————— PlaceUsingTxt.dll (动态链接库——文本文件操作,用以取得系数矩阵、常数列阵)
—————— Main.exe (Windows 控制台程序——执行文件)
开始:
1.新建类库,LinearEquation ,新建类 ClassY ,添加引用之前准备的 PlaceUsingTxt.dll (参考文章 .Net 中操作文本文件),贴入以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using PlaceUsingTxt;
namespace LinearEquation
{
public class ClassY
{
//二维数组存放系数矩阵
private Single[,] d;
//系数矩阵的行数、列数
private int rows, cols;
public ClassY(string FileName)
{
ClassReadTxt cr = new ClassReadTxt(Environment.CurrentDirectory + "/EXAMPLES/" + FileName + ".txt");
string[,] str = cr.OutStr2D();
cr.close();
rows = str.GetLength(0);
cols = str.GetLength(1);
//将读取的字符串数组转为数值型
d = new Single[rows, cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
d[i, j] = Convert.ToSingle(str[i, j]);
}
}
}
[DllImport("FORTRANCAL/MatrixCal.dll")]
public static extern void MatrixNi(ref Single A, ref int n);
//得到逆矩阵
public Single[,] GetA_()
{
//取得需要求逆的方阵
Single[,] A = new Single[rows, rows];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < rows; j++)
{
A[i, j] = d[i, j];
}
}
//返回逆矩阵
MatrixNi(ref A[0, 0], ref rows);
return A;
}
//取得列阵
public Single[] Getb()
{
Single[] b = new Single[rows];
for (int i = 0; i < rows; i++)
{
b[i] = d[i, cols - 1];
}
return b;
}
[DllImport("FORTRANCAL/MatrixCal.dll")]
public static extern void MatrixJie(ref Single A_, ref int n, ref Single b, ref Single x);
//取得解
public Single[] Getx()
{
Single[] x = new Single[rows];
MatrixJie(ref this.GetA_()[0, 0], ref rows, ref this.Getb()[0], ref x[0]);
return x;
}
//测试用,返回从文本读取的矩阵
public Single[,] GetM()
{
return d;
}
}
}
编译生成 LinearEquation.dll 。
2. (Fortran 方面)新建项目,Fortran 动态链接库,命名为 MatrixCal ,新建 2 个源文件,关于 .Net 与 Fortran 混合编程基础参考文章(.Net(c#) 通过 Fortran 动态链接库,实现混合编程),贴入以下代码:
(1)系数矩阵求逆
subroutine MatrixNi(a,num)
implicit none
!dec$ attributes dllexport::MatrixNi
!dec$ attributes alias:"MatrixNi"::MatrixNi
!dec$ attributes reference::a,num
integer::num
real(4)::a(num,num)
integer::i,j,k
integer::n
n = num
do k=1,N
a(k,k) = 1.d0/a(k,k)
do j=1,N
if(j/=k) a(j,k) = a(k,k)*a(j,k)
end do
do i=1,N
do j=1,N
if(i/=k.and.j/=k) a(j,i) = a(j,i) - a(k,i)*a(j,k)
end do
if(i/=k) a(k,i) = -a(k,i)*a(k,k)
end do
end do
end subroutine
其中, a 为系数矩阵, num 为方阵的维数。将 .Net 传递的数组首地址后 n × n 个地址中数字取出,当成数组来使用,将 a 求逆,然后存回原地址中。
(2)系数逆矩阵与列阵 b 相乘取得 解列阵 x
subroutine MatrixJie(a,num,b,x)
implicit none
!dec$ attributes dllexport::MatrixJie
!dec$ attributes alias:"MatrixJie"::MatrixJie
!dec$ attributes reference::a,num,b,x
integer::num
real(4)::a(num,num)
real(4)::b(num)
real(4)::x(num)
integer::n,i,j
n = num
do i = 1,N
do j = 1,N
x(i) = x(i) + a(j,i) * b(j)
end do
end do
end subroutine
其中,a 为刚才求得的逆矩阵,num 为方阵维数,b 为(A x = b)中右侧列阵,x 为所求的解列阵。
编译后将 MatrixCal.dll 放入 Degug/FORTRANCAL 中。
3.(主程序)新建 windows 控制台程序,命名为 Main,添加对 LinearEquation.dll 的引用,贴入代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LinearEquation;
namespace Main
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please press down the filename.");
string s = Console.ReadLine();
ClassY c = new ClassY(s.Trim());
//取得逆矩阵
Single[,] A_ = c.GetA_();
//取得解列阵
Single[] x = c.Getx();
for (int i = 0; i < A_.GetLength(0); i++)
{
for (int j = 0; j < A_.GetLength(1); j++)
{
Console.Write(A_[i, j].ToString() + ",");
}
Console.WriteLine("");
}
Console.WriteLine();
for (int i = 0; i < x.GetLength(0); i++)
{
Console.WriteLine(x[i].ToString());
}
Console.ReadLine();
}
}
}
4.进行测试,在 Debug 文件夹中新建文件夹 EXAMPLES ,新建文本 test.txt ,写入:
1,1,1,1
1,2,1,1
1,1,3,1
这个矩阵原型为:
x + y + z = 1
x + 2y + z = 1
x + y + 3z = 1
保存,运行程序,键入 test ,返回
注:
若要将此程序在未装 cvf 的电脑中运行,在 cvf 中编译 MatrixCal.dll 时,对 cvf 进行如下设置:
Project - Settings - Fortran ,在 Category 中选择 Libraries ,选择 Multi-threaded ,确定。