用F2PY对numpy数组使用Fortran函数时结果不一致

2024-10-02 08:22:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我想了解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脚本如下:

^{pr2}$

但结果是:

^{3}$

所有结果都是正确的,除了rsum1中的一个是{}。我发现更奇怪的是rsum3,其中我只更改了函数结果的名称(或者,至少,我认为我正在这样做),工作非常完美!在

我知道这与Fortran和numpy之间的类型转换有关,但我不明白问题出在哪里。在

附言:我最近才学过Fortran。在


Tags: 函数infunction数组realendsumarr
1条回答
网友
1楼 · 发布于 2024-10-02 08:22:09

简短回答和解决方法

问题的根本原因与函数中使用假定形状伪参数(即arr)有关。Fortran要求这些函数具有显式接口。@弗拉基米尔夫给了你一个很好的答案(相关?)问题here正是关于这一点,这表明首选的解决方案是将函数放入模块中。假设您的函数代码列表保存在一个名为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,然后运行它以获得预期的结果:

^{pr2}$

更长的答案和解释

Fortranfunction由F2PY包装在subroutines中。为了以符合Fortran标准的方式支持假定形状数组,F2PY创建的子例程包装器包含interfaces,用于用户定义的函数和假定的形状伪参数。当用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 rulesrsum1interface意味着一个具有real数据类型的函数,不是预期的real(8),因此接口中存在数据类型不匹配的情况!这解释了为什么带有显式result语句(rsum3)的函数在原始示例中返回正确的结果,其结果具有正确的数据类型。幸运的是,在命名函数时,rsum有正确的接口。如果您将rsum的名称更改为例如isum,那么在其F2PY子例程包装器接口中的隐式数据类型规则将意味着它有一个integer结果,并且您将从python脚本(经过修改以反映名称从fsum更改为isum)中得到以下输出:

0.0
0.0
3.0
3.0

因此,在我看来,F2PY如何为带有假定形状伪参数的函数创建接口(可以通过直接将这些函数放入模块中,或通过使用result显式声明函数的返回值来绕过这个问题)。在

为了完整起见,我使用了Python 3.6.3 :: Intel Corporation,与NumPy 1.14.3和{}。在

相关问题 更多 >

    热门问题