Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在带有F2PY的numpy数组上使用Fortran函数时,结果不一致_Python_Numpy_Fortran_F2py - Fatal编程技术网

Python 在带有F2PY的numpy数组上使用Fortran函数时,结果不一致

Python 在带有F2PY的numpy数组上使用Fortran函数时,结果不一致,python,numpy,fortran,f2py,Python,Numpy,Fortran,F2py,我试图了解F2PY是如何工作的。为此,我编写了一个简单的Fortran函数,该函数将数组作为输入,并返回数组元素的总和 我编写了相同函数的三个不同版本,我希望它们具有相同的结果: function rsum(arr) real, dimension(:), intent(in) :: arr real :: rsum rsum=sum(arr) end function rsum function rsum1(arr) real(8), dimension(:), intent(in) ::

我试图了解F2PY是如何工作的。为此,我编写了一个简单的Fortran函数,该函数将数组作为输入,并返回数组元素的总和

我编写了相同函数的三个不同版本,我希望它们具有相同的结果:

function rsum(arr)
real, dimension(:), intent(in) :: arr
real :: rsum
rsum=sum(arr)
end function rsum

function rsum1(arr)
real(8), dimension(:), intent(in) :: arr
real(8) :: rsum1
rsum1=sum(arr)
end function rsum1

function rsum2(arr) result(s)
real, dimension(:), intent(in) :: arr
real :: s
s=sum(arr)
end function rsum2

function rsum3(arr) result(s)
real(8), dimension(:), intent(in) :: arr
real(8) :: s
s=sum(arr)
end function rsum3
测试这些函数的python脚本如下所示:

from numpy import *
import ftest as f

a=array(range(3))

print(f.rsum(a))
print(f.rsum1(a))
print(f.rsum2(a))
print(f.rsum3(a))
但结果是:

3.0
0.0
3.0
3.0
除了
rsum1
中的
0.0
之外,所有结果都是正确的。我发现更奇怪的是,
rsum3
,我只需更改函数结果的名称(或者,至少,我认为我正在这样做),就可以完美地工作

我知道这与Fortran和numpy之间的类型转换有关,但我不明白问题是什么

PS:我最近才学会Fortran。

简短回答和解决方法 问题的根本原因与在函数中使用假定的形状伪参数(即
arr
)有关。Fortran要求此类函数具有显式接口@VladimirF对您的(相关?)问题给出了极好的回答,表明首选解决方案是将函数放在模块中。假设您的函数代码列表保存在名为
funcs.f90
的文件中,您只需将它们放入一个名为
mod_funcs.f90
的模块中,如下所示:

module mod_funcs
    implicit none
    contains
        include "funcs.f90"
end module mod_funcs
用F2PY
python-m numpy.F2PY-m ftest-c mod_funcs.f90
将python测试脚本中的import语句更新为
from ftest import mod_funcs as f
,然后运行它以获得预期结果:

3.0
3.0
3.0
3.0
较长的答案和解释 Fortran
函数
s被F2PY包装在
子例程
s中。为了以符合Fortran标准的方式支持假定形状数组,F2PY创建的子例程包装包含用户定义的具有假定形状伪参数的函数的
接口
s。使用F2PY包装时,您可以通过指定带有
--build dir
标志的生成目录来查看这些包装,例如:

python -m numpy.f2py --build-dir .\build -m ftest -c funcs.f90
查看为有问题的函数
rsum1
创建的包装器很有启发性(我正在从
ftest-f2pywrappers.f
中逐字复制F2PY的缩进):

请注意,由于,rsum1的
接口
意味着数据类型为
real
的函数,不是预期的
real(8)
,因此接口中存在数据类型不匹配!这解释了为什么带有显式
result
语句(
rsum3
)的看似相同的函数返回正确的结果。在原始示例中,其结果具有正确的数据类型。幸运的是,
rsum
具有正确的接口。如果将
rsum
的名称更改为例如
isum
,则其F2PY子例程包装器接口中的隐式数据键入规则将意味着它有一个
integer
结果,并且您将从(修改以反映名称从
fsum
更改为
isum
)python脚本中获得以下输出:

0.0
0.0
3.0
3.0
因此,在我看来,F2PY为具有假定形状伪参数的函数创建接口的方式似乎存在缺陷(可以通过将这些函数直接放入模块中,或者通过使用
result
显式声明函数的返回值来绕过)


为了完整起见,我使用的是
python3.6.3::Intel Corporation
,以及
NumPy 1.14.3
,以及
GNU-Fortran(GCC)8.2.0

如果你是新手,不要学习
real(8)
的坏习惯,人们从哪里学来的?它不在任何好的教科书中。
rsum1
rsum3
应该完全相同。但也许f2py解释了一个错误,我可以复制它。当我在从f2py调用的Fortran子例程中调用它们时,结果是正确的。但即使在Python中,报告的
f.*
函数的签名也是正确的。@VladimirF关于表示法real(8),有人教过我。为什么这么糟糕?另外,我不明白:在运行脚本时,您是否遇到了与我相同的错误?是的,我遇到了相同的错误。Real(8)是不可移植的,它不能用某些编译器编译。看到和
0.0
0.0
3.0
3.0