从 python 向 Fortran 传递变量会导致错误的值
Passing variables to Fortran from python causes wrong values
基于此,我想使用Python 和Fortran 子例程来操作Fortran 模块的变量。请看下面的例子:
vars.f90
module vars
implicit none
real(kind=selected_real_kind(p=15)) :: fk(10)
end module vars
sub.f90
subroutine sub
use vars
print *, "sub: fk(1) = ", fk(1)
print *, "adding 1 to fk(1)"
fk(1) = fk(1) + 1
print *, "fk(1) = ", fk(1)
end
mytest.f90
include "vars.f90"
include "sub.f90"
使用以下命令和 gfortran 完成编译:
f2py -c -m mytest mytest.f90
最后,这是在 Python 3.6.5 控制台中重现问题的测试用例:
>>> import mytest
>>> mytest.vars.fk[1]
0.0
>>> mytest.vars.fk[1]=1.5000
>>> mytest.vars.fk[1]
1.5
>>> mytest.sub()
sub: fk(1) = 0.12500000000000000
adding 1 to fk(1)
fk(1) = 1.1250000000000000
>>> mytest.vars.fk[1]
1.890625
>>>
以我的观点,fk(1)最终应该是2.5。但不幸的是,尽管通过 python 控制台直接访问变量显示了正确的值,但 Fortran 错误地读取了子例程中的变量。修改变量后,python 控制台也显示错误的数字。
对resolve/reason这种行为有什么建议或建议吗?感谢您的帮助!谢谢!
P.S.: 首先我认为这取决于 Python 和 Fortran 处理数组的方式不同(Python 从索引 0 开始,Fortran 从索引 1 开始),但是这不是错误。 mytest.vars.fk[0]调用子程序后不修改(初始值0.0)。
代码有两个问题:
索引问题,您已经注意到了。您仍然需要在Python中访问fk[0]
以获得所需的行为。
使用selected_real_kind(p=15)
进行种类规范。参见 FAQ of F2PY and this related SO answer.
目前,f2py 将您的 varibale 视为默认实数变量(此处为 32 位)而不是双精度。您可以通过创建文件 .f2py_f2cmap
(在当前工作目录中)来修复它,其内容为:
{'real':{'selected_real_kind(p=15)': 'double'}}
那将 select "double" 作为参数的相应 C 类型。不幸的是,F2PY 无法检测现代 Fortran 类型。
我将其标记为 f2py: Specifying real precision in fortran when interfacing with python? 的副本,但这里也存在索引问题。看看别人怎么看。
基于此
vars.f90
module vars
implicit none
real(kind=selected_real_kind(p=15)) :: fk(10)
end module vars
sub.f90
subroutine sub
use vars
print *, "sub: fk(1) = ", fk(1)
print *, "adding 1 to fk(1)"
fk(1) = fk(1) + 1
print *, "fk(1) = ", fk(1)
end
mytest.f90
include "vars.f90"
include "sub.f90"
使用以下命令和 gfortran 完成编译:
f2py -c -m mytest mytest.f90
最后,这是在 Python 3.6.5 控制台中重现问题的测试用例:
>>> import mytest
>>> mytest.vars.fk[1]
0.0
>>> mytest.vars.fk[1]=1.5000
>>> mytest.vars.fk[1]
1.5
>>> mytest.sub()
sub: fk(1) = 0.12500000000000000
adding 1 to fk(1)
fk(1) = 1.1250000000000000
>>> mytest.vars.fk[1]
1.890625
>>>
以我的观点,fk(1)最终应该是2.5。但不幸的是,尽管通过 python 控制台直接访问变量显示了正确的值,但 Fortran 错误地读取了子例程中的变量。修改变量后,python 控制台也显示错误的数字。
对resolve/reason这种行为有什么建议或建议吗?感谢您的帮助!谢谢!
P.S.: 首先我认为这取决于 Python 和 Fortran 处理数组的方式不同(Python 从索引 0 开始,Fortran 从索引 1 开始),但是这不是错误。 mytest.vars.fk[0]调用子程序后不修改(初始值0.0)。
代码有两个问题:
索引问题,您已经注意到了。您仍然需要在Python中访问
fk[0]
以获得所需的行为。使用
selected_real_kind(p=15)
进行种类规范。参见 FAQ of F2PY and this related SO answer.
目前,f2py 将您的 varibale 视为默认实数变量(此处为 32 位)而不是双精度。您可以通过创建文件 .f2py_f2cmap
(在当前工作目录中)来修复它,其内容为:
{'real':{'selected_real_kind(p=15)': 'double'}}
那将 select "double" 作为参数的相应 C 类型。不幸的是,F2PY 无法检测现代 Fortran 类型。
我将其标记为 f2py: Specifying real precision in fortran when interfacing with python? 的副本,但这里也存在索引问题。看看别人怎么看。