簡體   English   中英

使用F2PY在numpy數組上使用Fortran函數時的結果不一致

[英]Inconsistent result when using Fortran function on numpy array with 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) :: 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 function由F2PY包裝在subroutine 為了以符合Fortran標准的方式支持假定形狀數組,F2PY創建的子例程包裝器包含用於具有假定形狀偽參數的用戶定義函數的interface 您可以通過使用F2PY包裝時使用--build-dir標志指定構建目錄來查看這些包裝器,例如:

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

看看為有問題的函數rsum1創建的包裝器是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

請注意,由於隱式數據類型規則rsum1interface意味着具有real數據類型的函數, 而不是預期的real(8) - 因此接口中存在數據類型不匹配! 這解釋了為什么具有顯式result語句( rsum3 )的看似相同的函數在原始示例中返回正確的結果,其結果具有正確的數據類型。 通過命名您的函數, rsum具有正確的接口。 如果將rsum的名稱更改為例如isum ,則其F2PY子例程包裝器界面中的隱式數據類型規則將暗示它具有integer結果,並且您將從中獲得以下輸出(已修改以反映從fsumisum的名稱更改) )python腳本:

0.0
0.0
3.0
3.0

所以對我來說似乎F2PY如何為具有假定形狀偽參數的函數創建接口(可以通過將這些函數直接放入模塊中,或通過使用result顯式聲明函數的返回值來繞過) )。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM