在下面的Python中,我有五個函數包含在由func
返回的數組中,這是我必須集成的。該代碼調用使用f2py
產生的外部的Fortran模塊:f2py,Python函數,返回一個數組(向量值函數)
import numpy as np
from numpy import cos, sin , exp
from trapzdv import trapzdv
def func(x):
return np.array([x**2, x**3, cos(x), sin(x), exp(x)])
if __name__ == '__main__':
xs = np.linspace(0.,20.,100)
ans = trapzdv(func,xs,5)
print 'from Fortran:', ans
print 'exact:', np.array([20**3/3., 20**4/4., sin(20.), -cos(20.), exp(20.)])
Fortran例程是:
subroutine trapzdv(f,xs,nf,nxs,result)
integer :: I
double precision :: x1,x2
integer, intent(in) :: nf, nxs
double precision, dimension(nf) :: fx1,fx2
double precision, intent(in), dimension(nxs) :: xs
double precision, intent(out), dimension(nf) :: result
external :: f
result = 0.0
do I = 2,nxs
x1 = xs(I-1)
x2 = xs(I)
fx1 = f(x1)
fx2 = f(x2)
result = result + (fx1+fx2)*(x2-x1)/2
enddo
return
end
的問題是,Fortran的僅在func(x)
集成第一功能。 參見印刷結果:
from Fortran: [ 2666.80270721 2666.80270721 2666.80270721 2666.80270721 2666.80270721]
exact: [ 2.66666667e+03 4.00000000e+04 9.12945251e-01 -4.08082062e-01 4.85165195e+08]
一種方法workarond即修改func(x)
返回給定 位置的值的函數的陣列中:
def func(x,i):
return np.array([x**2, x**3, cos(x), sin(x), exp(x)])[i-1]
,然後改變Fortran例程調用函數有兩個參數:
subroutine trapzdv(f,xs,nf,nxs,result)
integer :: I
double precision :: x1,x2,fx1,fx2
integer, intent(in) :: nf, nxs
double precision, intent(in), dimension(nxs) :: xs
double precision, intent(out), dimension(nf) :: result
external :: f
result = 0.0
do I = 2,nxs
x1 = xs(I-1)
x2 = xs(I)
do J = 1,nf
fx1 = f(x1,J)
fx2 = f(x2,J)
result(J) = result(J) + (fx1+fx2)*(x2-x1)/2
enddo
enddo
return
end
其中一期工程:
from Fortran: [ 2.66680271e+03 4.00040812e+04 9.09838195e-01 5.89903440e-01 4.86814128e+08]
exact: [ 2.66666667e+03 4.00000000e+04 9.12945251e-01 -4.08082062e-01 4.85165195e+08]
但這裏func
被稱爲超過必要的5倍(在現實情況下func
具有高於300層的功能,所以它會被稱爲多300倍必要)。
- 有沒有人知道一個更好的解決方案,使Fortran識別出
func(x)
返回的所有數組?換句話說,將Fortran構建爲fx1 = f(x1)
作爲一個數組,其中有5個元素對應於func(x)
中的函數。
OBS:我使用f2py -c --compiler=mingw32 -m trapzdv trapzdv.f90