【问题标题】:f2py: strange behaviour for constants in modulef2py:模块中常量的奇怪行为
【发布时间】:2013-06-11 16:42:51
【问题描述】:

在 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 中指定显式处理双精度?

【问题讨论】:

    标签: python global-variables fortran f2py


    【解决方案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 目前不支持它。

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

    【讨论】:

    • 您好,感谢您的回答。因此,您还会说编译器标志 "--f90flags="-fdefault-double-8 -fdefault-integer-8 -fdefault-real-8" 被 ft2py 简单地忽略,它不知道如何映射不同的数据类型。我忘了在问题中提到,我明确告诉f2py 使用--fcompiler=gfortran 使用哪个编译器(在我的例子中是gfortran)。
    • 忘记这些标志,真的不值得复杂。使代码现代化并使用您可以轻松更改的种类参数。接受的答案只会增加混淆。
    • @VladimirF -- 考虑到我曾经使用过 fortran 的几乎所有机器都使用 IEEE,我总是发现 kind 参数过于复杂。此外,(更重要的是)我不完全确定 f2py 是否足够聪明,能够从 kind 参数中找出相应的 C 类型...
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2016-07-09
      • 2022-11-14
      • 1970-01-01
      • 2021-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-27
      • 1970-01-01
      相关资源
      最近更新 更多