« Previous 1 2 3 Next »
Accessing Fortran code with Python
Scientific Computing
f2py Example
The simple Fortran code in Listing 2 illustrates how to call a subroutine with input data.
Listing 2
secret.f90
subroutine hellofortran(n) integer n write(*,*) "Hello from Fortran! The secret number is: ", n return end
The next step is to create the signature of the code for f2py
:
$ python3 -m numpy.f2py secret.f90 -m secretcode -h secret.pyf
For this command, f2py
takes the Fortran 90 code and creates the signature file secret.pyf
. The Python module is named secretcode
(with the -m
option). The resulting signature file is shown in Listing 3.
Listing 3
secret.pyf
$ more secret.pyf ! -*- f90 -*- ! Note: the context of this file is case sensitive. python module secretcode ! in interface ! in :secretcode subroutine hellofortran(n) ! in :secretcode:secret.f90 integer :: n end subroutine hellofortran end interface end python module secretcode ! This file was auto-generated with f2py (version:2). ! See http://cens.ioc.ee/projects/f2py2e/
The final step is to compile the code with f2py
and create the Python module:
$ python3 -m numpy.f2py -c secret.pyf secret.f90
The output from the command (not shown) provides some good information about what it's doing and is useful in understanding what f2py
does.
f2py
creates a shared object (.so
) suitable for Python to import:
$ ls -s total 120 112 secretcode.cpython-37m-x86_64-linux-gnu.so 4 secret.f90 4 secret.pyf
To test the code, run python3
(Listing 4). Remember, the Python module is secretcode
.
Listing 4
Testing the Code
$ python3 Python 3.7.3 (default, Mar 27 2019, 22:11:17) [GCC 7.3.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> import secretcode >>> secretcode.hellofortran(5) Hello from Fortran! The secret number is: 5
The first command (see the >>>
prompts) imports the secretcode
Python module. The shared object has the function hellofortran
, which you use in the second command, secretcode.hellofortran()
. I used the argument 5
in the test.
OpenMP and f2py
If you can compile Fortran routines to use in Python, shouldn't you be able to compile OpenMP Fortran code for Python? After all, Python only uses a single core. If you either take existing Fortran routines or write new Fortran routines that use OpenMP to take advantage of all of the CPU cores, you would make much better use of computational resources.
Previously, I wrote an article that introduced the concept of using multicore processing with Fortran and OpenMP [9]. The article has a simple example of finding an array's minimum. f2py
was used on the command line with several options for the compiler to build OpenMP code:
$ f2py --f90flags=-fopenmp -L/usr/lib/gcc/x86_64-redhat-linux/4.8.2/ -lgomp -c -m test test.f90
In this case, the GFortran compiler option -fopenmp
was used to compile the OpenMP. It also added the appropriate gomp
library with the full path. This test.f90
code also used the ompmin
function and created the test
module. Read the article to understand how you can use OpenMP with your Fortran code in Python.
gfort2py
During my research for this article, I ran into the interesting gfort2py
project [10], which uses the GNU Fortran (GFortran) compiler and Fortran modules (.mod
files) to translate the Fortran code's application binary interface (ABI) to Python-compatible types with Python's ctypes
library.
In principle, gfort2py
can accommodate anything the compiler can compile (i.e., valid Fortran), as long as it is in a Fortran module. Mostly written in Python, gfort2py
requires no changes to your Fortran code, as long as it is a module; however, you can only use GFortran.
gfort2py
requires GFortran version greater than 5.3.1. It works with both Python 2.7 and Python 3. Although it is set up to be installed by pip
, because I'm using Anaconda, I will install it the old-fashioned way and build it on the target system. The instructions for installation on the gfort2py
website are easy to follow, and it's simple to install. Just be sure to start with the Python version you intend to use later.
The Fortran test code is very simple (Listing 5) and almost the same as the previous code. It just writes out a variable that is passed in. Notice that the code is in a module, as required.
Listing 5
test1.f90
module test1 contains subroutine hello(n) integer :: n write(*,*) "hello world. The secret number is ",n return end end module test1
The next step is to compile the code and create the library (Listing 6). The resulting Python library is very easy to use: You use a function from the gfort2py
Python module, and it handles the heavy lifting, so to speak (Listing 7).
Listing 6
Compiling Fortran Code
$ gfortran -fPIC -shared -c test1.f90 $ gfortran -fPIC -shared -o libtest1.so test1.f90 $ ls -s total 28 8 libtest1.so 4 test1.f90 4 test1.fpy 4 test1.mod 4 test1.o 4 test1.py
Listing 7
Using the Python Library
import gfort2py as gf SHARED_LIB_NAME = "./libtest1.so" MOD_FILE_NAME="test1.mod" x = gf.fFort(SHARED_LIB_NAME, MOD_FILE_NAME) y = x.hello(6)
First, variables are defined pointing to the library and the compiled .mod
file. Next, an object is defined that contains the functions in the Fortran module file (x
). Finally, a function from the code is used. Running the Python code shows the output:
$ python3 test1.py hello world. The secret number is 6
Going beyond this simple code would make the article too long, but it seems like almost anything you can put into a Fortran module would work – perhaps even OpenMP or another extension. Since gfort2py
seems to be under active development, check back in from time to time to see what new features have been added.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)