从python将变量传递给Fortran会导致错误的值

时间:2018-11-05 09:35:43

标签: python fortran f2py

基于此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]。

1 个答案:

答案 0 :(得分:3)

代码有两个问题:

  1. 您已注意到索引编制问题。您仍然还需要在Python中访问fk[0]才能获得所需的行为。

  2. 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?的副本,但是这里也存在索引问题。让我们看看别人的想法。