Me gustaría usar f2py
con Fortran moderno. En particular, estoy tratando de que el siguiente ejemplo básico funcione. Este es el ejemplo útil más pequeño que pude generar.
! alloc_test.f90
subroutine f(x, z)
implicit none
! Argument Declarations !
real*8, intent(in) :: x(:)
real*8, intent(out) :: z(:)
! Variable Declarations !
real*8, allocatable :: y(:)
integer :: n
! Variable Initializations !
n = size(x)
allocate(y(n))
! Statements !
y(:) = 1.0
z = x + y
deallocate(y)
return
end subroutine f
Tenga en cuenta que n
se infiere de la forma del parámetro de entrada x
. Tenga en cuenta que y
está asignado y desasignado dentro del cuerpo de la subrutina.
Cuando compilo esto con f2py
f2py -c alloc_test.f90 -m alloc
Y luego correr en Python
from alloc import f
from numpy import ones
x = ones(5)
print f(x)
Obtuve el siguiente error
ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (-1,)
Así que voy y creo y edito el pyf
archivo manualmente
f2py -h alloc_test.pyf -m alloc alloc_test.f90
Original
python module alloc ! in
interface ! in :alloc
subroutine f(x,z) ! in :alloc:alloc_test.f90
real*8 dimension(:),intent(in) :: x
real*8 dimension(:),intent(out) :: z
end subroutine f
end interface
end python module alloc
Modificado
python module alloc ! in
interface ! in :alloc
subroutine f(x,z,n) ! in :alloc:alloc_test.f90
integer, intent(in) :: n
real*8 dimension(n),intent(in) :: x
real*8 dimension(n),intent(out) :: z
end subroutine f
end interface
end python module alloc
Ahora se ejecuta pero los valores de la salida z
son siempre 0
. Algunas impresiones de depuración revelan que n
tiene el valor 0
dentro de la subrutina f
. Supongo que me falta algo de f2py
magia de encabezado para manejar esta situación correctamente.
En general, ¿cuál es la mejor manera de vincular la subrutina anterior a Python? Preferiría no tener que modificar la subrutina misma.