jameskermode / f90wrap Goto Github PK
View Code? Open in Web Editor NEWF90 to Python interface generator with derived type support
License: GNU Lesser General Public License v3.0
F90 to Python interface generator with derived type support
License: GNU Lesser General Public License v3.0
hi,
do you have any intend to support PY3?
Hai
...do not seem to be supported.
I mean here:
module mod1_api
implicit none
type typ1
integer :: n = 2
contains
procedure :: inc
end type
contains
subroutine inc(self)
class(typ1), intent(inout) :: self
t%n = t%n + 1
end subroutine
end module
e.g. of use in fortran:
program prog
use mod1_api
type(typ1) :: t
call t%inc()
print*, t%n
end program
Note it is a secondary issue (there seem to be more advantages not using this feature than otherwise in fortran...), so it would be only justified to work on that if this would require only minor work (e.g. in the wrapper, replace back class
with type
, remove the contains
part of the type and use information provided by procedure :: inc
or procedure :: inc => typ1_inc
to add methods to the corresponding python class...)
This would be quite handy on the python side though.
If a function uses pointer variables, the function is skipped, without warning.
Minimal example :
module module_calcul
contains
subroutine evaluer_valeur(x)
real,dimension(:,:),pointer :: x
return
end subroutine evaluer_valeur
end module module_calcul
I m trying to wrap a fortran code hsl_example.f90 to python using f90wrap (because I have some user defined types) and I run into problems with type mismatch.
When i run f90wrap -m hsl_example hsl_example.f90 i get a wrapper file f90wrap_hsl_example.f90 with some of the variable types different from than in hsl_example.f90, e.g. integer is converted to real.
For example, running f2py-f90wrap -c -m _hsl_example f90wrap_hsl_example.f90 results in the following error:
f90wrap_hsl_example.f90:590.45:
call find_max_match(m=m, n=n, ne=ne, ptr=ptr, row=row, rowset=rowset, &
1
Error: Type mismatch in argument 'ptr' at (1); passed REAL(4) to INTEGER(4)
f90wrap_hsl_example.f90:614.40:
call find_rect(m=m, n=n, ne=ne, ptr=ptr, col=col, marked=marked, &
1
Error: Type mismatch in argument 'ptr' at (1); passed REAL(4) to INTEGER(4)
f90wrap_hsl_example.f90:647.48:
call find_conn_comps(m=m, n=n, ne=ne, a_ptr=a_ptr, a_col=a_col, d_ptr=d_ptr
1
Error: Type mismatch in argument 'a_ptr' at (1); passed REAL(4) to INTEGER(4)
f90wrap_hsl_example.f90:680.48:
call find_conn_comp_sq(m=m, n=n, ne=ne, ptr=ptr, idx=idx, nhcols=nhcols, &
1
Error: Type mismatch in argument 'ptr' at (1); passed REAL(4) to INTEGER(4)
f90wrap_hsl_example.f90:590.45:
call find_max_match(m=m, n=n, ne=ne, ptr=ptr, row=row, rowset=rowset, &
1
Error: Type mismatch in argument 'ptr' at (1); passed REAL(4) to INTEGER(4)
f90wrap_hsl_example.f90:614.40:
call find_rect(m=m, n=n, ne=ne, ptr=ptr, col=col, marked=marked, &
1
Error: Type mismatch in argument 'ptr' at (1); passed REAL(4) to INTEGER(4)
f90wrap_hsl_example.f90:647.48:
call find_conn_comps(m=m, n=n, ne=ne, a_ptr=a_ptr, a_col=a_col, d_ptr=d_ptr
1
Error: Type mismatch in argument 'a_ptr' at (1); passed REAL(4) to INTEGER(4)
f90wrap_hsl_example.f90:680.48:
call find_conn_comp_sq(m=m, n=n, ne=ne, ptr=ptr, idx=idx, nhcols=nhcols, &
1
Error: Type mismatch in argument 'ptr' at (1); passed REAL(4) to INTEGER(4)
The original fortran file hsl_example.f90
is attached. Thanks.
Reported by Bob Fischer. OO-style Fortran extension derived types don't work. In this case, I have a Fortran derived type:
type :: DebugType
.....
end type DebugType
Then I extend it:
type, extends(DebugType) :: Debug_heat_eq
....
end type Debug_heat_eq
In the .py file that gets generated, the corresponding Python class Debug_Heat_Eq needs to extend the Python class Debugtype. Instead, it just extends f90wrap.runtime.FortranDerviedType, which messes things up
I am trying to get going with f90wrap
. On my system (Arch Linux 64 bit) the example mockderivetype
does not pass all its tests. I am running in a pip updated virtualenv (python 2.7). For reference, the traceback I get is:
File "f90wrap/examples/mockderivetype/test.py", line 30, in <module>
result = use_a_type.do_stuff(8)
TypeError: do_stuff() takes exactly 2 arguments (1 given)
As far as I understand the error, the arguments list in the Fortran sources contains both input and output variables, where intent(in/out)
specifies the nature of the specific arguments. For the case above see f90wrap/examples/mockderivetype/fwrap.f90 line 19. But the Python call also requires to pass on the output variable. From the generated mockdt.py
I get:
@staticmethod
def do_stuff(factor, out):
"""
do_stuff(factor, out)
Defined at fwrap.fpp lines 23-64
Parameters
----------
factor : float
out : float
This is the module which defines the type 'atype'
Here's a routine that does something
"""
_mockdt.f90wrap_do_stuff(factor=factor, out=out)
Is that the intended behaviour, or maybe I am missing something obvious here (I have experience with Python, but only some basic Fortran)?
The example recursive_type
does not compile.
Platform: macOS
Python 3.7.3
GNU Fortran (Homebrew GCC 8.2.0) 8.2.0
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
This is the relevant error message:
f90wrap_tree.f90:9:22:
type node_ptr_type
1
Error: Derived type definition of 'node_ptr_type' at (1) has already been defined
f90wrap_tree.f90:11:7:
end type node_ptr_type
1
Error: Expecting END SUBROUTINE statement at (1)
f90wrap_tree.f90:28:22:
type node_ptr_type
1
Error: Derived type definition of 'node_ptr_type' at (1) has already been defined
f90wrap_tree.f90:30:7:
end type node_ptr_type
1
Error: Expecting END SUBROUTINE statement at (1)
f90wrap_tree.f90:47:22:
type node_ptr_type
1
Error: Derived type definition of 'node_ptr_type' at (1) has already been defined
f90wrap_tree.f90:49:7:
end type node_ptr_type
1
Error: Expecting END SUBROUTINE statement at (1)
f90wrap_tree.f90:66:22:
type node_ptr_type
1
Error: Derived type definition of 'node_ptr_type' at (1) has already been defined
f90wrap_tree.f90:68:7:
end type node_ptr_type
1
Error: Expecting END SUBROUTINE statement at (1)
This is the generated f90wrap_tree.f90
with code cause the error:
! Module tree defined in file tree.fpp
subroutine f90wrap_node__get__left(this, f90wrap_left)
use tree, only: node
implicit none
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
integer, intent(in) :: this(2)
type(node_ptr_type) :: this_ptr
integer, intent(out) :: f90wrap_left(2)
type(node_ptr_type) :: left_ptr
this_ptr = transfer(this, this_ptr)
left_ptr%p => this_ptr%p%left
f90wrap_left = transfer(left_ptr,f90wrap_left)
end subroutine f90wrap_node__get__left
subroutine f90wrap_node__set__left(this, f90wrap_left)
use tree, only: node
implicit none
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
integer, intent(in) :: this(2)
type(node_ptr_type) :: this_ptr
integer, intent(in) :: f90wrap_left(2)
type(node_ptr_type) :: left_ptr
this_ptr = transfer(this, this_ptr)
left_ptr = transfer(f90wrap_left,left_ptr)
this_ptr%p%left = left_ptr%p
end subroutine f90wrap_node__set__left
subroutine f90wrap_node__get__right(this, f90wrap_right)
use tree, only: node
implicit none
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
integer, intent(in) :: this(2)
type(node_ptr_type) :: this_ptr
integer, intent(out) :: f90wrap_right(2)
type(node_ptr_type) :: right_ptr
this_ptr = transfer(this, this_ptr)
right_ptr%p => this_ptr%p%right
f90wrap_right = transfer(right_ptr,f90wrap_right)
end subroutine f90wrap_node__get__right
subroutine f90wrap_node__set__right(this, f90wrap_right)
use tree, only: node
implicit none
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
integer, intent(in) :: this(2)
type(node_ptr_type) :: this_ptr
integer, intent(in) :: f90wrap_right(2)
type(node_ptr_type) :: right_ptr
this_ptr = transfer(this, this_ptr)
right_ptr = transfer(f90wrap_right,right_ptr)
this_ptr%p%right = right_ptr%p
end subroutine f90wrap_node__set__right
subroutine f90wrap_treeallocate(root)
use tree, only: treeallocate, node
implicit none
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
type(node_ptr_type) :: root_ptr
integer, intent(out), dimension(2) :: root
allocate(root_ptr%p)
call treeallocate(root=root_ptr%p)
root = transfer(root_ptr, root)
end subroutine f90wrap_treeallocate
subroutine f90wrap_treedeallocate(root)
use tree, only: treedeallocate, node
implicit none
type node_ptr_type
type(node), pointer :: p => NULL()
end type node_ptr_type
type(node_ptr_type) :: root_ptr
integer, intent(in), dimension(2) :: root
root_ptr = transfer(root, root_ptr)
call treedeallocate(root=root_ptr%p)
deallocate(root_ptr%p)
end subroutine f90wrap_treedeallocate
! End of module tree defined in file tree.fpp
Nevermind - The problem is elsewhere. My bad.
Edit : The problem seems to be there after all...
Hi,
I have a code that compiled with f90warp version 0.1.0
but not with 0.1.4
I think the problem is coming from the creation _Xnpartclass_Array classes
In the f90 code I used allocatable array of structure.
and when creating the file f90warp*.f90
function with name like f90wrap_part_xn_part_array__array_getitem__items()
are created with dimension for the structure that are not defined
I understand this is not really clear, but this reflect my understanding of the problem
happy to provide more info
in the meantime, would that be possible to access later version of f90wrap through pip or conda?
Thanks
Ronan
With the following command lines, the module compiles, but can not be imported in python because "Symbol not found" for the functions inside the module :
f90wrap -v -m maxwell functions.f90
f2py3 -c -m _maxwell f90wrap*.f90
If I add *.o to the f2py3 command, it works with a minimal test case. However, with the complex fortran code I am trying to use, the commands
f90wrap -v -m maxwell functions.f90
f2py3 -c -m _maxwell f90wrap*.f90 *.o
the "import maxwell" command produces the error "Symbol not found: f90wrap_abort".
So i can have a link to my own functions or to the f90wrapper functions, but not both. What am i doing wrong ?
For example, the following doesn't work:
recursive &
subroutine sub(...)
Probably removing all "&" symbols all and joining into long lines before doing any parsing would be safer.
When instantiating data structures from Python (through f90wrap), the default definition of derived types is all in lower case in Windows (vs. upper case in Unix). Not a big deal, but if its a quick fix, could you please fix in a new update of f90wrap?
xyz = module containing definition of derived type(s)
when I do
print dir(xyz)
on Windows, I get
['class', 'delattr', 'dict', 'doc', 'format', 'getattribute', 'hash', 'init', 'metaclass', 'module', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref', '_arrays', '_dt_array_initialisers', '_objs', 'contour_prop_def', 'cross_section_def', 'material_type_def', 'rotor_info_def', 'skin_info_def', 'spar_info_def']
On Linux, the same command yields
['Contour_Prop_Def', 'Cross_Section_Def', 'Material_Type_Def', 'Rotor_Info_Def', 'Skin_Info_Def', 'Spar_Info_Def', 'class', 'delattr', 'dict', 'doc', 'format', 'getattribute', 'hash', 'init', 'metaclass', 'module', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref', '_arrays', '_dt_array_initialisers', '_objs']
Contour_Prop_Def vs. contour_prop_def
Cross_Section_Def vs. cross_section_def
Material_Type_Def vs. material_type_def
Rotor_Info_Def vs. rotor_info_def
Skin_Info_Def vs. skin_info_def
Spar_Info_Def vs. spar_info_def
Currently Fortran supports optional arguments before default arguments, see program below:
program test
call wrap(def = 2)
contains
subroutine wrap(opt, def)
implicit none
integer :: def
integer, optional :: opt
print *, 'present(opt) = ', present(opt)
print *, 'def = ', def
if (present(opt)) print *, 'opt = ', opt
end subroutine
end program test
This compiles and runs fine.
f90wrap also runs fine:
f90wrap -m test main.F90
But if I import the program:
$ python
>>> import test
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/theory/phukgm/Documents/test/test.py", line 5
def wrap(opt=None, def_):
^
SyntaxError: non-default argument follows default argument
>>>
Is it possible to add optional before default arguments support to this module?
Hi,
I have a Fortran routine with some input characters of type "characters" and some optional ouput array parameters. When the caller (in Python) passes one optional array, that array is filled correctly by the called subroutine. If the caller passes all optional arrays, they all return filled with the same values (which is wrong for all of them but one).
The same calling program in Fortran does not show this problem.
MODULE mvars
CONTAINS
SUBROUTINE vars(N, optCON, optT, optP, &
pco2_deriv, fco2_deriv )
IMPLICIT NONE
INTEGER, PARAMETER :: r4 = KIND(1.0)
! Input variables
!> number of records
INTEGER, INTENT(in) :: N
CHARACTER(6), INTENT(in) :: optCON
CHARACTER(7), INTENT(in) :: optT
CHARACTER(2), INTENT(in) :: optP
! Optional output variables:
REAL(kind=r4), OPTIONAL, INTENT(out), DIMENSION(6,N) :: pco2_deriv
REAL(kind=r4), OPTIONAL, INTENT(out), DIMENSION(6,N) :: fco2_deriv
! Local variables
INTEGER :: j
IF (PRESENT(pco2_deriv)) THEN
DO j=1,6
pco2_deriv(J,:) = REAL(N)+REAL(J)
END DO
ENDIF
IF (PRESENT(fco2_deriv)) THEN
DO j=1,6
fCO2_deriv(J,:) = REAL(N)+REAL(J)+1
END DO
ENDIF
RETURN
END SUBROUTINE vars
PROGRAM test_vars
USE mvars
IMPLICIT NONE
INTEGER, PARAMETER :: r4 = KIND(1.0)
REAL(kind=r4), DIMENSION(6,1) :: ph_deriv, pco2_deriv, fco2_deriv
call vars(1, optCON='mol/kg', optT='Tinsitu', optP='db', &
pco2_deriv=pco2_deriv)
write (,) "pco2_deriv[1,0]", pco2_deriv(2,1)
call vars(1, optCON='mol/kg', optT='Tinsitu', optP='db', &
pco2_deriv=pco2_deriv, fco2_deriv=fco2_deriv)
write (,) "pco2_deriv[1,0]", pco2_deriv(2,1)
STOP
It outputs:
pco2_deriv[1,0] 3.00000000
pco2_deriv[1,0] 3.00000000
Twice the same value = 3, which is correct.
mocsy_dnad_dir = "/home/jean-marie/Documents/DNAD/mocsy-bug"
import sys
import numpy as np
sys.path.append (mocsy_dnad_dir)
import mocsy
pco2_deriv = np.zeros((6,)).astype('f')
fco2_deriv = np.zeros((6,)).astype('f')
pco2_deriv = pco2_deriv.reshape ((6,1), order='F')
fco2_deriv = pco2_deriv.reshape ((6,1), order='F')
mocsy.mvars.vars(n=1,optcon="mol/kg",optt='Tinsitu',optp='db',
pco2_deriv=pco2_deriv )
print "pco2_deriv[1,0]", pco2_deriv[1,0]
mocsy.mvars.vars(n=1,optcon="mol/kg",optt='Tinsitu',optp='db',
pco2_deriv=pco2_deriv, fco2_deriv=fco2_deriv)
It outputs :
pco2_deriv[1,0] 3.0
pco2_deriv[1,0] 4.0
I have simplified my program as much as I could. I hope I have not made any mistake.
It looks like first optional output array is overwritten with values of the second optional array.
Best regards,
Jean-Marie
So I also tried python setup.py install from source, and ran into a "multiple_definition" error with Windows 10, Python 2.7 and mingw-w64.
F:/Programs/mingw/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-atonexit.o):atonexit.c:(.text+0xc0): multiple definition of atexit' F:\Programs\Python\libs/libmsvcr90.a(deoks01081.o):(.text+0x0): first defined here F:/Programs/mingw/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-mingw_helpers.o):mingw_helpers.c:(.text+0x0): multiple definition of
_decode_pointer'
F:\Programs\Python\libs/libmsvcr90.a(deoks00231.o):(.text+0x0): first defined here
F:/Programs/mingw/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-mingw_helpers.o):mingw_helpers.c:(.text+0x10): multiple definition of `_encode_pointer'
F:\Programs\Python\libs/libmsvcr90.a(deoks00241.o):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
error: Command "gcc -g -shared build\temp.win-amd64-2.7\Release\f90wrap\arraydatamodule.o build\temp.win-amd64-2.7\Release\programs\python\lib\site-packages\numpy\f2py\src\fortranobject.o -LF:\Programs\Python\libs -LF:\Programs\Python\PCbuild\amd64 -lpython27 -lmsvcr90 -o build\lib.win-amd64-2.7\f90wrap\arraydata.pyd" failed with exit status 1
Are your docs hosted somewhere? ISTM you have Sphinx docs ready to go (I'll clone this and check). I'm happy to show you how to host them on https://readthedocs.org/ if you'd like.
In test_set_derived_type(self) in derivedtypes/tests.py, the line
self.assert_(isinstance(dt, self.lib.datatypes.different_types))
passes for LibTestsPkg (for which lib = ExampleDerivedTypes_pkg
) but FAILS for LibTests (for which lib = ExampleDerivedTypes
).
type(dt)
gives
<class 'ExampleDerivedTypes_pkg.datatypes.different_types'>
for both LibTests and LibTestsPkg but self.lib.datatypes.different_types
can be either
<class 'ExampleDerivedTypes.Datatypes.different_types'>
<class 'ExampleDerivedTypes_pkg.datatypes.different_types'>
for LibTests and LibTestsPkg respectively, and which are not the same. Hence isinstance(dt, ...)
is False for LibTests and the assertion fails.
This is one of four failures running make test
, and seen in Travis build 169.5, with commit 04d81b5.
Currently, setup.py
uses setup
from numpy.distutils
:
from numpy.distutils.core import setup, Extension
from numpy.distutils.system_info import get_info
However, you can still rely on setuptools
in combination with numpy.distutils
(which is required for the compiled extensions). This happens when setuptools
is imported before numpy.distutils
:
import setuptools
from numpy.distutils.core import setup, Extension
from numpy.distutils.system_info import get_info
I am not aware of the details, but I found in an old mailing list entry [1] that numpy.distutils
figures out import setuptools
happened before its own import and therefore magic happens... The result is still the same, but now the packaging is just slightly cleaner and you can actually properly uninstall f90wrap with pip from a virtual environment. I think the latter is real bonus.
[1] http://comments.gmane.org/gmane.comp.python.f2py.user/707
Looks like abstract classes are not parsed properly. The code snippet
type, abstract :: shapes
integer :: shapetype = 0
end type
is parsed as type(abstract)
instead of an abstract type(shapes)
. However, since this is an abstract class, the f90wrap_shapes__get__shapetype(this, shapetype)
subroutine would probably have to be handled differently.
Hi James,
Great project, much potential to solve common annoyances when wrapping modern *f90 code. Both type-passing (f90wrap) and Exception catching are very useful features, actuallly all of f2py-f90wrap are useful !
When testing it out though, exception catching did not work as smoothly as hoped: just calling stop
did crash the fortran program, as with f2py. Calling f90wrap_error_abort
or even quippy_error_abort
(as grepped in f90wrap/patch_f2py
) did not help either ...
So what's your approach?
Thanks again.
Hello.
I'm working again on my fortran to python wrapping and come across the 32/64 bit problem again:
I initialize variables in python with numpy.zeros, which produces 64bit floats by default. When the array is of size 1, this works for fortran integer or real transparently. However, with size > 1 I have to explicitly use zeros(xxx, int32) (or float32) to be accepted by fortran. Note that I use in/out arrays, courtesy to the --default-to-inout flag. In the simple (in) mode, there is no problem but I don't recover any value ;)
Is this a f90-wrap internal conversion issue, or an f2py conversion issue ? Or maybe should we compile all fortran sources with some flag to enforce 64 bit fortran variables, to be compatible with their python counterparts ?
FORTRAN file
module module_test
INTEGER,PARAMETER :: n=12
contains
subroutine testf(x)
integer, dimension(n) :: x
x(2) = 4
end subroutine testf
subroutine testf2(x)
integer :: x
x = 4
end subroutine testf2
end module module_test
PYTHON file
import test3_python
from numpy import zeros, int32
b = zeros(1)
test3_python.module_test.testf2(b)
assert b == 4
a = zeros(12, int32)
test3_python.module_test.testf(a)
assert all(a == [0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
MAKE file
test3 : clean
gfortran -c -O3 -fPIC test3.f90
f90wrap --default-to-inout -m test3_python test3.f90
f2py-f90wrap -c -m _test3_python f90wrap_* *.o
python test3.py
clean :
rm -rf *.o *.mod *.so *python.py f90wrap* ./build
When wrapping a procedure which has a BIND(C, NAME='XXX')
attribute, the "bind, c, name and XXX" are put in the arguments list of the generated procedure.
Hello,
I have a problem running f90wrap on both examples included in the package. As documented, I tried to run make
for the examples, but the test fail with an error inside pywrapgen.py
:
File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 468, in write_repr self.write(r"ret = ['<{}>".format(node.name) + r"{\n']") ValueError: zero length field name in format
I reverted to a version before the commit of May 9, 2015 by rpfische, and could build the examples; the example2
ran successfully, but there is still another issue with mockderivetype
example that I try to understand now.
FYI, here is the full log of make:
(f90wrap_test3)yvesc@tethys->tethys:/home/yvesc/test/languages/python/f90wrap_install/f90wrap/examples/mockderivetype> make gfortran -x f95-cpp-input -fPIC -c leveltwomod.f90 -o leveltwomod.o gfortran -x f95-cpp-input -fPIC -c define.f90 -o define.o gfortran -x f95-cpp-input -fPIC -c fwrap.f90 -o fwrap.o ar src libsrc.a leveltwomod.o define.o fwrap.o gfortran -E -x f95-cpp-input -fPIC leveltwomod.f90 -o leveltwomod.fpp gfortran -E -x f95-cpp-input -fPIC define.f90 -o define.fpp gfortran -E -x f95-cpp-input -fPIC fwrap.f90 -o fwrap.fpp f90wrap -m mockdt leveltwomod.fpp define.fpp fwrap.fpp -k kind_map -v Kind map read from file "'kind_map'" : (also saved to .f2py_f2cmap) {'complex': {'': 'complex_float', '8': 'complex_double', 'dp': 'complex_double'}, 'integer': {'': 'int', '8': 'long_long', 'dp': 'long_long'}, 'real': {'': 'float', '8': 'double', 'dp': 'double'}} Constructors: ('initialise_ptr', 'initialise', 'allocate') Destructors: ('finalise', 'deallocate') Short names for derived types read from file "None" {} String lengths read from file "None": {} Initialisation lines for derived types read from file "None": {} Argument name map: {} Size of Fortran derived type pointers is 2 bytes. Parsing Fortran source files ['leveltwomod.fpp', 'define.fpp', 'fwrap.fpp'] ... DEBUG:root:processing file leveltwomod.fpp INFO:root:parser reading type leveltwo DEBUG:root: type leveltwo DEBUG:root: module leveltwomod DEBUG:root:processing file define.fpp INFO:root:parser reading type atype DEBUG:root: type atype INFO:root:parser reading type unused_type DEBUG:root: type unused_type DEBUG:root: module subroutine use_set_vars DEBUG:root: module function return_a_type_func DEBUG:root: module subroutine return_a_type_sub DEBUG:root: module define_a_type DEBUG:root: subroutine top_level INFO:root:parser reading type horrible_type DEBUG:root: type horrible_type DEBUG:root: module horrible DEBUG:root:processing file fwrap.fpp DEBUG:root: module subroutine do_stuff DEBUG:root: module subroutine not_used DEBUG:root: module use_a_type done parsing source. DEBUG:root:type leveltwo defined in module leveltwomod DEBUG:root:type atype defined in module define_a_type DEBUG:root:type unused_type defined in module define_a_type DEBUG:root:type horrible_type defined in module horrible Derived types detected in Fortran source files: {'atype': Type(name=atype), 'horrible_type': Type(name=horrible_type), 'leveltwo': Type(name=leveltwo), 'type(atype)': Type(name=atype), 'type(horrible_type)': Type(name=horrible_type), 'type(leveltwo)': Type(name=leveltwo), 'type(unused_type)': Type(name=unused_type), 'unused_type': Type(name=unused_type)} DEBUG:root:marking public symbol leveltwo DEBUG:root:marking public symbol rl DEBUG:root:marking public symbol atype DEBUG:root:marking public symbol bool DEBUG:root:marking public symbol integ DEBUG:root:marking public symbol rl DEBUG:root:marking public symbol vec DEBUG:root:marking public symbol dtype DEBUG:root:marking public symbol unused_type DEBUG:root:marking public symbol a_set_real DEBUG:root:marking public symbol a_set_bool DEBUG:root:marking public symbol use_set_vars DEBUG:root:marking public symbol return_a_type_func DEBUG:root:marking public symbol return_a_type_sub DEBUG:root:marking public symbol horrible_type DEBUG:root:marking public symbol x DEBUG:root:marking public symbol a_real DEBUG:root:marking public symbol p DEBUG:root:marking public symbol p_array DEBUG:root:marking public symbol vector DEBUG:root:marking public symbol do_stuff DEBUG:root:marking public symbol not_used DEBUG:root:visiting Module(name=leveltwomod) DEBUG:root:visiting Type(name=leveltwo) DEBUG:root:visiting Module(name=define_a_type) DEBUG:root:visiting Type(name=atype) DEBUG:root:visiting Type(name=unused_type) DEBUG:root:visiting Module(name=horrible) DEBUG:root:visiting Type(name=horrible_type) DEBUG:root:visiting Module(name=use_a_type) INFO:root:adding missing constructor for leveltwo INFO:root:adding missing constructor for atype INFO:root:adding missing constructor for unused_type INFO:root:adding missing constructor for horrible_type INFO:root:adding missing destructor for leveltwo INFO:root:adding missing destructor for atype INFO:root:adding missing destructor for unused_type INFO:root:adding missing destructor for horrible_type Reading .f2py_f2cmap ... Warning: redefinition of {'real':{'':'float'->'float'}} Mapping "real(kind=)" to "float" Warning: redefinition of {'real':{'8':'double'->'double'}} Mapping "real(kind=8)" to "double" Mapping "real(kind=dp)" to "double" Warning: redefinition of {'integer':{'':'int'->'int'}} Mapping "integer(kind=)" to "int" Warning: redefinition of {'integer':{'8':'long_long'->'long_long'}} Mapping "integer(kind=8)" to "long_long" Mapping "integer(kind=dp)" to "long_long" Warning: redefinition of {'complex':{'':'complex_float'->'complex_float'}} Mapping "complex(kind=)" to "complex_float" Warning: redefinition of {'complex':{'8':'complex_float'->'complex_double'}} Mapping "complex(kind=8)" to "complex_double" Mapping "complex(kind=dp)" to "complex_double" Succesfully applied user defined changes from .f2py_f2cmap DEBUG:root:allocating arg "ret_a" in return_a_type_func DEBUG:root:allocating arg "this" in leveltwo_initialise DEBUG:root:deallocating arg "this" in leveltwo_finalise DEBUG:root:allocating arg "this" in atype_initialise DEBUG:root:deallocating arg "this" in atype_finalise DEBUG:root:allocating arg "this" in unused_type_initialise DEBUG:root:deallocating arg "this" in unused_type_finalise DEBUG:root:allocating arg "this" in horrible_type_initialise DEBUG:root:deallocating arg "this" in horrible_type_finalise INFO:root:PythonWrapperGenerator visiting module leveltwomod INFO:root:PythonWrapperGenerator visiting type leveltwo INFO:root:PythonWrapperGenerator visiting routine leveltwo_initialise INFO:root:PythonWrapperGenerator visiting routine leveltwo_finalise Traceback (most recent call last): File "/home/yvesc/test/languages/python/f90wrap_test3/bin/f90wrap", line 244, in main init_file=args.init_file).visit(py_tree) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 445, in visit result = visitor(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 168, in visit_Root self.generic_visit(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 453, in generic_visit self.visit(item) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 445, in visit result = visitor(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 204, in visit_Module self.generic_visit(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 453, in generic_visit self.visit(item) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 445, in visit result = visitor(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 407, in visit_Type self.write_repr(node, properties) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 468, in write_repr self.write(r"ret = ['<{}>".format(node.name) + r"{\n']") ValueError: zero length field name in format f90wrap: ValueError('zero length field name in format',) for help use --help Traceback (most recent call last): File "/home/yvesc/test/languages/python/f90wrap_test3/bin/f90wrap", line 264, in sys.exit(main()) File "/home/yvesc/test/languages/python/f90wrap_test3/bin/f90wrap", line 244, in main init_file=args.init_file).visit(py_tree) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 445, in visit result = visitor(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 168, in visit_Root self.generic_visit(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 453, in generic_visit self.visit(item) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 445, in visit result = visitor(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 204, in visit_Module self.generic_visit(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 453, in generic_visit self.visit(item) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/fortran.py", line 445, in visit result = visitor(node) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 407, in visit_Type self.write_repr(node, properties) File "/bira-iasb/home/yvesc/test/languages/python/f90wrap_test/lib/python2.6/site-packages/f90wrap/pywrapgen.py", line 468, in write_repr self.write(r"ret = ['<{}>".format(node.name) + r"{\n']") ValueError: zero length field name in format make: *** [_mockdt.so] Error 1
I have installed f90wrap by cloning the repository from GitHub and running the setup.py script in anaconda prompt. The f90wrap can already be imported in python as module however the f90wrap can not be found if I call it directly in the anaconda prompt (or terminal). error message below:
'f90wrap' is not recognized as an internal or external command, operable program or batch file.
can not find the usable f90wrap.exe file to be added as environment variable
Hi James. As it is, I am still struggling to use some fortran code in Python ...
It seems that implicit arguments are skipped in the f90wrap files, instead of following the fortran implicit declaration rules (which f2py seems to know). Is there something I am missing, or do I have to explicitly declare all subroutine arguments ?
I have created a python wrapper for a LARGE fortran library of code using f2py. One of the problem I have is to call one of the subroutines function(cell) which takes in a cell as input and then update the input cell at the end of the subroutine [intent(inout)]. what is correct way of calling this kind of subroutine? Is the equivalent of the cell in python a dictionary? its a unitcell that contains many attributes (properties) of an object. this unitcell is later exported as an hdf5 data set
Fortran source code:
subroutine function_name(cell)
use ...
IMPLICIT NONE
type(unitcell),intent(inout) :: cell
cell%name1=a
cell%name2=b
...
end subroutine function_name
cell : Unitcell
Repro:
Windows 10
conda activate my_env
installing mingw following these instructions
pip install f90wrap
ValueError: path '/Users/jameskermode/.pyenv/versions/3.6.6/lib/python3.6/site-packages/numpy/f2py/src/fortranobject.c' cannot be absolute
Installing from source with python setup.py develop
seems to work fine however.
Wrapping of interfaces was implemented recently by relying on the wrapped code to raise exceptions when the wrong one is being used and continue to the next one. Currently the f2py-generated code is not raising the TypeError
and hence the first function that is tried can succeed and RuntimeError is found when the wrong type is encountered later while using the values in fortran.
The solution would be to check the number of args and types in the python code that calls the interface and decide based on that.
I'm running into the following error while trying to wrap this fortran module
DEBUG:root: module subroutine fida_weights_los
DEBUG:root: module subroutine checking npa_weights
DEBUG:root: module subroutine npa_weights
DEBUG:root: module libfida
Traceback (most recent call last):
File "/home/lstagner/anaconda3/bin/f90wrap", line 187, in main
parse_tree = fparse.read_files(args.files)
File "/home/lstagner/anaconda3/lib/python3.5/site-packages/f90wrap/parser.py", line 1316, in read_files
check = check_program(cline, file)
File "/home/lstagner/anaconda3/lib/python3.5/site-packages/f90wrap/parser.py", line 369, in check_program
out.uses.append(check[0])
AttributeError: 'Program' object has no attribute 'uses'
Should the Program
object have a uses
atttribute?
First, thank you for f90wrap.
I'd like to get a callback mechanism to capture Fortran messages and display them in a jupyter cell output (stdout is captured by a python console but SFAIK no easy way with jupyter).
I note f90wrap
has a 'callback' CLI option but I am not sure how to use it. Say I have in cbfunc.f90 :
module cbfunc
implicit none
public
contains
subroutine f1()
print *, "in f1, calling f2 twice.."
call f2()
call f2()
return
end
subroutine f2()
!f2py intent(callback, hide) fpy
external fpy
print *, "in f2, calling f2py.."
call fpy()
return
end
end module
and using
F90_FILES="cbfunc.f90"
OBJ_FILES="cbfunc.o"
MODULE_NAME=CBF
rm f90wrap_*.f90 *.o
rm _${MODULE_NAME}*
rm ${MODULE_NAME}.py
rm -rf __pycache__
f90wrap -m ${MODULE_NAME} $F90_FILES --callback fpy
gfortran -c $F90_FILES -fPIC
f2py-f90wrap -c -m _${MODULE_NAME} f90wrap_*.f90 $OBJ_FILES
Then in python import CBF
fails with ImportError: /xxx/yyy/ff/_CBF.cpython-37m-x86_64-linux-gnu.so: undefined symbol: fpy_
The callback mechanism works if using only f2py
i.e. f2py -c -m ${MODULE_NAME} cbfunc.f90
and in python:
import CBF
dir(CBF.cbfunc)
CBF.cbfunc.f2()
def f(): print("python f")
# CBF.cbfunc.fpy = f #nope ?
CBF.fpy = f
CBF.cbfunc.f2()
CBF.cbfunc.f1()
I'll see if I can find a fix or workaround.
Module constants that have documentation in Fortran should have special doc comments added to Python wrappers
https://stackoverflow.com/questions/20227051/how-to-document-a-module-constant-in-python
I'm in the process of wrapping a Fortran code that uses a derived type within the same the derived type, ie. it is recursive. This causes problems when the wrapper is written as there are two definitions of the same type.
I've written a simple example that replicates the issue.
f90wrap_test.tar.gz
This should give the error:
gfortran:f90: f90wrap_tree_test.f90
f90wrap_tree_test.f90:11.22:
type node_ptr_type
1
Error: Derived type definition of 'node_ptr_type' at (1) has already been defined
I've found that it can be fixed by modifying the line in the _write_scalar_wrapper routine in the f90wrapgen.py file. Replace:
if el.type.startswith('type'):
self.write_type_lines(el.type)
with
if el.type.startswith('type') and (ft.strip_type(t.name) != ft.strip_type(el.type)):
self.write_type_lines(el.type)
There may be other places where this would be an issue, but this seemed to fix the scalar case for me at least.
Hi,
I test a subroutine with double precision as input, but the python module gives a comment "unknown" for the double precision. The module still works, but the comment is not right.
f90 code:
module test_double_precision
implicit none
contains
subroutine set_double_precision(dp,rl)
implicit none
double precision, intent(in) :: dp
real, intent(in) :: rl
write(*,*) "The double precision number is: ",dp
write(*,*) "The real number is: ",rl
end subroutine
end module
makefile:
#=======================================================================
# define the compiler names and flags
#=======================================================================
CC = gcc
F90 = gfortran
FPP = gfortran -E
F90FLAGS = -x f95-cpp-input -fPIC
CFLAGS = -fPIC
all: mod
double_precision.o:
${F90} ${F90FLAGS} -c double_precision.f90
mod: double_precision.o
f90wrap -m double_precision double_precision.f90 -k kind_map
f2py-f90wrap -c -m _double_precision f90wrap_double_precision.f90 double_precision.o
clean:
-rm double_precision.py
-rm f90wrap*.f90 *.o *.pyc *.mod
-rm _double_precision.so
kind_map:
{
'double precision': { '' : 'double'},
'real': { '' : 'float',
'4' : 'float',
'isp' : 'float',
'8' : 'double',
'dp' : 'double',
'idp' : 'double'}
}
(edited to add syntax highlighting)
Hello:
I am facing a problem. The f90wrap is not making wrapper for the subroutines that has interfaced another subroutine. For example, I have tried odeint from the following pdf
https://homepage.univie.ac.at/mario.barbatti/papers/NRF/bookf90pdf/chap16f9.pdf
SUBROUTINE derivs(x,y,dydx)
USE nrtype
IMPLICIT NONE
REAL(SP), INTENT(IN) :: x
REAL(SP), DIMENSION(:), INTENT(IN) :: y
REAL(SP), DIMENSION(:), INTENT(OUT) :: dydx
END SUBROUTINE derivs
derivs is interfaced here. If I keep it, it does not produce the wrapper. If I write external derivs, it treats derivs as a float and I get problem in executing f2py-f90wrap step.
Do you have any suggestions ?
This type of routines are not provided in examples.
Thanks in advance,
Dhiraj
With a derived type containing a variable called type, f90wrap produces __get__type_bn and __set__type_bn.
f2py3 then has the error : 'type_bn' at (1) is not a member of the structure.
Minimal example f90 file :
module module_structure
type type_face
integer :: type
end type type_face
end module module_structure
Hi,
I try to use f90wrap with windows7 64bit, intel fortran and anaconda2(python2.7), but failed. The fortran file is example.f90 under the examples\interface directory. So, why? very thanks!
G:\Source\Python\collections\f90wrap\f90wrap-master\examples\interface>python "C
:\Anaconda2\Scripts\f90wrap" -v -m example example.f90
Kind map (also saved to .f2py_f2cmap)
{}
Constructors:
('initialise_ptr', 'initialise', 'allocate')
Destructors:
('finalise', 'deallocate')
Short names for derived types:
{}
String lengths:
{}
Initialisation lines for derived types
{}
Python module name remapping
{}
Class names remapping
{}
Argument name map:
{}
Size of Fortran derived type pointers is 2 bytes.
Parsing Fortran source files ['example.f90'] ...
DEBUG:root:processing file example.f90
INFO:root:marking module class_example as default private
DEBUG:root: interface return_example
INFO:root:parser reading type Example
DEBUG:root: type Example
DEBUG:root: module function checking return_example_first
DEBUG:root: implicit type of "return_example_first" inferred from its nam
e as "real"
DEBUG:root: module function return_example_first
DEBUG:root: module function checking return_example_second
DEBUG:root: implicit type of "return_example_second" inferred from its na
me as "real"
DEBUG:root: module function return_example_second
DEBUG:root: module function checking return_example_third
DEBUG:root: implicit type of "return_example_third" inferred from its nam
e as "real"
DEBUG:root: module function return_example_third
DEBUG:root: module class_example
done parsing source.
DEBUG:root:type example defined in module class_example
Derived types detected in Fortran source files:
{'example': Type(name=example), 'type(example)': Type(name=example)}
Class name mapping:
{'example': 'Example', 'type(example)': 'Example'}
Modules for each type:
{'class_example': 'class_example'}
Traceback (most recent call last):
File "c:\anaconda2\lib\site-packages\f90wrap-0.1.4-py2.7-win-amd64.egg\EGG-INF
O\scripts\f90wrap", line 298, in main
remove_optional_arguments)
TypeError: transform_to_generic_wrapper() takes exactly 12 arguments (14 given)
f90wrap: TypeError('transform_to_generic_wrapper() takes exactly 12 arguments (1
4 given)',)
for help use --help
Traceback (most recent call last):
File "C:\Anaconda2\Scripts\f90wrap", line 4, in
import('pkg_resources').run_script('f90wrap==0.1.4', 'f90wrap')
File "C:\Anaconda2\lib\site-packages\pkg_resources_init_.py", line 738, in
run_script
self.require(requires)[0].run_script(script_name, ns)
File "C:\Anaconda2\lib\site-packages\pkg_resources_init_.py", line 1499, in
run_script
exec(code, namespace, namespace)
File "c:\anaconda2\lib\site-packages\f90wrap-0.1.4-py2.7-win-amd64.egg\EGG-INF
O\scripts\f90wrap", line 341, in
sys.exit(main())
File "c:\anaconda2\lib\site-packages\f90wrap-0.1.4-py2.7-win-amd64.egg\EGG-INF
O\scripts\f90wrap", line 298, in main
remove_optional_arguments)
TypeError: transform_to_generic_wrapper() takes exactly 12 arguments (14 given)
f90wrap converts intent(out) arrays to intent(in, out). This was a deliberate design decision to allow allocatable and automatic arrays to be used. It’s hard in general to work out what size array needs to be allocated, so I decided that relying on the the user to pre-allocate from Python seemed the safest solution to reduce the chance of memory leaks.
It would be quite useful to have an option where the behaviour of f90wrap can be told to follow that of f2py
, i.e., returning intent(out)
arrays. The main interest is for consistency with the default for standard functions in python.
File "/Users/chaoyizhu/anaconda/lib/python3.6/site-packages/f90wrap/pywrapgen.py", line 456, in visit_Interface
proc_name += proc.mod_name.title() + '.'
AttributeError: 'Prototype' object has no attribute 'mod_name'
f90wrap: AttributeError("'Prototype' object has no attribute 'mod_name'",)
I am using f90wrap for a library of fortran source code. I got the above error message. what are the things to check in order to fix this error?
First off, allow me to compliment you on this nice python library and f2py extension. After some work, I got it working for my library, but I did run into a few issues:
Interfaced functions of a f90 module are translated to static methods in the auto generate python class, however in the function list for the overloaded call loop, the function names are not prefixed by Class_name, i.e.
[Class_name.method1(a,b), Class_name.method1(a,b,c), ... ]
Another issue I found was that asterisks inserted after a type are not handled correctly, and instead the parameter containing the asterisk is ignored completely. For example,
subroutine foo(a,b)
real*8, intent(in) :: a
integer :: b
print *, a*b
end subroutine foo
is parsed by f90wrap as
subroutine f90wrap_foo(b)
integer :: b
....
end subroutine
If I instead use real(kind=8), f90wrap will include the parameter, but will translate it to the wrong type. In the f90wrap_ file it will be listed as real(4).
Coming back to f90wrap. Renewed congrats.
I really like the convenience --move-methods
options, but apparently it assumes that all methods with the type as first argument come from the same module as the type in question. Here a case where it will cause an error:
debug_move_methods.f90
:
module basemod
!! base module, where the type is defined
implicit none
type param_t
integer :: a
end type
contains
subroutine increment_a(p)
type(param_t), intent(inout) :: p
p%a = p%a + 1
end subroutine
end module
module extmod
!! extension module, adding non essential functionality
implicit none
use basemod, only: param_t
contains
subroutine print_a(p)
type(param_t), intent(in) :: p
print*, p%a
end subroutine
end module
The standard procedure works like a charm:
gfortran -c debug_move_methods.f90 -fPIC
f90wrap -m debug debug_move_methods.f90
f2py-f90wrap -c -m _debug debug_move_methods.o f90wrap_debug_move_methods.f90
But the --move-methods
variant fails:
f90wrap -m debug debug_move_methods.f90 --move-methods
f2py-f90wrap -c -m _debug debug_move_methods.o f90wrap_debug_move_methods.f90 # FAILS
because of unified (wrong) module use in f90wrap_debug_move_methods.f90
use basemod, only: param_t, print_a
Whereas print_a
is defined in the extension module extmod
, not in basemod
.
I am not saying my design is the best ever (maybe the use of new submodule feature might achieve something similar -- but is it supported by f90wrap?), but I assume this bug should easy to fix? Thanks in any case.
Hi,
First of all: what a great idea! I have a collaborator who can only work with Fortran, and we have been re-inventing the proverbial wheel for all the simple (in Python) things that are tedious in Fortran.
I was trying f90wrap and noticed that a simple elemental function poses a problem.
Example:
module elemental_module
implicit none
contains
elemental real(kind=8) function sinc(x)
real(kind=8), intent(in) :: x
if(abs(x).gt.1d-5) then
sinc = sin(x)/x
else
sinc = 1.0d0
endif
return
end function sinc
end module elemental_module
I have used the following commands to build it
f90wrap -m elmod elemental_module.f90 -k kind_map -v
f2py-f90wrap --fcompiler=gfortran -I. --build-dir . -c -m _elmod elemental_module.f90 f90wrap*.f90
The problem is, I believe in f90wrap_elemental_module.f90 as it uses elemental as a type for ret_sinc
Cheers
Piotr
It would be handy to use f90wrap from distutils directly, as is now possible with f2py.
Any plan in this direction?
Never checked the internals, it must not be too complicated...
It is about subclassing the distutils.extension.Extension
class, or/and provide a new setup script, or, like cython
does, defining a build_ext
function to pass to setup's cmd_class
.
An example here: https://github.com/perrette/python-fortran-cpp-template/blob/master/setup.py.
I will take a look at some point in 2016...
Casting to type(c_ptr)
is functionally equivalent to using ``transfer()` as we do currently, but the latter is more error prone so we should switch.
See notes here: http://www.fortran90.org/src/best-practices.html#v-using-type-c-ptr-pointer
replace pointer with intent(inout). in addition to that, add a directive for the f2py
!f2py intent(in,out) :: var (is this modification to the Fortran source code needed in the f90wrap?)
does it seem reasonable?
The type definition:
TYPE queued_node
INTEGER :: node_index
TYPE(queued_node),POINTER:: next_node
END TYPE queued_node
produces a f90wrap_*f90 file that produces an error when trying to compile with f2py-f90wrap.
The error is as follows:
Error: Derived type definition of ‘queued_node_ptr_type’ at (1) has already been defined
And is down to the queued_node_ptr_type being defined twice in two of the subroutines:
use tort_mod, only: queued_node
implicit none
type queued_node_ptr_type
type(queued_node), pointer :: p => NULL()
end type queued_node_ptr_type
type queued_node_ptr_type
type(queued_node), pointer :: p => NULL()
end type queued_node_ptr_type
integer, intent(in) :: this(2)
type(queued_node_ptr_type) :: this_ptr
integer, intent(out) :: f90wrap_next_node(2)
type(queued_node_ptr_type) :: next_node_ptr
this_ptr = transfer(this, this_ptr)
next_node_ptr%p => this_ptr%p%next_node
f90wrap_next_node = transfer(next_node_ptr,f90wrap_next_node)
end subroutine f90wrap_queued_node__get__next_node
subroutine f90wrap_queued_node__set__next_node(this, f90wrap_next_node)
use tort_mod, only: queued_node
implicit none
type queued_node_ptr_type
type(queued_node), pointer :: p => NULL()
end type queued_node_ptr_type
type queued_node_ptr_type
type(queued_node), pointer :: p => NULL()
end type queued_node_ptr_type
integer, intent(in) :: this(2)
type(queued_node_ptr_type) :: this_ptr
integer, intent(in) :: f90wrap_next_node(2)
type(queued_node_ptr_type) :: next_node_ptr
this_ptr = transfer(this, this_ptr)
next_node_ptr = transfer(f90wrap_next_node,next_node_ptr)
this_ptr%p%next_node = next_node_ptr%p
end subroutine f90wrap_queued_node__set__next_node
If you remove one of these in each subroutine it compiles fine.
Does anyone know how to avoid this issue?
Thanks!
If a function uses an array of some derived type, the function is simply skipped by f90wrap, and no warning is issued.
Minimal example :
module module_calcul
type type_ptmes
integer :: y
end type type_ptmes
contains
subroutine recup_point(x)
type(type_ptmes) :: x(2)
return
end subroutine recup_point
end module module_calcul
Hi James : )
The --only and --skip are buggy:
The "kept_modules" variable is defined in the file "f90wrap.py" as a set, to ensure a non-redundant list along the various appends.
But sets only work for hashable object. So the "Module" class needs a "hash()" function for your code to work as intended. All seems to work by adding the following function to the "Module" class, in the "fortran.py" file:
# Required for the Module object to be hashable so one can create sets of Modules
# So this function should return a unique imprint of the object.
# I guess the filename + the module name should be unique enough ?
# Also, hash requires an integer, so we convert the characters to integers with the
# same number of digits to ensure one-to-one conversion.
# This is maybe unnecessarily long ?
def __hash__(self):
return int(''.join(str(ord(x)).zfill(3) for x in self.filename + self.name))
I felt the is not worth a complete pull request, especially since I am tinkering with other files to handle arrays of derived types.
I have a fortran module as:
`module gen
use ISO_C_BINDING
use parm
real (type_r8), allocatable :: xg(:)
end module gen`
And f2py-f90wrap produces the following python class/def:
` class Gen(f90wrap.runtime.FortranModule):
Module gen
Defined at ../src/gen.f lines 1-1607
@property
def xg(self):
Element xg ftype=real (type_r8) pytype=float
Defined at ../src/gen.f line 150
array_ndim, array_type, array_shape, array_handle = \
_min3p.f90wrap_gen__array__xg(f90wrap.runtime.empty_handle)
if array_handle in self._arrays:
xg = self._arrays[array_handle]
else:
xg = f90wrap.runtime.get_array(f90wrap.runtime.sizeof_fortran_t,
f90wrap.runtime.empty_handle,
_min3p.f90wrap_gen__array__xg)
self._arrays[array_handle] = xg
return xg
@xg.setter
def xg(self, xg):
self.xg[...] = xg`
It looks fine, however when I ask my python main
to print it, it gives something like:
1.96938765049 -1.32611814684e+23 1.97448968887 -1.86322722022e+26 1.97959172726 -2.61938127341e+29 1.98469376564 -3.57632946796e+32 1.98979580402 -5.15415206355e+35 1.99489784241 4.20389539297e-45
That looks like a right value followed by a wrong value... Does anyone know what is going on there?
Cheers!
Consider the simple fortran function:
function array(n)
implicit none
integer, intent(in) :: n
integer :: array(n)
integer :: i
do i = 1,n
array(i) = i
enddo
end function
The f90wrap wrapper yields two parmeters n and n0 for some reason (does not dare to guess the output size, I suppose this is related to issue #33).
subroutine f90wrap_array(ret_array, n, n0)
implicit none
external array
integer array
integer, intent(out), dimension(n0) :: ret_array
integer, intent(in) :: n
integer :: n0
ret_array = array(n)
end subroutine f90wrap_array
but the corresponding python wrapper is inconsistent (import and doc removed for brevety), lacking the n0 parameter.
def array(n):
array = _testfunction.f90wrap_array(n=n)
return array
So far my workaround is to use sed to fix the python wrapper:
sed -i "s/_testfunction.f90wrap_array(n=n)/_testfunction.f90wrap_array(n=n, n0=n)/" *.py
But something less ad-hoc would be preferable of course.
Note that in this example the fortran wrapper fails (segmentation fault), but it works well when used in a module.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.