Sunday, December 4, 2011

More Calling Fortran 90 from Python

Wrote some more Fortran to be compiled with f2py and called from Python.  Ran into some issues and solutions.  The first had to do with variable precision.  I usually use the selected_real_kind() type functions to define the precision of the variables.  This is a tricky thing for f2py to parse so I ended up using the simple mapping real(4) for 32 bit reals and real(8) for 64 bit reals.  Second, it turns out you have to be careful using automatic and assumed shape arrays.  Its easiest for f2py to parse the fortran if the size of assumed shape and automatic arrays are included in the fortran subroutine argument list.  f2py is even nice enough to make the size an optional argument in the python version of the function.  For example, this subroutine was giving me segmentation faults,

subroutine calc_arr( inarr,outarr )  
real(8),dimension(:),intent(in) :: inarr
real(8),dimension(size(inarr)-1),intent(out) :: outarr
outarr = inarr(2:nn) - inarr(1:nn-1) 
end subroutine calc_arr 

This one works fine,

subroutine calc_arr( inarr,nn,outarr )  
real(8),dimension(0:nn-1),intent(in) :: inarr
integer(4),intent(in) :: nn
real(8),dimension(0:nn-2),intent(out) :: outarr
outarr = inarr(1:nn-1) - inarr(0:nn-2) 
end subroutine calc_arr 

The extra argument helps f2py determine the array sizes.  In addition, you can use the nice fortran feature of being able to label the array entries starting with whatever index you like (including zero to make them more like python arrays).  I also learned you should stay away from the logical type in Fortran as I don't think there is a solid mapping into a C/f2py type and it gave me unpredictable results. Simply use integers instead of bools for logical variables.

No comments:

Post a Comment