Sto giocando con f2py. Sono un po 'confuso riguardo i tipi intrinseci di Numpy e quelli di Fortran 90. Sembra che io possa usare solo reals a precisione singola in fortran 90, quando si interagisce con Python. Permettetemi di illustrare con un esempio:f2py: specificare la precisione reale in fortran quando si interfaccia con python?
Dire che ho questo Fortran 90 modulo, test.f90, per essere compilato con f2py e importati in python:
module test
implicit none
integer, parameter :: sp = selected_real_kind(6,37) ! single precision
integer, parameter :: dp = selected_real_kind(15,307) ! double precision
real(sp) :: r_sp = 1.0
real(dp) :: r_dp = 1.0_dp
end module
e compilare in questo modo:
f2py -c -m prova test.f90
Poi, in pitone:
>>> import test
>>> test.test.r_sp
array(1.0, dtype=float32)
>>> test.test.r_dp
array(1.0)
IOW, sembra che f2py non accetti la doppia precisione. Ciò diventa ancora più problematico quando si passa l'input a una subroutine di fortran 90 da python. Di 'Estendo il mio modulo:
module test
implicit none
integer, parameter :: sp = selected_real_kind(6,37) ! single precision
integer, parameter :: dp = selected_real_kind(15,307) ! double precision
real(sp) :: r_sp = 1.0
real(dp) :: r_dp = 1.0_dp
contains
subroutine input_sp(val)
real(sp), intent(in) :: val
real(sp) :: x
x = val
write(*,*) x
end subroutine
subroutine input_dp(val)
real(dp), intent(in) :: val
real(dp) :: x
x = val
write(*,*) x
end subroutine
end module
f2py -c -m prova test.f90
pitone
>>> import test
>>> test.test.input_sp(array(1.0,dtype=float32))
1.0000000
>>> test.test.input_sp(array(1.0,dtype=float64))
1.0000000
>>> test.test.input_dp(array(1.0,dtype=float32))
-1.15948430791165406E+155
>>> test.test.input_dp(array(1.0,dtype=float64))
-1.15948430791165406E + 155
Così, sembra come qualsiasi la variabile di input da inviare da python deve essere dichiarata a precisione singola. Si tratta di un problema noto con f2py?
Inoltre, come un follow-up domanda: Conversione da sp DP opere, nel senso seguente:
subroutine input_sp_to_dp(val)
real(sp), intent(in) :: val(2)
real(dp) :: x(2)
x = val
write(*,*) x
end subroutine
Ma mi chiedo se questo è specifica del compilatore a tutti? Posso aspettarmi che la suddetta subroutine faccia la cosa giusta con qualsiasi compilatore su qualsiasi architettura? Durante il test, ho usato gfortran per tutti gli esempi precedenti.
Grazie per la tua risposta. Ho fatto prima il metodo 2, e questo ha funzionato bene. Ma poi ho provato ad applicarlo al programma vero e proprio che sto scrivendo, che usa le distutils per fare la compilazione tramite un file setup.py e così via. Ho poi scoperto che il solo fatto di avere un file .f2py_cmap non era sufficiente, anche se sputa che ha applicato correttamente le modifiche da .f2py_cmap durante la compilazione. Quindi ho dovuto usare il metodo 3. In realtà, stavo già usando un modulo separato per le definizioni delle variabili di precisione, ma avevo l'istruzione 'use types' nella parte superiore del modulo che lo utilizzava, non all'interno delle singole subroutine. – arne