F2py: Specifying Real Precision In Fortran When Interfacing With Python?
Solution 1:
In your first example, I don't know why you say it seems like f2py doesn't accept double precision, when test.test.r_dp
is double precision. A numpy array that shows a value with a decimal point and no explicit dtype is a double precision array.
The second example shows a limitation in F2PY's handling of type definitions with kind=<kind>
. See the FAQ:
https://numpy.org/doc/stable/f2py/advanced.html#dealing-with-kind-specifiers
To see what is happening, run f2py test.f90 -m test
. I get this:
Reading fortran codes...
Reading file 'test.f90' (format:free)
Post-processing...
Block: test
Block: test
Block: input_sp
Block: input_dp
Post-processing (stage 2)...
Block: test
Block: unknown_interface
Block: test
Block: input_sp
Block: input_dp
Building modules...
Building module"test"...
Constructing F90 module support for"test"...
Variables: r_dp sp r_sp dp
Constructing wrapper function"test.input_sp"...
getctype:"real(kind=sp)"is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype:"real(kind=sp)"is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype:"real(kind=sp)"is mapped to C "float" (to override define dict(real = dict(sp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
input_sp(val)
Constructing wrapper function"test.input_dp"...
getctype:"real(kind=dp)"is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype:"real(kind=dp)"is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
getctype:"real(kind=dp)"is mapped to C "float" (to override define dict(real = dict(dp="<C typespec>")) in /Users/warren/tmp/.f2py_f2cmap file).
input_dp(val)
Wrote C/API module"test"to file "./testmodule.c"
Fortran 90 wrappers are saved to"./test-f2pywrappers2.f90"
Note that it is mapping both "real(kind=sp)" and "real(kind=dp)" to C "float", which is single precision.
There are several ways to fix this.
Method 1
Change the type declarations to "real(kind=4)" and "real(kind=8)" (or "real4" and "real8"), respectively.
Of course, this defeats the purpose of using selected_real_kind
, and for some compilers,
4 and 8 are not the correct KIND values for single and double precision.
In this case, with gfortran, sp
is 4 and dp
is 8, so it works.
Method 2
Tell f2py how to handle those declarations. This is explained in the f2py FAQ, and it is the approach suggested in the "getctype: ..." messages in the output of f2py shown above.
In this case, you would create a file called .f2py_f2cmap
(in the directory where you are running f2py) that contains the line
dict(real=dict(sp='float', dp='double'))
Then f2py will do the right thing with those real(sp)
and real(dp)
declarations.
Method 3
It also works to rearrange your code a bit:
module types
implicit noneinteger, parameter :: sp = selected_real_kind(6,37) ! single precisioninteger, parameter :: dp = selected_real_kind(15,307) !double precisionreal(sp) :: r_sp =1.0real(dp) :: r_dp =1.0_dp
endmodulemodule input
contains
subroutine input_sp(val)
use types
real(sp), intent(in) :: val
real(sp) :: x
x = val
write(*,*) x
end subroutine
subroutine input_dp(val)
use types
real(dp), intent(in) :: val
real(dp) :: x
x = val
write(*,*) dp, val, x
end subroutine
endmodule
See Subroutine argument not passed correctly from Python to Fortran for a similar suggestion.
Post a Comment for "F2py: Specifying Real Precision In Fortran When Interfacing With Python?"