简体   繁体   English

f2py:模块中常量的奇怪行为

[英]f2py: strange behaviour for constants in module

I found some strange behaviour for f2py when working with global constants in a Fortran module. 在Fortran模块中使用全局常量时,我​​发现f2py有一些奇怪的行为。

Let's say I have a file test.f90, which looks like 假设我有一个文件test.f90,看起来像

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

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

If I wrap this with f2py using 如果我用f2py包装

f2py -c -m mymod test.f90

and running 并运行

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

I get 我懂了

12345.0
6789.0

which is pretty much you would expect. 这是您所期望的。 Both real and real*8 statements behave the same way. real和real * 8语句的行为相同。

For my actual project I need to compile my Fortran code with compiler flags, specifying explicit usage of double precision. 对于我的实际项目,我需要使用编译器标志来编译我的Fortran代码,并指定双精度的显式用法。 In Fortran, this works fine. 在Fortran中,这可以正常工作。 When I compile the above code as 当我将上面的代码编译为

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

I get as result 我得到的结果

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

0.0
6789.0

This is actually weird. 这实际上很奇怪。 The global variable is not initialized in the first case, it's value is zero. 在第一种情况下,全局变量未初始化,其值为零。 Is this a bug or is there a different way to specify explicit handling of double precision in f2py? 这是错误还是在f2py中指定了显式处理双精度的方法?

You're not specifying "explicit use of double precision" -- I would argue that you're specifying "implicit use of double precision" and numpy/f2py has no way of knowing the datatype. 您不是在指定“显式使用双精度”,而是要在您指定“隐式使用双精度”,而numpy / f2py无法得知数据类型。 In this case, it is likely that f2py is guessing the datatype is float32, so only the first 32 bits of your (64-bit) parameter are actually being interpreted. 在这种情况下,很可能f2py猜测数据类型为float32,因此实际上仅解释了(64位)参数的前32位。 You can see the same effect if you pass a double precision number to a function which expects a float: 如果将双精度数字传递给需要浮点数的函数,则可以看到相同的效果:

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

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

compile and run: 编译并运行:

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

The take-away here is that you're expecting f2py to know how to interpret fortran code and also how to interpret commandline arguments for a particular compiler. 这里的f2py是,您期望f2py知道如何解释fortran代码以及如何解释特定编译器的命令行参数。 We might be able to argue that this type of support would be useful for a small set of compilers -- Unfortunately, it is currently not supported by f2py . 我们也许可以争辩说,这种支持类型对少量编译器将很有用-不幸的是, f2py目前不支持这种支持。

You need to declare all of your parameters and arguments to be a specific type and changing them on the command line will likely result in the kinds of errors that you see above. 您需要将所有参数和参数声明为特定类型,并且在命令行上更改它们可能会导致您在上面看到的各种错误。

I found a workaround so far. 到目前为止,我找到了一种解决方法。 The problem is that f2py does not recognize that it should map a fortran real to a C-type double when appropriate double precision compiler flags are provided. 问题在于,当提供适当的双精度编译器标志时,f2py无法识别它应将fortran real映射到C类型的double

The solution is to tell f2py explicitly how to do the mapping of different data types. 解决方案是明确告诉f2py如何进行不同数据类型的映射。 This can be achieved by creating a file .f2py_f2cmap which contains a python dictionary specifying the data type mapping. 这可以通过创建文件.f2py_f2cmap来实现,该文件包含一个指定数据类型映射的python字典。 For details see here . 有关详细信息,请参见此处

In my case the following entry solved the problem 就我而言,以下条目解决了问题

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM