如何在Mathematica中使用FORTRAN子程序或函数?

14

我对在Mathematica会话中调用fortran代码很感兴趣。我了解到Mathlink提供了一种实现的方法。但是我对C语言知之甚少,对C++更是一无所知。 是否有人能够给我提供一个详细的示例呢?

我使用的是Mathematica 8、MS Visual Studio 2008和Intel Fortran 11。操作系统为Windows 7 Home Premium。

非常感谢!


4
这个链接可能对你有趣。 - celtschk
你有一个非常小但完整的FORTRAN代码示例,以测试可能的解决方案吗? 我认为可以通过使用f2c将FORTRAN转换为C,然后使用LibraryLink创建一个动态库,Mathematica可以加载。 - Arnoud Buzing
4
这也可能很有用。对于MathLink,您只需要使用C语言,不需要任何C ++知识,而且学习C语言相当容易。但是,如果要将其与Fortran集成,则可能需要学习一些关于调用约定的内容,这需要一些更高级的知识(除非您熟悉计算机内部结构)。 - Szabolcs
3
搜索c和fortran问题,发现这个有趣的答案涉及使用gcc将fortran与c联合编程时的调用约定。 - rcollyer
3
@rcollyer提供的答案实际上更为通用。Fortran ISO C绑定是Fortran 2003语言标准的一部分,因此它依赖于编译器和平台,并且提供了一种从C调用Fortran或反之的方式。除了gfortran和gcc之外,许多编译器都支持它。它避免了旧的问题,例如需要了解内部调用约定和名称混淆。因此,如果有一种从Mathematica调用C的方法,您可以使用ISO C绑定来调用Fortran,从而使您的Fortran过程使用C调用约定。 - M. S. B.
显示剩余8条评论
1个回答

7
以下是我使用Windows系统成功使用gfortan和gcc的明确示例:
我发现了这个博客Adventures in Mathlink。它提供了一个具体的例子,对我非常有帮助。我安装了MinGW以便使用gfortran和gcc。安装后,必须设置PATH才能在不每次输入路径的情况下使用gfortran和gcc。添加PATH的技巧是:添加完PATH后,打开cmd,运行set PATH=C:,然后关闭cmd,再次打开它,用echo %PATH%,你会看到新的路径列表。我按照链接的博客中的步骤,在Windows上进行了适应,并使用教程示例addtwo。
Mathematica代码编写一个.bat文件并运行它以生成可执行文件。
(* Write a .bat file to compile the MathLink template *.tm, FORTRAN codes *.f and 
C codes *.c files, and run it to create an executable file. *)
CreateExeF[s_String] := 
Module[{dir, libdir, bindir, BatCode, bat}, dir = NotebookDirectory[];
{libdir, bindir} = StringJoin[
  "\"", $InstallationDirectory, 
 "\\SystemFiles\\Links\\MathLink\\DeveloperKit\\Windows\\CompilerAdditions\\mldev32\\",
  #] & /@ {"lib\\", "bin\\"};
BatCode = StringJoin[
 "gfortran -c ", #, ".f -o ", #, "f.o
 gcc -c ", #, ".c -o ", #, ".o
 ",
 bindir, "mprep.exe\" ", #, ".tm -o ", #, "tm.c
 gcc -c ", #, "tm.c -o ", #, "tm.o
 gcc ", #, "tm.o ", #, ".o ", #, "f.o ",
 libdir, "ml32i3m.lib\" ", 
 "-lm -lpthread -mwindows -lstdc++ -o ", #
 ] &;
 (* write the .bat file *)
 bat = Export[FileNameJoin[{dir, # <> ".bat"}], BatCode[dir <> #], 
  "string"] &[s];
 (* run the .bat file *)
 Run[bat]]

FORTRAN代码addtwo.f

   subroutine addtwof(i,j,k)
   integer i, j, k
   k = i + j
   end

C包装器 addtwo.c

#include "mathlink.h"

int addtwo(int i, int j) 
{
  int res;
  addtwof_(&i, &j, &res);
  return res;
}

#if WINDOWS_MATHLINK

#if __BORLANDC__
#pragma argsused
#endif

int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine,     int nCmdShow)
{
char  buff[512];
char FAR * buff_start = buff;
char FAR * argv[32];
char FAR * FAR * argv_end = argv + 32;

hinstPrevious = hinstPrevious; /* suppress warning */

if( !MLInitializeIcon( hinstCurrent, nCmdShow)) return 1;
MLScanString( argv, &argv_end, &lpszCmdLine, &buff_start);
return MLMain( (int)(argv_end - argv), argv);
}

#else

int main(int argc, char* argv[])
{
return MLMain(argc, argv);
}

#endif

模板文件addtwo.tm与Todd Gayley教程中的相同。为了完整起见,在此也提供:

:Begin:
:Function:       addtwo
:Pattern:        AddTwo[i_Integer, j_Integer]
:Arguments:      { i, j }
:ArgumentTypes:  { Integer, Integer }
:ReturnType:     Integer
:End:

:Evaluate:       AddTwo::usage = "AddTwo[i, j] gives the sum of two integer numbers i and j."

您在Mathematica中使用Fortran的动机是什么? - Rolf Mertig
@Mertig,首先非常感谢您为FeynCalc所付出的努力!具体来说,我需要计算一些包含相当多四点环积分的衰变振幅。然后我需要绘制一些不变质量分布和Dalitz图。只用Mathematica的话,这将非常慢。但在这种情况下我想使用Mathematica,因为它可以为我提供漂亮的图形。您有更好的建议吗? - unstable
@Mertig,如果可以通过C将表达式发送到FORTRAN,然后将结果返回到Mathematica,那就更好了...这可行吗? - unstable
是的,这是可能的,但需要投入大量精力。我之前曾经尝试过一些实验。这个问题太复杂了,在Stackoverflow上无法继续讨论。请直接给我发送电子邮件。 - Rolf Mertig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接