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.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus