Monday, December 12, 2011

f2py on cosma

Turns out you need to use the --f90exec= option on cosma as opposed to the -fcompiler=.  The executable can be determined by echo $FC after you've loaded a module in.  The rest of the options are standard f2py stuff.
f2py --f90exec=[$FC] -c -m fortran_code fortran_code.f90

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.





Thursday, November 3, 2011

Compiling HDF5 1.8.6

Installed HDF5 on yinzer today.  Just some notes about the config.  This is what I used,

sudo /home/galtay/Downloads/linux-programs/hdf5/hdf5-1.8.6/configure FC=gfortran-4.5 --enable-fortran --prefix=/opt/hdf5-1.8.6-gfortran-4.5
sudo make
sudo make install

Compiling OpenMPI 1.4.4


Installed OpenMPI on yinzer today.  Just some notes about the config.  This is what I used,

sudo ~/Downloads/linux-programs/openmpi-1.4.4/configure --prefix=/opt/openmpi-1.4.4-gfortran-4.5 F77=gfortran-4.5 FC=gfortran-4.5
sudo make all install


Monday, January 10, 2011

Calling Fortran 90 from Python

I've been experimenting with calling Fortran 90 from Python. I've got an example working with gfortran 4.5.1 and python 2.6.6, here's how it works. First write the Fortran 90 code you'd like to call. In this example, I put the code in main.f90,



module main

contains

subroutine print_int(a)
integer :: a
write(*,*) 'Hello from Fortran'
write(*,*) 'a = ', a
end subroutine print_int

subroutine print_mat_val( a )
integer :: a(0:2,0:2)
write(*,*) 'a(1,2) = ', a(1,2)
end subroutine print_mat_val

end module main

Next I create a shared object from this code using F2py, which is part of NumPy

f2py --fcompiler=gnu95 -c -m main main.f90

You can now import the module in Python. For example I create a file called example.py with the following code,



import main
import numpy as np

a = np.array([[1,2,3],[4,5,6],[7,8,9]])

main.main.print_int(5)
main.main.print_mat_val(a)

You can run the Python script by typing,

python example.py

The calls contain main.main because both the file and the module are named 'main'. It isn't necessary to wrap the subroutines in a module, but it could be helpful for more complex code.