I have a problem getting an old module to work with latest NumPy and f2py version.
Namely, I have this small code to do some vertical averaging:
module mod_spatialaverage
contains
subroutine spatialaverage(depdata,
& vardata,depval,varout,sum_a,sum_b,nz,nx,ny)
implicit none
real, intent(in) :: depdata(nz,ny,nx)
real, intent(in) :: vardata(nz,ny,nx)
integer, intent(in) :: nz,nx,ny
real, intent(in) :: depval
real, intent(out) :: varout(ny,nx)
real, intent(out) :: sum_a(ny,nx),sum_b(ny,nx)
integer ii,jj,ilev
real missing_value,dz
! ----------------------------------
varout=0.0;
missing_value=-1.e3
! ----------------------------------
do ii = 1,nx
do jj= 1,ny
! if it is landpoint:
if (depdata(1,jj,ii).le.missing_value) cycle
! --------------------------------
dz=abs(0.0-depdata(1,jj,ii));
sum_a(jj,ii)=sum_a(jj,ii)+vardata(1,jj,ii)*dz
sum_b(jj,ii)=sum_b(jj,ii)+dz;
! --------------------------------
do ilev=2,nz
dz=abs(depdata(ilev,jj,ii)-depdata(ilev-1,jj,ii));
if (depdata(ilev,jj,ii).gt.depval) then
sum_a(jj,ii)=sum_a(jj,ii)+vardata(ilev,jj,ii)*dz
sum_b(jj,ii)=sum_b(jj,ii)+dz;
endif
if (depdata(ilev,jj,ii).lt.depval.and.
& depdata(ilev-1,jj,ii).gt.depval) then
dz=abs(depval-depdata(ilev-1,jj,ii))
sum_a(jj,ii)=sum_a(jj,ii)+vardata(ilev,jj,ii)*dz
sum_b(jj,ii)=sum_b(jj,ii)+dz;
endif
enddo
! --------------------------------
enddo
enddo
varout=sum_a/sum_b;
! ==================================
return
end subroutine spatialaverage
end module mod_spatialaverage
! ==================================================
and Makefile:
bin=f2py
#bin=/storage/software/Python-2.7.6/bin/f2py
# --------------------------------
all: mod_spatialaverage
mod_spatialaverage: mod_spatialaverage.f90
$(bin) -c -m $@ $<
but during the compilation I get an error:
> p/tmp7boek982/src.linux-x86_64-3.11/mod_spatialaverage-f2pywrappers2.f90:7:36:
>
> 7 | use mod_spatialaverage, only : unknown_subroutine
> | 1 Error: Symbol ‘unknown_subroutine’ referenced at (1) not found in module
> ‘mod_spatialaverage’
The code and compilation was working with older f2py
(some time ago).
How can I get the compilation and module to work with current versions of f2py? Why is there all of the sudden unknown_subroutine
?
The compiler I am using is gfortran, NumPy/f2py is version 1.26.4.
The solution is to convert your source file to a proper free-form Fortran source by adding the &
characters at the appropriate lines
subroutine spatialaverage(depdata, &
& vardata,depval,varout,sum_a,sum_b,nz,nx,ny)
if (depdata(ilev,jj,ii).lt.depval.and. &
& depdata(ilev-1,jj,ii).gt.depval) then
The parser for fixed form probably does not work well with modules and similar features as everyone uses them rather in free-form (.f90).
It is probably a bug in f2py
and you may try to report it, but there is no guarantee anybody will actually want to deal with this kind of problem.The Numpy community recently rather tries to avoid dealing with more Fortran.
Compilation:
> f2py -c -m mod_spatialaverage mod_spatialaverage.f90
Test:
> ipython
Python 3.11.11 (main, Dec 06 2024, 17:06:18) [GCC]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.31.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import mod_spatialaverage
In [2]: ?? mod_spatialaverage.mod_spatialaverage.spatialaverage??
Signature: mod_spatialaverage.mod_spatialaverage.spatialaverage(*args, **kwargs)
Type: fortran
String form: <fortran function spatialaverage>
Docstring:
varout,sum_a,sum_b = spatialaverage(depdata,vardata,depval,[nz,nx,ny])
Wrapper for ``spatialaverage``.
Parameters
----------
depdata : input rank-3 array('f') with bounds (nz,ny,nx)
vardata : input rank-3 array('f') with bounds (nz,ny,nx)
depval : input float
Other Parameters
----------------
nz : input int, optional
Default: shape(depdata, 0)
nx : input int, optional
Default: shape(depdata, 2)
ny : input int, optional
Default: shape(depdata, 1)
Returns
-------
varout : rank-2 array('f') with bounds (ny,nx)
sum_a : rank-2 array('f') with bounds (ny,nx)
sum_b : rank-2 array('f') with bounds (ny,nx)