f2py: странное поведение констант в модуле

Я обнаружил странное поведение f2py при работе с глобальными константами в модуле Fortran.

Допустим, у меня есть файл test.f90, который выглядит так

module test1
  real, parameter :: a = 12345.
end module test1

module test2
  real*8, parameter :: a = 6789.
end module test2

Если я оберну это с помощью f2py, используя

f2py -c -m mymod test.f90

и работает

python -c "import mymod as m; print m.test1.a; print m.test2.a"

я получил

12345.0
6789.0

что в значительной степени вы ожидаете. Операторы real и real*8 ведут себя одинаково.

Для моего реального проекта мне нужно скомпилировать мой код Fortran с флагами компилятора, указав явное использование двойной точности. В Фортране это работает нормально. Когда я компилирую приведенный выше код как

f2py --f90flags="-fdefault-double-8 -fdefault-integer-8 -fdefault-real-8" -c -m mymod test.f90

я получаю в результате

python -c "import mymod as m; print m.test1.a; print m.test2.a"

0.0
6789.0

Это на самом деле странно. В первом случае глобальная переменная не инициализируется, ее значение равно нулю. Это ошибка или есть другой способ указать явную обработку двойной точности в f2py?


person allion    schedule 11.06.2013    source источник


Ответы (2)


Вы не указываете «явное использование двойной точности» - я бы сказал, что вы указываете «неявное использование двойной точности», а numpy/f2py не может узнать тип данных. В этом случае вполне вероятно, что f2py предполагает, что тип данных — float32, поэтому фактически интерпретируются только первые 32 бита вашего (64-битного) параметра. Вы можете увидеть тот же эффект, если передадите число с двойной точностью функции, которая ожидает число с плавающей запятой:

program main
  real*8 :: foo
  foo = 12345.
  call printme(foo)
end program

subroutine printme(foo)
  real foo
  print*, foo
end subroutine printme

скомпилировать и запустить:

gfortran test2.f90
./a.out  #prints 0.00000

Вывод здесь состоит в том, что вы ожидаете, что f2py будет знать, как интерпретировать код fortran, а также как интерпретировать аргументы командной строки для конкретного компилятора. Мы могли бы утверждать, что этот тип поддержки был бы полезен для небольшого набора компиляторов. К сожалению, в настоящее время он не поддерживается f2py.

Вам нужно объявить все ваши параметры и аргументы определенного типа, и их изменение в командной строке, скорее всего, приведет к ошибкам, которые вы видите выше.

person mgilson    schedule 12.06.2013
comment
Привет, спасибо за ваш ответ. Таким образом, вы также можете сказать, что флаги компилятора --f90flags=-fdefault-double-8 -fdefault-integer-8 -fdefault-real-8 просто игнорируются ft2py и не знают, как отображать разные типы данных. Я забыл упомянуть в вопросе, что я явно указываю f2py, какой компилятор (в моем случае gfortran) использовать, используя --fcompiler=gfortran. - person allion; 14.06.2013
comment
Забудьте об этих флагах, действительно не стоит осложнений. Модернизируйте код и используйте параметры типа, которые вы можете легко изменить. Принятый ответ только увеличивает запутывание. - person Vladimir F; 14.06.2013
comment
@VladimirF - я всегда считал, что параметры вида слишком сложны, учитывая тот факт, что почти все машины, которые я когда-либо использовал на Fortran, используют IEEE. Кроме того (и что более важно), я не совсем уверен, что f2py достаточно умен, чтобы определить соответствующий тип C из параметра kind... - person mgilson; 14.06.2013

Я нашел обходной путь до сих пор. Проблема в том, что f2py не распознает, что он должен сопоставлять fortran real с C-типом double, когда предоставлены соответствующие флаги компилятора двойной точности.

Решение состоит в том, чтобы явно указать f2py, как выполнять сопоставление различных типов данных. Этого можно добиться, создав файл .f2py_f2cmap, который содержит словарь Python, определяющий сопоставление типов данных. Подробнее см. здесь.

В моем случае следующая запись решила проблему

{'real':{'':'double'},'integer':{'':'long'},'real*8':{'':'double'}}

person allion    schedule 14.06.2013