using allocatable arrays from modules in f2py

纵然是瞬间 提交于 2021-02-10 20:47:57

问题


I'm having issues with allocatable arrays in f2py. In the code below (stored in mymod.f90), I created two modules, vars and worker:

  • vars stores and allocates the array b
  • worker contains subroutines to work with this array from vars.

The first worker-subroutine adds a scalar to b. This works as expected. The problem is with the next routine that should add a vector of matching first dimension to the array b. The implemented subroutine add_vector2 works, but needs the dimension of the input vector to be passed along.

What I need is a subroutine with only the vector as argument, like the commented-out subroutine add_vector1. This, however does not compile with f2py (but works with gfortran).

Here's the code:

! =======================================
! 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

This can be compiled with

f2py -m mymod -c mymod.f90

In 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.]])

How can I get add_vector1 (with the same arguments/call) to work with f2py?

Edit 1:

This is the error message from 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.

Edit 2:

One option might be to create a wrapper, such as this one (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

However compiling this with f2py -m wrapper -c mymod.f90 wrapper.f90 still causes the same problem that is f2py cannot compile mymod.f90. The whole thing should be usable as numpy extension.

来源:https://stackoverflow.com/questions/52597454/using-allocatable-arrays-from-modules-in-f2py

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!