zoukankan      html  css  js  c++  java
  • .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 ,确定。



  • 相关阅读:
    Understanding about Baire Category Theorem
    Isometric embedding of metric space
    Convergence theorems for measurable functions
    Mindmap for "Principles of boundary element methods"
    Various formulations of Maxwell equations
    Existence and uniqueness theorems for variational problems
    Kernels and image sets for an operator and its dual
    [loj6498]农民
    [luogu3781]切树游戏
    [atAGC051B]Three Coins
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106925.html
Copyright © 2011-2022 走看看