3
$\begingroup$

I'm trying to figure how to make Mathematica interact with a Fortran program that takes 2 parameters in a first input line, 3 parameters in a second input line and produces two lines as outputs. Below a simple example to illustrate my point:

program par  
  implicit none  
  integer            :: i,j  
  integer            :: k,l,m

  read (*,*) i, j  
  read (*,*) k, l, m  
  write (*,*) (i+j)*k, (i+j)-2*l  
  write (*,*) 2*l, 3*m, i-j 

end program par

When I run the code below in Mathematica, I get "EndOfFile" as a result.

pr = StartProcess["par"];
g[i_, j_, k_, l_, m_] := (Write[pr, ToString[i], ToString[j]]; 
Write[pr, ToString[k], ToString[l], ToString[m]]; Read[pr,Number];Read[pr, Number]);
g[1, 2, 3, 4, 5]

Any help would be highly appreciated. Cheers.

$\endgroup$
  • 1
    $\begingroup$ Can you clarify a bit? What should Mathematica take as an input, and return exactly? $\endgroup$ – anderstood Nov 15 '16 at 0:25
  • $\begingroup$ related: mathematica.stackexchange.com/a/77063/2079.. I suspect your Write may be running the numbers together with no spaces but cant test here..try adding ," ", to the lists $\endgroup$ – george2079 Nov 15 '16 at 1:00
  • $\begingroup$ In the Fortran code given above as an example, the "read" statements are the inputs (variables i and j in the first, and k, l and m in the second), and the "write" are the outputs. $\endgroup$ – LMelo Nov 15 '16 at 1:42
4
$\begingroup$

This worked for me

g[i_, j_, k_, l_, m_] := (
  WriteLine[pr, ToString[i] <> " " <> ToString[j]];
  WriteLine[pr, 
   ToString[k] <> " " <> ToString[l] <>
    " " <> ToString[m]];
  {Read[pr, Record], Read[pr, Record]})

pr = StartProcess["/home/louis/prgms/tmp/par"];
g[1, 2, 3, 4, 5] // ColumnForm

(* " 9 -5", " 8 15 -1" *)

For numeric output, one could use this

g[i_, j_, k_, l_, m_] := (
  WriteLine[pr, ToString[i] <> " " <> ToString[j]];
  WriteLine[pr, 
   ToString[k] <> " " <> ToString[l] <>
    " " <> ToString[m]];
  {ToExpression /@ StringSplit[Read[pr, Record]],
   ToExpression /@ StringSplit[Read[pr, Record]]})

pr = StartProcess["/home/louis/prgms/tmp/par"];
output = g[1, 2, 3, 4, 5]

(* {{9, -5}, {8, 15, -1}} *)

The above works for integer input to and output from the external program, which is okay for specified Fortran program. If the external program, however, were reading and writing floating point numbers, scientific notation and/or text, we would want to do things a little differently.

$\endgroup$
  • $\begingroup$ Nicely done, thanks much! I would slightly modify the two Read statements of your proposed solution to get a numerical output: {Read[StringToStream[Read[pr, Record]], {Number, Number}], Read[StringToStream[Read[pr, Record]], {Number, Number, Number}]} $\endgroup$ – LMelo Nov 15 '16 at 2:17
  • $\begingroup$ ReadList[pr,Number,2] may do $\endgroup$ – george2079 Nov 15 '16 at 2:37
  • $\begingroup$ This also works for numeric output: {Read[pr, {Number, Number}], Read[pr, {Number, Number, Number}]} $\endgroup$ – LouisB Nov 15 '16 at 2:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.