.Net ( c# ) 与 Fortran 混合编程实例(一):求线性方程组的解
几点说明:
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 ,确定。