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 ,确定。



  • 相关阅读:
    多继承
    NavigationController的使用
    WebService概述
    IOS block 教程
    多测师肖老师__项目讲解(12.3)
    跨平台跨服务器跨网站SSO(单点登录)方案的DEMO
    使用SQL Server Profiler
    asp.net生成高质量缩略图通用函数(c#代码),支持多种生成方式
    SQL优化实例:从运行30分钟到运行只要30秒
    测试工具的选择和使用
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106925.html
Copyright © 2011-2022 走看看