2

在 Fortran 模块中使用全局常量时,我​​发现 f2py 有一些奇怪的行为。

假设我有一个文件 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 代码,并指定显式使用双精度。在 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 中双精度的显式处理?

4

2 回答 2

1

您没有指定“显式使用双精度” - 我认为您正在指定“隐式使用双精度”并且 numpy/f2py 无法知道数据类型。在这种情况下,f2py 很可能猜测数据类型是 float32,因此实际上只解释了(64 位)参数的前 32 位。如果将双精度数传递给需要浮点数的函数,则可以看到相同的效果:

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.

您需要将所有参数和参数声明为特定类型,并在命令行上更改它们可能会导致您在上面看到的各种错误。

于 2013-06-12T17:47:56.663 回答
0

到目前为止,我找到了一种解决方法。问题在于,当提供了适当的双精度编译器标志时,f2py 无法识别它应该将 fortran 映射real到 C 类型。double

解决方案是明确告诉 f2py 如何进行不同数据类型的映射。这可以通过创建一个.f2py_f2cmap包含指定数据类型映射的 python 字典的文件来实现。有关详细信息,请参见此处

在我的情况下,以下条目解决了问题

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

于 2013-06-14T05:59:47.423 回答