Search code examples
pythonfortranf2py

f2py error with allocatable arrays


I have a Fortran subroutine that I would like to use in Python.

subroutine create_hist(a, n, dr, bins, hist)
    integer, intent(in) :: n
    real(8), intent(in) :: a(n)
    real(8), intent(in) :: dr
    integer, intent(out), allocatable :: hist(:)
    real(8), intent(out), allocatable :: bins(:)

    n_b = n_bins(a, n, dr)  ! a function calculating the number of bins
    allocate(bins(n_b+1))
    allocate(hist(n_b))
    hist = 0

    !... Create the histogram hist by putting elems of a into bins
end subroutine

It is a simple programme to get an array of numbers a and create a histogram based on given bin size dr. First, it gets the number of bins using function n_bins and then accordingly allocates the space for the arrays bins and hist.

While gfortran compiles this code fine, f2py raises an error:

/tmp/tmpY5badz/src.linux-x86_64-2.6/mat_ops-f2pywrappers2.f90:32.37:
      call create_hist_gnu(a, n, dr, bins, hist)
Error: Actual argument for 'bins' must be ALLOCATABLE at (1)

As I understand it, f2py does not tolerate allocating space for arrays at runtime (no idea why, as this seems to be a natural scientific need).

Could anyone please suggest a way to allocate Fortran arrays at run-time so that f2py is happy with that?


Solution

  • As far as I know f2py does not support dummy arguments (sometimes known as function parameters) which have the attribute ALLOCATABLE. An alternative would be to make it a large enough explicit shape array. You would then use just a certain part of the array.

    subroutine create_hist(a, n, dr, n_b_max, bins, hist)
        integer, intent(in) :: n
        real(8), intent(in) :: a(n)
        real(8), intent(in) :: dr
        integer, intent(in) :: n_b_max
        integer, intent(out) :: hist(n_b_max)
        real(8), intent(out) :: bins(n_b_max+1)
    

    By the way, using real(8) is not a portable way how to specify 64-bit precision and will fail with certain compilers. Even good old double precision is better as it will always compile to something and often to 64 bit.