Pergunta

I found some strange behaviour for f2py when working with global constants in a Fortran module.

Let's say I have a file test.f90, which looks like

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

For my actual project I need to compile my Fortran code with compiler flags, specifying explicit usage of double precision. In Fortran, this works fine. 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?

Foi útil?

Solução 2

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.

The solution is to tell f2py explicitly how to do the mapping of different data types. This can be achieved by creating a file .f2py_f2cmap which contains a python dictionary specifying the data type mapping. For details see here.

In my case the following entry solved the problem

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

Outras dicas

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

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top