Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use FORTRAN subroutines or functions in Mathematica?

I'm interested in calling fortran codes in a Mathematica session. I learn that Mathlink offers a way to do that. But I have little knowledge on C and nothing on C++. Is anybody willing to give me a detailed example?

I'm using with Mathematica 8, MS Visual Studio 2008 and Intel Fortran 11. The system is Windows 7 Home Premium.

Many thanks!

like image 663
unstable Avatar asked Nov 18 '11 16:11

unstable


People also ask

How do I use subroutine in FORTRAN?

A Fortran function is similar to a mathematical function, which takes one or many parameters as inputs and returns a single output value. A Fortran subroutine is a block of code that performs some operation on the input variables, and as a result of calling the subroutine, the input variables are modified.

How do you define a function in FORTRAN?

A FORTRAN function is a procedure whose result is a single number, logical value, character string or array. There are two types of functions, intrinsic and user-defined. Intrinsic functions are those functions built into a FORTRAN language, such as SIN(x) or LOG(x).

How do you call a subroutine in FORTRAN 90?

In the main program, a subroutine is activated by using a CALL statement which include the subroutine name followed by the list of inputs to and outputs from the subroutine surrounded by parenthesis. The inputs and outputs are collectively called the arguments.


1 Answers

The following is an explicit example which I succeeded using gfortan and gcc with the Windows system:

I found this blog Adventures in Mathlink. It is helpful with a specific example. I installed MinGW in order to use gfortran and gcc. After installation, one must set PATH in order to use gfortran and gcc without typing the path each time. A tip for adding PATH without restarting the system: After adding the PATH, open cmd, and run set PATH=C: Then close cmd, whenyou open it again, with echo %PATH%, you will see the new path list. I followed the steps in the linked blog, adapted to Windows, with the tutorial example addtwo:

The Mathematica codes writing a .bat file and running it to generate the executable

(* 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 codes addtwo.f

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

C wrapper 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

The template file addtwo.tm is the same as the one in Todd Gayley's tutorial. For completeness, it is also given here:

: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."
like image 151
unstable Avatar answered Oct 08 '22 02:10

unstable