使用f2py时,fortran模块中的功能范围与为fortran程序编译时的功能范围不同吗?
作者:互联网
我的问题是,使用f2py进行编译时,模块内定义的函数无法识别某些模块变量.如果声明了传递给函数的参数的变量类型(例如,描述实数或维元素类型的变量),则会引发错误.使用gfortran编译时没有出现此错误.有什么区别?用f2py编译时如何纠正这些错误?
我的示例文件moddata.f90包含以下代码:
module mod
implicit none
integer, parameter :: dp = selected_real_kind(15)
integer, parameter :: nelem = 3
real(kind=dp), dimension(nelem) :: b
parameter (b=(/3,1,2/))
contains
function foo(x,y) result(z)
! dp, nelem are defined in module above
real(kind=dp), intent(in) :: x !scalar
integer, dimension(nelem), intent(in) :: y
! local variable
real(kind=dp) :: z
z = sum(b*y*x)
end function foo
end module mod
我编译
f2py -c -m moddata moddata.f90
我得到这些错误:
y_Dims[0]=(nelem);
^
1 warning and 1 error generated.reduce to a constant expression
如果我在整数,dimension(nelem),intent(in):: y之前重新定义整数,参数:: nelem = 3并重新编译,则得到
real(kind=dp) foof2pywrap
1
Error: Parameter 'dp' at (1) has not been declared or is a variable, which does not reduce to a constant expression
每个real(kind = dp)声明都有相同的错误,并且
foof2pywrap = foo(x, y)
1
Warning: Possible change of value in conversion from REAL(8) to REAL(4) at (1)
因此,我必须通过函数中的参数:: dp = selected_real_kind(15)通过整数重新定义dp.然后工作.
使用fortran包装器编译此模块时,没有得到这些错误.我想知道为什么函数中的nelem和dp不能正确地用f2py作用域?
解决方法:
也许我错了,但是我认为f2py无法处理包含Fortran 90功能的模块.如果将代码转换为
function foo(x,y) result(z)
integer, parameter :: dp = selected_real_kind(15)
real(kind=dp), intent(in) :: x
integer, parameter :: nelem = 3
integer, dimension(3), parameter : = (/3, 1, 2/)
integer, dimension(nelem), intent(in) :: y
real(kind=dp) :: z
z = sum(b*y*x)
end function
并像以前一样编译它,它的工作原理是:
>>> x = 1.0000000000
>>> y = [2, 3, 4]
>>> moddata.foo(x,y)
17.0
编辑
this question on SO的答案表明f2py不了解如何将Fortran函数转换为python函数.所以我将函数foo更改为子例程foo2,然后编译为f2py moddata.f90 -m moddata并得到了输出
Reading fortran codes...
Reading file 'moddata.f90' (format:free)
Post-processing...
Block: moddata
Block: moddata
In: :moddata:moddata.f90:moddata
get_parameters: got "invalid syntax (<string>, line 1)" on '(/3, 1, 2/)'
Block: foo2
Post-processing (stage 2)...
Block: moddata
Block: unknown_interface
Block: moddata
Block: foo2
Building modules...
Building module "moddata"...
Constructing F90 module support for "moddata"...
Variables: nelem b dp
Constructing wrapper function "moddata.foo2"...
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /home/jdwood/Documents/Physics/Fortran/tests/f2py/.f2py_f2cmap file).
z = foo2(x,y)
Wrote C/API module "moddata" to file "./moddatamodule.c"
Fortran 90 wrappers are saved to "./moddata-f2pywrappers2.f90"
因此,看起来确实好像失去了双精度,所以在建议编辑一个名为.f2py_f2cmap的文件之后,我这样做了,并且在使用dp时没有出现错误.但是,它仍然为nelem提供了一个错误,因此我可以想到两种解决方案:
>坚持使用3代替nelem
>将nelem和b作为变量传递给子例程
我还发现在使用parameter(b =(/3.d0,1.d0,2.d0 /))行时,我收到一条警告,提示已读取
analyzeline: Failed to evaluate '/3.e0+1j*( 1.e0+1j*( 2.e0/)'. Ignoring: invalid syntax (<string>, line 1)
我不确定该怎么做.但是,当我使用x = 1.0和y =(/ 3,6,2 /)(都使用python并在Fortran程序中使用模块)时,确实得到18作为答案.
简而言之,在使用f2py时,请完全避免使用函数.
标签:fortran90,f2py,python,gfortran 来源: https://codeday.me/bug/20191030/1967990.html