Fortran调用Matlab

*************************************************
* *
* 一、Visual Fortran中使用Matlab引擎 *
* *
*************************************************
source:http://www.simwe.com/cgi-bin/ut/topic_show.cgi?id=16634&h=1&bpg=1&age=-1
#1.安装
软件版本:
Compaq Visual Fortran(以下简称CVF)6.5
Matlab 6.1
安装路径:
CVF: C:\Program Files\Microsoft Visual Studio
Matlab: D:\matlab
#2.配置mex
matlab下运行命令mex –setup,然后按提示选择CVF编译器
#3.配置编译环境
有两种选择
(1)Matlab下编译
(假设matlab安装目录为 %matlab%)
1.打开%matlab%\bin\win32\mexopts\df60engmatopts.bat
将13行中的 set DF_ROOT=%DF_ROOT %
改为set DF_ROOT =C:\Program Files\Microsoft Visual Studio (CVF安装目录)
2.将matlab的工作目录改为你的fortran源代码存放的目录
3.在matlab下运行 mex –f df60engmatopts.bat exsample.for
(假设源文件为exsample.for 其中有关于matlab引擎的操作)
(2)CVF下编译
1.新建一个项目
2.在tools->directory 里设置 include 和 lib目录
记住要包括以下目录
include ->C:\Program Files\Microsoft Visual Studio\DF98\Include
include->C:\Program Files\Microsoft Visual Studio\DF98\IMSL\Include
include->D:\MATLAB\EXTERN\INCLUDE

lib->D:\MATLAB\EXTERN\LIB\WIN32
lib->D:\MATLAB\EXTERN\LIB\WIN32\DIGITAL\DF60
lib->C:\Program Files\Microsoft Visual Studio\DF98\IMSL\Lib
lib->C:\Program Files\Microsoft Visual Studio\DF98\Lib
3. 在project->setting->link->Object/library modules里添加libmx.lib libmat.
lib libeng.lib

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1。上面提到的无法定位程序输入点 的错误。
因为我是用的matlab自带的一个例程,出现这个错误肯定是自己系统的问题。不知道别人有没有遇到过。在这里发问,没结果呀。我就用“无法定位程序输入点”在“百度”上搜,查到一个mm在玩某个游戏的时候也遇到这样错误,解决的办法就是把提到的那个dll文件名前加_,如libeng.dll改为_libeng.dll,照这样按照出错提示把c:\winnt\system32中的libeng.dll、libmx.dll、libut.dll都改了一遍,再编译运行,搞定。
2。我要做的其实是想借Matlab中的用符号运算解一个二元三次方程组来求八节点等参单元中给定点整体坐标对应的局部坐标。主要就是根据matlab中的fengdemo.f来加入自己的东西,其实也很简单,一些小的地方要注意。开始的时候老是编译不通过,一度都要放弃了,因为用到Symbolic Math Toolbox中的solve,以为不支持。偶尔看fengdemo.f的源程序,在用到engEvalString时输入到matlab中的单引号(')都是用2个单引号('')来表示的,错就在这里,统统改掉,就可以了。
Matlab中的计算结果: 0.99433792247939 0.92631964961160
Fortran中调用结果: 0.994337897515527 0.926319366356284
差一点,双精度的
3。我的源程序
! XSHHN 2004.6.22
program main
double precision ElementCod(16),InquireCod(2),LocalCod(2)
DATA ElementCod/-6.75000E+00,-6.75000E+00,-6.2500,-6.25000E+00,&
& -6.75000E+00,-6.50000E+00,-6.25000E+00,-6.50000E+00,&
& 1.00000E+01,9.50000E+00,9.50000E+00,1.00000E+01,&
& 9.75000E+00,9.50000E+00,9.75000E+00,1.00000E+01/ !一组八节点单元节点坐标
data InquireCod/-6.3,9.55/ !需查询的单元内整体坐标
data LocalCod/2*0/ !查询到的单元内局部坐标
call InquireLocalCod(ElementCod,InquireCod,LocalCod)
write(*,*)LocalCod
end
!调用MATLAB查询局部坐标的子程序
subroutine InquireLocalCod(ElementCod,InquireCod,LocalCod)
double precision ElementCod(16),InquireCod(2),LocalCod(2)
integer engOpen,engGetVariable,mxCreateDoubleMatrix
integer engPutVariable, engEvalString, engClose
integer mxGetPr
integer ep,EC,IC,LC
integer status
write(*,*)ElementCod,InquireCod,LocalCod
ep=engOpen('matlab') !打开Matlab引擎
if (ep.eq.0) then
write(6,*)'Can''t start MATLAB engine'
stop
endif
EC=mxCreateDoubleMatrix(1,16,0) !建立mxArray
call mxCopyReal8ToPtr(ElementCod,mxGetPr(EC),16)
IC=mxCreateDoubleMatrix(1,2,0)
call mxCopyReal8ToPtr(InquireCod,mxGetPr(IC),2)
status = engPutVariable(ep,'EC',EC) !将mxArray送入Matlab
if (status.ne.0) then
write(6,*)'engPutVariable failed1'
stop
endif
status=engPutVariable(ep,'IC',IC) !将mxArray送入Matlab
if (status.ne.0) then
write(6,*)'engPutVariable failed2'
stop
endif
if (engEvalString(ep, 'syms r s;') .ne. 0) then !在这里就开始调用Symbolic Math Toolbox了
write(6,*) 'engEvalString failed3'
stop
endif
!下面开始向Matlab中输入8节点等参单元的形函数,注意在Matlab中的“'”要表示成“''”
mmm=engEvalString(ep,'N1=sym(''(1-r)*(1-s)*(-r-s-1)/4'')')
mmm=engEvalString(ep,'N2=sym(''(1+r)*(1-s)*(r-s-1)/4'')')
mmm=engEvalString(ep, 'N3=sym(''(1+r)*(1+s)*(r+s-1)/4'')')
mmm=engEvalString(ep, 'N4=sym(''(1-r)*(1+s)*(-r+s-1)/4'')')
mmm=engEvalString(ep, 'N5=sym(''(1-r^2)*(1-s)/2'')')
mmm=engEvalString(ep, 'N6=sym(''(1+r)*(1-s^2)/2'')')
mmm=engEvalString(ep, 'N7=sym(''(1-r^2)*(1+s)/2'')')
mmm=engEvalString(ep, 'N8=sym(''(1-r)*(1+s^2)/2'')')
mmm=engEvalString(ep, 'x=0')
mmm=engEvalString(ep, 'y=0')
mmm=engEvalString(ep, 'x=x+N1*EC(1)+N2*EC(2)+N3*EC(3)+N4*EC(4)')
mmm=engEvalString(ep, 'x=x+N5*EC(5)+N6*EC(6)+N7*EC(7)+N8*EC(8)')
mmm=engEvalString(ep, 'y=y+N1*EC(9)+N2*EC(10)+N3*EC(11)+N4*EC(12)')
mmm=engEvalString(ep, 'y=y+N5*EC(13)+N6*EC(14)+N7*EC(15)+N8*EC(16)')
mmm=engEvalString(ep, 'x=x-IC(1)')
mmm=engEvalString(ep, 'y=y-IC(2)')
mmm=engEvalString(ep, '[r,s]=solve(x,y)') !这里是最关键的,就是用solve解方程啊
mmm=engEvalString(ep, 'LC=[eval(r(1)) eval(s(1))]')
LC=engGetVariable(ep,'LC')
call mxCopyPtrToReal8(mxGetPr(LC), LocalCod, 2)
write(*,*)LocalCod !看看结果
call mxDestroyArray(EC) !回收内存
call mxDestroyArray(IC)
call mxDestroyArray(LC)
status = engClose(ep) !关闭Matlab引擎
if (status .ne. 0) then
write(6,*) 'engClose failed'
stop
endif
end
*************************************************
* *
* 二、如何由Fortran中调用MATLAB的M文件 *
* *
*************************************************
http://www.simwe.com/cgi-bin/ut/topic_show.cgi?id=23401&h=1&bpg=2&age=-1
基本的作法是先将m文件转换为dll文件再由Fortran去呼叫之
程式是使用 Matlab 6.5.1
Matlab compiler v3.0.1
Compaq Visual Fortran Pro v6.6.0 (CVF) (Compaq bought DEC and HP bought Compaq)
原始m文件为:
function b= matlabinc(a)
% Increment given argument a and return result b to caller, displaying both _disibledevent=>
disp(b)
explore(b)
end
使用以下的方式compile 为DLL
eval(['mcc -t -L C -W lib:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])
%如果m 文件中有绘图请使用以下方式
% eval(['mcc -B sgl -t -L C -W libhg:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])
以下為原始檔與描述
This heavily commented Fortran program serves as a simple example _disibledevent=>
!
! This program serves as a simple example _disibledevent=>
! % Increment given argument a and return result b to caller, displaying both _disibledevent=>
! disp(b)
! explore(b)
!
! We compile our Matlab script using a function like this
!
! function compileDLL(progName)
! % Compile the .m file given and place result into a dll
! eval(['mcc -t -L C -W lib:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])
! % Use this line instead if you call graphics routines in your .m file
! %eval(['mcc -B sgl -t -L C -W libhg:QuGeneLib -T link:lib -h ' progName '.m libmmfile.mlib'])
!
! This will create two files, QuGeneLib.lib and QuGeneLib.dll. The.lib file contains information for the Fortran
! compiler _disibledevent=>
! Declaration section
! Definitions for the "loadlibrary", "freelibrary" and "getprocaddress" routines are included in the following files
!use dfwin ! More stuff than is in kernel32
use kernel32 ! Use this to safe compilation time if other stuff is not needed
IMPLICIT NONE ! Produce error during compilation if variables aren't declared
!---------------------------------------------------------------------------------------------------------------
INTERFACE
! Define the interfaces to our own Matlab scripts
! The <dllname>LibInitialize() and <dllname>LibTerminate() routines are automatically added by the compilation
! and dll creation progress in Matlab.
SUBROUTINE matlabinc(nlhs,plhs, nrhs,prhs)
integer*4 :: nlhs,nrhs
integer*4 :: plhs(*),prhs(*)
!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:"_mlxMatlabinc" :: matlabinc
!DEC$ ATTRIBUTES VALUE :: nlhs,nrhs
!DEC$ ATTRIBUTES REFERENCE :: plhs,prhs
END SUBROUTINE
SUBROUTINE QuGeneLibInitialize()
!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:"_QuGeneLibInitialize" :: QuGeneLibInitialize
END SUBROUTINE
SUBROUTINE QuGeneLibTerminate()
!DEC$ ATTRIBUTES C, DLLIMPORT, ALIAS:"_QuGeneLibTerminate" :: QuGeneLibTerminate
END SUBROUTINE
END INTERFACE
!---------------------------------------------------------------------------------------------------------------
! This part _disibledevent=>
! Executable section
! Locate the QuGeneLib.dll and load it into memory
! This library contains all of our own Matlab functions
p_QuGeneLib = loadlibrary("QuGeneLib.dll"C)
if (p_QuGeneLib == 0) then
type *, "Error occurred opening QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif
! Set up a pointers to the routines of interest
pr1_QuGeneLib = getprocaddress(p_QuGeneLib, "_QuGeneLibInitialize"C)
if (pr1_QuGeneLib == 0) then
type *, "Error occurred finding _QuGeneLibInitialize in QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif
pr2_QuGeneLib = getprocaddress(p_QuGeneLib, "_mlxMatlabinc"C)
if (pr2_QuGeneLib == 0) then
type *, "Error occurred finding _mlxMatlabinc in QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif
pr3_QuGeneLib = getprocaddress(p_QuGeneLib, "_QuGeneLibTerminate"C)
if (pr3_QuGeneLib == 0) then
type *, "Error occurred finding _QuGeneLibTerminate in QuGeneLib.dll"
type *, "Program aborting"
goto 1000
endif
!===============================================================================================================
! Initialise interface to our Matlab routine
! (this initialisation routine is automatically created by Matlab during compilation)
call QuGeneLibInitialize()
! The real*4 value we want to pass from this Fortran code to our Matlab routine
a(1) = 1.0
a(2) = 2.0
a(3) = 3.0
! Create mx array for this value and remember pointer to that mx array (not the value!)
! The mx Array is a special structure that can contain any Matlab datatype
! We omit checking pointers from here _disibledevent=>
a_mx_p = mxCreateNumericMatrix(3, 1, mxClassIDFromClassName('double'), 0)
! Remember pointer to the data in the mx array, given the pointer to the mx array itself
a_dx_p = mxGetData(a_mx_p)
type *, a
! Store data in Matlab mx array
call mxCopyReal8ToPtr(a, a_dx_p, 3)
! Now we want to prove the data above has been stored by retrieving it again
! Retrieve the number of values (elements) in the mx array, given the pointer to the mx array (not the value!)
na = mxGetNumberOfElements(a_mx_p)
! Check
type *, na
! Now call our Matlab routine which returns b given the argument a (actually pointers to a & b)
call matlabinc(1,b_mx_p, 1,a_mx_p)
! Retrieve data pointer given the mx array pointer
b_dx_p = mxGetData(b_mx_p)
! Convert the value(s) stored in the mx array to Fortran representation, given the pointer to the data in the mx array
call mxCopyPtrToReal8(b_dx_p, b, 3)
! Just to see if it worked
type *, b
! Release memory
call mxDestroyArray(a_mx_p)
call mxDestroyArray(b_mx_p)
! Terminate interface to our Matlab routine
! (this termination routine is automatically created by Matlab during compilation)
call QuGeneLibTerminate()
1000 continue
! Release library
status = freelibrary(p_QuGeneLib)
end
Tags: 

延伸阅读

最新评论

发表评论