У меня проблемы с размещаемыми массивами в f2py
.В приведенном ниже коде (хранящемся в mymod.f90
) я создал два модуля: vars
и worker
:
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
Это может быть скомпилировано с
f2py -m mymod -c mymod.f90
В 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
не может скомпилировать mymod.f90
.Все это должно быть использовано как numpy
расширение.