gpt4 book ai didi

python - 使用 F2PY 在 numpy 数组上使用 Fortran 函数时结果不一致

转载 作者:行者123 更新时间:2023-11-28 18:23:58 25 4
gpt4 key购买 nike

我正在尝试了解 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

所有结果都是正确的,除了 rsum10.0。我发现更奇怪的是 rsum3,我只是更改了函数结果的名称(或者,至少,我认为我正在这样做),它工作得很好!

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

PS:最近才学Fortran。

最佳答案

简答和解决方法

问题的根本原因与在您的函数中使用假定形状伪参数(即 arr)有关。 Fortran 要求此类函数具有显式接口(interface)。 @VladimirF 对您的(相关?)问题给出了很好的答案 here仅此而已,表明首选解决方案是将功能放在模块中。假设包含函数的代码 list 保存在名为 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 code> 然后运行它得到预期的结果:

3.0
3.0
3.0
3.0

较长的答案和解释

F2PY 将 Fortran function 包装在 subroutine 中。为了以符合 Fortran 标准的方式支持假设形状数组,F2PY 创建的子例程包装器包含用于用户定义函数的 interface,这些函数具有假设形状虚拟参数。在使用 F2PY 包装时,您可以通过使用 --build-dir 标志指定构建目录来查看这些包装器,例如像这样:

python -m numpy.f2py --build-dir .\build -m ftest -c funcs.f90

查看为有问题的函数创建的包装器 rsum1 正在揭示(我正在逐字复制 ftest-f2pywrappers.f保持 F2PY 的缩进):

subroutine f2pywraprsum1 (rsum1f2pywrap, arr, f2py_arr_d0)
integer f2py_arr_d0
real(8) arr(f2py_arr_d0)
real(8) rsum1f2pywrap
interface
function rsum1(arr)
real(8), dimension(:),intent(in) :: arr
end function rsum1
end interface
rsum1f2pywrap = rsum1(arr)
end

请注意,由于 implicit data typing rules , rsum1interface 意味着一个具有real 数据类型的函数,不是 real(8) 符合预期 - 因此接口(interface)中存在数据类型不匹配!这解释了为什么在您的原始示例中具有显式 result 语句 (rsum3) 的看似相同的函数返回正确的结果,其结果具有正确的数据类型。幸运的是你的函数命名,rsum 有正确的接口(interface)。如果您将 rsum 的名称更改为例如isum,其 F2PY 子程序包装器接口(interface)中的隐式数据类型化规则将暗示它有一个 integer 结果,您将从您的(修改以反射(reflect)名称从 fsum 更改为 isum) python 脚本:

0.0
0.0
3.0
3.0

所以在我看来,F2PY 如何为具有假定形状伪参数的函数创建接口(interface)(可以通过将这些函数直接放入模块或通过显式声明使用 result 的函数)。

为了完整起见,我使用的是 Python 3.6.3::Intel CorporationNumPy 1.14.3GNU Fortran (GCC) 8.2.0

关于python - 使用 F2PY 在 numpy 数组上使用 Fortran 函数时结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42791532/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com