f2py,返回数组的Python函数(向量值函数) [英] f2py, Python function that returns an array (vector-valued function)
问题描述
在下面的Python中,由func
返回的数组中包含五个函数,我必须对其进行集成.该代码调用使用f2py
生成的外部Fortran模块:
In the following Python I have five functions contained in the array returned by func
which I have to integrate. The code calls an external Fortran module generated using f2py
:
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例程是:
The Fortran routine is:
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)
中集成了第一个功能.
查看打印结果:
The problem is that Fortran is only integrating the first function in func(x)
.
See the print result:
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]
一种工作方式是修改func(x)
以返回给定值
在函数数组中的位置:
One way to workarond that is to modify func(x)
to return the value of a given
position in the array of functions:
def func(x,i):
return np.array([x**2, x**3, cos(x), sin(x), exp(x)])[i-1]
然后更改Fortran例程以使用两个参数来调用该函数:
And then change the Fortran routine to call the function with two parameters:
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次以上.
But here func
is called 5 times more than necessary (in the real case func
has above 300 functions, so it will be called 300 times more than necessary).
- 有人知道更好的解决方案以使Fortran识别
func(x)
返回的所有数组吗?换句话说,使Fortran将fx1 = f(x1)
构建为具有5个与func(x)
中的功能相对应的元素的数组.
- Does anyone know a better solution to make Fortran recognizes all the array returned by
func(x)
? In other words, make Fortran buildfx1 = f(x1)
as an array with 5 elements corresponding to the functions infunc(x)
.
OBS:我正在使用f2py -c --compiler=mingw32 -m trapzdv trapzdv.f90
OBS: I am compiling using f2py -c --compiler=mingw32 -m trapzdv trapzdv.f90
推荐答案
不幸的是,您无法将数组从python函数返回到Fortran中.为此,您将需要一个子例程(这意味着使用call
语句调用它),而f2py
不允许您这样做.
Unfortunately, you cannot return the array from the python function into Fortran. You would need a subroutine for that (meaning it is called with the call
statement), and this is something that f2py
does not let you do.
在Fortran 90中,您可以创建返回数组的函数,但这又不是f2py
可以做的,尤其是因为您的函数不是Fortran函数.
In Fortran 90 you can create functions that return arrays, but again this is not something that f2py
can do, especially since your function is not a Fortran function.
您唯一的选择是使用循环解决方法,或者重新设计您希望python和Fortran交互的方式.
Your only option is to use your looping workaround, or a redesign of how you want python and Fortran to interact.
这篇关于f2py,返回数组的Python函数(向量值函数)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!