Mi piacerebbe usare f2py
con il moderno Fortran. In particolare, sto cercando di far funzionare il seguente esempio di base. Questo è il più piccolo esempio utile che potrei generare.
! 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
Si noti che n
è dedotto dalla forma del parametro di input x
. Si noti che y
è allocato e deallocato all'interno del corpo della subroutine.
Quando lo compilo con f2py
f2py -c alloc_test.f90 -m alloc
E poi esegui in Python
from alloc import f
from numpy import ones
x = ones(5)
print f(x)
Ottengo il seguente errore
ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (-1,)
Quindi vado a creare e modificare il pyf
file manualmente
f2py -h alloc_test.pyf -m alloc alloc_test.f90
Originale
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
Modificata
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
Ora funziona ma i valori dell'output z
sono sempre 0
. Alcune stampe di debug rivelano che n
ha il valore 0
all'interno della subroutine f
. Presumo che mi manchi un po 'di f2py
magia dell'intestazione per gestire correttamente questa situazione.
Più in generale, qual è il modo migliore per collegare la subroutine sopra in Python? Preferirei fortemente non dover modificare la subroutine stessa.