Search code examples
pythonnumpyfortranfortran90f2py

F2PY cannot see module-scope variables


Sorry about being new to both Fortran 90 and f2py.

I am using Windows 64 bit, Python 3.4 64 bit, gfortran. Numpy version is 1.9.1, and I commented the "raise NotImplementedError("Only MS compiler supported with gfortran on win64")" in the gnu.py, as instructed on this link: http://scientificcomputingco.blogspot.com.au/2013/02/f2py-on-64bit-windows-python27.html

I have a module in fortran, written as follows, with a module-scope variable dp:

! testf2py.f90
module testf2py
    implicit none
    private
    public dp, i1
    integer, parameter :: dp=kind(0.d0)
contains
    real(dp) function i1(m)
        real(dp), intent(in) :: m(3, 3)
        i1 = m(1, 1) + m(2, 2) + m(3, 3)
        return
    end function i1
end module testf2py

Then, if I run f2py -c testf2py.f90 -m testf2py

It would report an error, stating that dp was not declared.

If I copy the module-scope to the function-scope, it would work.

! testf2py.f90
module testf2py
    implicit none
    private
    public i1
    integer, parameter :: dp=kind(0.d0)
contains
    real(dp) function i1(m)
        integer, parameter :: dp=kind(0.d0)
        real(dp), intent(in) :: m(3, 3)
        i1 = m(1, 1) + m(2, 2) + m(3, 3)
        return
    end function i1
end module testf2py

However, this does not look like the best coding practice though, as it is pretty "wet".

Any ideas?


Solution

  • Here's a work-around, in which dp is moved to a types module, and the use types statement is added to the function i1.

    ! testf2py.f90
    
    module types
        implicit none
        integer, parameter :: dp=kind(0.d0)
    end module types
    
    module testf2py
        implicit none
        private
        public i1
    contains
        real(dp) function i1(m)
            use types
            real(dp), intent(in) :: m(3, 3)
            i1 = m(1, 1) + m(2, 2) + m(3, 3)
            return
        end function i1
    end module testf2py
    

    In action:

    In [6]: import numpy as np
    
    In [7]: m = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
    
    In [8]: import testf2py
    
    In [9]: testf2py.testf2py.i1(m)
    Out[9]: 150.0
    

    The change is similar to the third option that I described in this answer: f2py: Specifying real precision in fortran when interfacing with python?