使用f2py中模块的可分配数组

2024-04-20 12:08:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我对f2py中的可分配数组有问题。在下面的代码中(存储在mymod.f90)中,我创建了两个模块vars和{}:

  • vars存储并分配数组b
  • worker包含从vars处理此数组的子例程。在

第一个worker-子例程向b添加一个标量。这和预期的一样。问题在于下一个例程应该向数组b添加匹配的第一维向量。实现的子例程add_vector2起作用,但需要传递输入vector的维度。在

我需要的是一个只有向量作为参数的子例程,比如注释掉的子例程add_vector1。但是,这并不是用f2py编译的(而是用gfortran编译的)。在

代码如下:

! =======================================
! MODULE TO STORE AND INTIALIZE VARIABLES
! =======================================
MODULE VARS
  IMPLICIT NONE
  SAVE
  INTEGER :: n1, n2
  DOUBLEPRECISION, ALLOCATABLE:: b(:,:)
CONTAINS

  SUBROUTINE ALLOC(n1in, n2in)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: n1in, n2in
    INTEGER :: i, j

    n1 = n1in
    n2 = n2in
    IF (ALLOCATED(b)) DEALLOCATE(b)
    ALLOCATE(b(n1,n2))
    b = 0d0

    DO i = 1, n1
       DO j = 1, n2
          b(i, j) = (i-1)*n2 + j
       ENDDO
    ENDDO

  END SUBROUTINE ALLOC
END MODULE VARS

! ===================================
! MODULE THAT PROCESSES THE VARIABLES
! ===================================
MODULE worker
    IMPLICIT NONE
CONTAINS

    ! ADD A SCALAR TO ALL VALUES
    SUBROUTINE add_scalar(x)
        USE vars, ONLY: b, n1, n2
        IMPLICIT NONE
        doubleprecision, INTENT(in) :: x
        INTEGER :: i, j
        DO i = 1, n1
            DO j = 1, n2
                b(i,j) = b(i,j) + x
            ENDDO
        ENDDO
    END SUBROUTINE add_scalar

    ! ADD A VECTOR TO EVERY ROW
    ! THIS ONE WORKS, but needs the dimension
    ! of the vector as input. Instead, it should
    ! use n1 for variables
    SUBROUTINE add_vector2(vector,n1in)
        USE vars, ONLY: b, n2
        IMPLICIT NONE
        integer, INTENT(IN) :: n1in
        doubleprecision, INTENT(in) :: vector(n1in)
        INTEGER :: i, j
        DO i = 1, n1in
            DO j = 1, n2
                b(i,j) = b(i,j) + vector(i)
            ENDDO
        ENDDO
    END SUBROUTINE add_vector2

    ! ADD A VECTOR TO EVERY ROW
    ! the call of this routine should not
    ! have any other arguments, the vector
    ! is supposed to have the right shape n1
    !SUBROUTINE add_vector1(vector)
    !    USE vars, ONLY: b, n1, n2
    !    IMPLICIT NONE
    !    doubleprecision, INTENT(in) :: vector(n1)
    !    INTEGER :: i, j
    !    DO i = 1, n1
    !        DO j = 1, n2
    !            b(i,j) = b(i,j) + vector(i)
    !        ENDDO
    !    ENDDO
    !END SUBROUTINE add_vector1

END MODULE worker

可以使用

^{2}$

在python中:

In [1]: import mymod
In [2]: mymod.vars.alloc(3,2)
In [3]: mymod.vars.b
Out[3]:
array([[1., 2.],
       [3., 4.],
       [5., 6.]])

In [4]: mymod.worker.add_vector2([1,2,3])
In [5]: mymod.vars.b
Out[5]:
array([[2., 3.],
       [5., 6.],
       [8., 9.]])

如何让add_vector1(具有相同的参数/调用)来处理f2py?在

编辑1:

这是来自f2py的错误消息:

#warning "Using deprecated NumPy API, disable it by " \
 ^
/var/folders/r_/b16rpth9643dx5csqdw29wn40000gn/T/tmpm_sqc9ce/src.macosx-10.6-x86_64-3.6/mymodmodule.c:550:19: error: use of undeclared identifier 'n1'
  vector_Dims[0]=(n1);
                  ^
/var/folders/r_/b16rpth9643dx5csqdw29wn40000gn/T/tmpm_sqc9ce/src.macosx-10.6-x86_64-3.6/mymodmodule.c:614:32: warning: incompatible function pointer types
 assigning to 'f2py_init_func' (aka 'void (*)(int *, long *, void (*)(char *, long *), int *)') from 'void (*)(int *, int *, void (*)(char *, int *), int
*)' [-Wincompatible-function-pointer-types]
  f2py_vars_def[i_f2py++].func = b;
                               ^ ~

2 warnings and 1 error generated.

编辑2:

一个选项可能是创建一个包装器,例如这个(wrapper.f90):

module wrapper
    implicit none
contains

    SUBROUTINE wrap_add_vector2(vector,n1in)
        USE vars, ONLY: b, n2
        IMPLICIT NONE
        integer, INTENT(IN) :: n1in
        doubleprecision, INTENT(in) :: vector(n1in)
        INTEGER :: i, j
        DO i = 1, n1in
            DO j = 1, n2
                b(i,j) = b(i,j) + vector(i)
            ENDDO
        ENDDO
    END SUBROUTINE wrap_add_vector2
end module wrapper

但是,用f2py -m wrapper -c mymod.f90 wrapper.f90编译这个仍然会导致相同的问题,即f2py不能编译{}。整个过程应该可以作为numpy扩展使用。在


Tags: noneaddintegervarsdovectorf2pyn2