Eu gostaria de usar f2py
com o Fortran moderno. Em particular, estou tentando fazer o exemplo básico a seguir funcionar. Este é o menor exemplo útil que eu poderia gerar.
! 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
Observe que n
é deduzido da forma do parâmetro de entrada x
. Observe que y
é alocado e desalocado dentro do corpo da sub-rotina.
Quando eu compilar isso com f2py
f2py -c alloc_test.f90 -m alloc
E então execute em Python
from alloc import f
from numpy import ones
x = ones(5)
print f(x)
Estou tendo o erro a seguir
ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (-1,)
Então, eu vou criar e editar o pyf
arquivo 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
Agora ele roda, mas os valores da saída z
são sempre 0
. Algumas impressões de depuração revelam que n
tem o valor 0
dentro da sub-rotina f
. Suponho que estou perdendo alguma f2py
mágica de cabeçalho para gerenciar essa situação corretamente.
De maneira geral, qual é a melhor maneira de vincular a sub-rotina acima ao Python? Eu preferiria fortemente não ter que modificar a própria sub-rotina.