f2py: указание реальной точности в fortran при взаимодействии с python?

Я играю с f2py. Я немного смущен о numpy intrinsic типа против fortran 90 типов. Кажется, что я могу использовать только одиночные префиксные переменные в fortran 90 при взаимодействии с python. Позвольте мне проиллюстрировать пример:

Скажем, у меня есть этот модуль fortran 90, test.f90, который должен быть скомпилирован с f2py и импортирован в 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 

и я компилирую вот так:

f2py -c -m test test.f90

Затем в python:

 >>> import test >>> test.test.r_sp array(1.0, dtype=float32) >>> test.test.r_dp array(1.0) 

IOW, похоже, что f2py не принимает двойную точность. Это становится еще более проблематичным при передаче ввода в подпрограмму fortran 90 из 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 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 test test.f90

питон

 >>> 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

Таким образом, кажется, что любая входная переменная, отправляемая из python, должна быть объявлена ​​одинарной точностью. Это известная проблема с f2py?

Кроме того, в качестве следующего вопроса: Преобразование из sp в dp работает, в следующем смысле:

 subroutine input_sp_to_dp(val) real(sp), intent(in) :: val(2) real(dp) :: x(2) x = val write(*,*) x end subroutine 

Но мне интересно, совсем ли это компилятор? Могу ли я ожидать, что вышеуказанная подпрограмма будет делать то же самое с любым компилятором в любой архитектуре? При тестировании я использовал gfortran для всех приведенных выше примеров.

    One Solution collect form web for “f2py: указание реальной точности в fortran при взаимодействии с python?”

    В первом примере я не знаю, почему вы говорите, что f2py не принимает двойную точность, когда test.test.r_dp является двойной точностью. Массив numpy, который показывает значение с десятичной точкой и без явного dtype, представляет собой массив с двойной точностью.

    Второй пример показывает ограничение в обработке F2PY определений типов с помощью kind=<kind> . См. FAQ: http://cens.ioc.ee/projects/f2py2e/FAQ.html#q-what-if-fortran-90-code-uses-type-spec-kind-kind

    Чтобы узнать, что происходит, запустите f2py test.f90 -m test . Я получаю это:

     Reading fortran codes... Reading file 'test.f90' (format:free) Post-processing... Block: test Block: test Block: input_sp Block: input_dp Post-processing (stage 2)... Block: test Block: unknown_interface Block: test Block: input_sp Block: input_dp Building modules... Building module "test"... Constructing F90 module support for "test"... Variables: r_dp sp r_sp dp Constructing wrapper function "test.input_sp"... getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). getctype: "real(kind=sp)" is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). input_sp(val) Constructing wrapper function "test.input_dp"... getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). getctype: "real(kind=dp)" is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file). input_dp(val) Wrote C/API module "test" to file "./testmodule.c" Fortran 90 wrappers are saved to "./test-f2pywrappers2.f90" 

    Обратите внимание, что он отображает как «real (kind = sp)», так и «real (kind = dp)» на C «float», который является одинарной точностью.

    Есть несколько способов исправить это.

    Способ 1

    Измените объявления типов на «real (kind = 4)» и «real (kind = 8)» (или «real * 4» и «real * 8») соответственно.

    Конечно, это побеждает цель использования selected_real_kind , а для некоторых компиляторов 4 и 8 не являются правильными значениями KIND для одиночной и двойной точности. В этом случае с gfortran sp равен 4, а dp – 8, поэтому он работает.

    Способ 2

    Скажите f2py, как обрабатывать эти объявления. Это объясняется в FAQ f2py, и это подход, предложенный в сообщениях «getctype: …» на выходе f2py, показанном выше.

    В этом случае вы должны создать файл с именем .f2py_f2cmap (в каталоге, где вы используете f2py), который содержит строку

     dict(real=dict(sp='float', dp='double')) 

    Тогда f2py будет делать правильные действия с этими real(sp) и real(dp) объявлениями.

    Способ 3

    Он также работает, чтобы немного изменить ваш код:

     module types 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 module input contains subroutine input_sp(val) use types real(sp), intent(in) :: val real(sp) :: x x = val write(*,*) x end subroutine subroutine input_dp(val) use types real(dp), intent(in) :: val real(dp) :: x x = val write(*,*) dp, val, x end subroutine end module 

    См. Аргумент подпрограммы, не переданный правильно из Python в Fortran для аналогичного предложения.

    Python - лучший язык программирования в мире.