Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F2PY - Access module parameter from subroutine

I cannot get f2py to reference a parameter from a module in a separate subroutine where it is used to defined an input array dimension. I.e. the paramter is defeind in a module:

! File: testmod.f90
MODULE testmod
INTEGER, PARAMETER :: dimsize = 20
END MODULE testmod

and the parameter dimsize needs to be referenced in a subroutine (NOT contained in the module) in another file, which will be the entry point for my python module:

! File testsub.f90
SUBROUTINE testsub(arg)
USE testmod
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

I compile like this:

f2py -m testmod  -h testmod.pyf testsub.f90
pgf90 -g -Mbounds -Mchkptr -c -fPIC testmod.f90 -o testmod.o
pgf90 -g -Mbounds -Mchkptr -c -fPIC testsub.f90 -o testsub.o
f2py -c testmod.pyf testmod.o testsub.o

but get this error:

testmodmodule.c: In function 'f2py_rout_testmod_testsub':
testmodmodule.c:180: error: 'dimsize' undeclared (first use in this function)

I have tried modifying testsub.g90 to include the following directive, as suggested ni other posts:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, parameter :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

but to no avail. I need to keep the subroutine separate from the module.

How can I get f2py to correctly resolve the variable dimsize?

TIA

like image 662
ccbunney Avatar asked Nov 14 '13 17:11

ccbunney


2 Answers

It's been a long time since this question has gotten any activity, but I figured out the problem so I thought I'd post it for anyone else who has this issue. The problem is that while the Fortran code is perfectly valid, the C wrapper generated by F2PY doesn't know what dimsize is when it checks that arrays are the correct size (within the C wrapper, it's encapsulated in some kind of module structure).

Just change this code:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, parameter :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

to this:

SUBROUTINE testsub(arg)
USE testmod
!f2py integer, intent(aux) :: dimsize
REAL, INTENT(IN) :: arg(dimsize)
END SUBROUTINE testsub

This will "Define auxiliary C variable in F2PY generated wrapper function". As the Scipy docs say, this is "Useful to save parameter values so that they can be accessed in initialization expression of other variables".

I haven't tested this with your code, but I've tested it with a similar situation I was having.

like image 196
Jeremy McGibbon Avatar answered Nov 14 '22 04:11

Jeremy McGibbon


Although I've not tested it, I think you nearly have it with your original code. We do something similar for some of our code, but with gfortran.

You shouldn't need to f2py the testmod.f90 file. You should just compile it to an object file just like you would if this were normal Fortran:

pgf90 -g -Mbounds -Mchkptr -c -fPIC testmod.f90 -o testmod.o

Then you should be able to compile your testsub.f90 into a python-usable module with:

f2py --fcompiler=pgf90 --f90flags="-g -Mbounds -Mchkptr" -c testsub.f90 -m testsub testmod.o

That should build a testsub.so, or equivalent, letting you import testsub and then testsub.testsub(my_arg) in python.

like image 31
cm2 Avatar answered Nov 14 '22 02:11

cm2