带有F2PY的可调节Fortran阵列

时间:2015-08-18 01:00:57

标签: python numpy fortran f2py

我一直试图包装一些Fortran库并增强一些例程,以允许它们使用numpy输入和输出数组而不是单个输入和输出。在大多数情况下,我已经成功并且包含了一些简单的例程。唯一的问题是我的f_prog例程。

subroutine f_prog(mu,x,y,m)
    integer :: m, i
    !f2py intent(hide) :: m
    DOUBLE PRECISION, intent(in) :: mu
    DOUBLE PRECISION, dimension(m , 6), intent(in) :: x
    DOUBLE PRECISION, dimension(m , 6), intent(out) :: y
    DOUBLE PRECISION, dimension( 6 ) :: y_temp(6)
    do i=1,m
        call prog(mu,x(i,1:6),y_temp)   
        y(i,1:6)=y_temp(1:6)
    enddo   
end subroutine

当使用输入 f_prog(1,([1,2,3,4,5,6])运行f_prog时,我收到错误:

    In [21]: clout(gm[0],sc_mars[0])
    1-th dimension must be 6 but got 0 (not defined).
    ---------------------------------------------------------------------------
    error                                    Traceback (most recent call last)
    <ipython-input-21-1614a809900e> in <module>()
    ----> 1 clout(gm[0],sc_mars[0])

    error: failed in converting 2nd argument `x' of pythage_new.f_clout to C/Fortran array

但是当我使用 f_prog(1,([1,2,3,4,5,6],[1,2,3,4,5,6])运行它时我接受了我的预期输出。请注意,所有数组输入都使用Python中的Numpy库,而不是Python的标准列表结构。

该错误让我相信当F2PY只是一行时,它不会尊重数组的维度。

感谢任何建议,谢谢!

正如Warren在下面提到的,也可以这样嵌套数组:

f_prog( 1 , [[1,2,3,4,5,6]] )

虽然,我正在尝试创建一个标准库,因此强制用户每次想要使用此例程时在变量周围添加括号都不太实用。

2 个答案:

答案 0 :(得分:1)

在表达式f_prog( 1 , ([1,2,3,4,5,6]) )中,[1,2,3,4,5,6]周围的括号无效(就像(1)1相同),所以论证是一维序列。为了使它看起来像一个二维序列,您可以添加一个尾随逗号,以便它是一个包含列表的元组:f_prog(1, ([1,2,3,4,5,6],))。或者使用嵌套列表:f_prog(1, [[1,2,3,4,5,6]])

更新:问题(正如我现在所理解的)是f2py生成的包装器对于参数的形状比你想要的更为挑剔。 Fortran文件说参数是2-d,因此f2py坚持要求用户使用2-d numpy数组调用该函数。这很容易做到,但是如果函数的用户也可以传入一维数组,并且让代码将其视为包含单行的二维数组,那就太好了。

可能的解决方法是在f2py函数周围创建一个瘦包装器。在包装器中,在将数组参数传递给f2py函数之前调用atleast_2d。大概是这样的:

def func(mu, x):
    x = np.atleast_2d(x)
    y = f_prog(mu, x)  # Call the function that was generated by f2py.
    return y

答案 1 :(得分:1)

我不确定我的问题。特别是你的意思是可调节或可分配或动态大小的阵列。代码中没有任何数组的动态更改。 F2py子程序只接受一些数组,它的出现方式并不重要,它只需要在第二维中有正确的大小6.

您还说您正在使用NumPy数组,但代码中没有numpy数组。如果你想使用numpy数组,那么只需创建一个:

- (void)logoutButtonClick:(id)sender
{
    NSLog(@"Logout Clicked");
    Login *loginview = [[Login alloc]init];
    [self.navigationController pushViewController:loginview animated:YES];
}

如果你需要输入一个矢量,你应该将它重新整形为一个2D数组,因为子程序需要一个二维数组

#create a Numpy array in Fortran ordering
arr = numpy.zeros([3,6], order='F')

#fill in some values
arr[:,:] = numpy.random.rand(3,6)

#run your f2py code
f_prog.f_prog(1, arr)