[英]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
請注意,由於隱式數據類型規則 , rsum1
的interface
意味着具有real
數據類型的函數, 而不是預期的real(8)
- 因此接口中存在數據類型不匹配! 這解釋了為什么具有顯式result
語句( rsum3
)的看似相同的函數在原始示例中返回正確的結果,其結果具有正確的數據類型。 通過命名您的函數, rsum
具有正確的接口。 如果將rsum
的名稱更改為例如isum
,則其F2PY子例程包裝器界面中的隱式數據類型規則將暗示它具有integer
結果,並且您將從中獲得以下輸出(已修改以反映從fsum
到isum
的名稱更改) )python腳本:
0.0
0.0
3.0
3.0
所以對我來說似乎F2PY如何為具有假定形狀偽參數的函數創建接口(可以通過將這些函數直接放入模塊中,或通過使用result
顯式聲明函數的返回值來繞過) )。
為了完整Python 3.6.3 :: Intel Corporation
,我使用的是Python 3.6.3 :: Intel Corporation
, NumPy 1.14.3
和GNU Fortran (GCC) 8.2.0
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.