1

So what I am trying to achieve is the following:

  1. Define an array in Python;
  2. Pass that array and its dimension into Fortran via f2py;
  3. Use that array among various subroutines within the Fortran code. (The Fortran code does not change the array.)

I already know that this is impossible in a common block from this answer. The Fortran code consists of many separate scripts, so I cannot use contains either. Is it possible that this can be achieved otherwise? Thanks in advance!

zyy
  • 1,271
  • 15
  • 25

1 Answers1

2

yes it's possible. Here is one way of doing it.

Create fortran code like so...

!example.f90
subroutine compute(x_1d, x_2d, nx, ny)

  implicit none
  integer, parameter :: dp = selected_real_kind(15, 307) !double precision

  ! input variables
  integer, intent(in)       :: nx
  integer, intent(in)       :: ny
  real(kind=dp), intent(in) :: x_1d(nx), x_2d(nx, ny)

  !f2py intent(in) x_1d, x_2d

  print *, 'Inside fortran code'
  print *, 'shape(x_1d) = ',  shape(x_1d)
  print *, 'shape(x_2d) = ',  shape(x_2d)

end subroutine compute

Compile it with f2py to make a module you can import into python.

python -m numpy.f2py -m example -h example.pyf example.f90
python -m numpy.f2py -c --fcompiler=gnu95 example.pyf example.f90

Now you should have a shared object file called something like example.cpython-39-x86_64-linux-gnu.so which can be imported directly into python like so:

#example.py
from example import compute
import numpy as np

def main():

    nx = 2
    ny = 4

    x = np.random.rand(nx)
    y = np.random.rand(nx, ny)

    print(compute.__doc__)

    compute(x, y)

    return

if __name__ == "__main__":
    main()

Running python example.py gives:

compute(x_1d,x_2d,[nx,ny])

Wrapper for ``compute``.

Parameters
----------
x_1d : input rank-1 array('d') with bounds (nx)
x_2d : input rank-2 array('d') with bounds (nx,ny)

Other Parameters
----------------
nx : input int, optional
    Default: shape(x_1d, 0)
ny : input int, optional
    Default: shape(x_2d, 1)

 Inside fortran code
 shape(x_1d) =            2
 shape(x_2d) =            2           4

Notice you don't need to explicitly pass the dimensions. It is handled automagically by f2py and the directives we put in the fortran code !f2py.

melt
  • 46
  • 5
  • Thank you so much for the answer, I am busy with other work to do recently. I will try to implement your solution as soon as I have time! – zyy Nov 12 '22 at 11:12