基于此minimal example,我想使用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控制台也会显示错误的数字。
是否有解决此现象的建议或提议?感谢您的帮助!谢谢!
P.S .:首先,我认为这取决于Python和Fortran以不同的方式处理数组的方式(Python从索引0开始,而Fortran从索引1开始),但这不是错误。调用子例程(初始值为0.0)后,不会修改mytest.vars.fk [0]。
答案 0 :(得分:3)
代码有两个问题:
您已注意到索引编制问题。您仍然还需要在Python中访问fk[0]
才能获得所需的行为。
将selected_real_kind(p=15)
用于种类说明。请参阅FAQ of F2PY和与此相关的SO answer。
当前,f2py将您的变量视为默认的实变量(此处为32位),而不是双精度。您可以通过创建一个包含以下内容的文件.f2py_f2cmap
(在当前工作目录中)来解决此问题:
{'real':{'selected_real_kind(p=15)': 'double'}}
,它将为您的参数选择“ double”作为相应的C类型。不幸的是,F2PY无法检测现代Fortran类型。
我将其标记为f2py: Specifying real precision in fortran when interfacing with python?的副本,但是这里也存在索引问题。让我们看看别人的想法。