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$
3
  • 1
    $\begingroup$ Can you clarify a bit? What should Mathematica take as an input, and return exactly? $\endgroup$
    – anderstood
    Nov 15, 2016 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, 2016 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$
    – lgcm
    Nov 15, 2016 at 1:42

1 Answer 1

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$
3
  • $\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$
    – lgcm
    Nov 15, 2016 at 2:17
  • $\begingroup$ ReadList[pr,Number,2] may do $\endgroup$
    – george2079
    Nov 15, 2016 at 2:37
  • $\begingroup$ This also works for numeric output: {Read[pr, {Number, Number}], Read[pr, {Number, Number, Number}]} $\endgroup$
    – LouisB
    Nov 15, 2016 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.