Three forms of Python calling Fortran
1 Introduction
In some research fields, many classic algorithms and tools are written in the ancient language Fortran, and this part of the code has no corresponding C/C++ and Python versions. Therefore, mastering the skill of calling Fortran programs in Python language will help us to see further on the shoulders of giants in some research fields. Python calling Fortran can be summarized into the following three types:
1) Through F2PY: F2PY is a tool developed by the NumPy team, which can convert Fortran programs into Python modules, thereby calling Fortran programs in Python.
2) Through the ctypes library: ctypes is a built-in library in Python, which can be used to call external C dynamic link libraries, so it can also be used to call Fortran programs. Through ctypes, Python can call Fortran programs, and Python functions can be called from Fortran.
3) Use Python's os package to call Fortran.
2. Three methods of Python calling Fortran
2.1 Calling Fortran based on F2PY's f2py
Step 1:
Fortran function to calculate the area of a circle. Next, the following function will be used for demonstration. The example here is the Fortran usage of returning one parameter, returning multiple parameters and modifying parameters, please refer to: Fortran - Procedures .
Fortran77 does not need to add when defining variables::
function area_of_circle (r)
! function result
implicit none
! dummy arguments
real :: area_of_circle
! local variables
real :: r
real :: pi
pi = 4 * atan (1.0)
area_of_circle = pi * r**2
end function area_of_circle
or
function area_of_circle (r) result(a)
implicit none
real :: a
real :: r
real :: pi
pi = 4 * atan (1.0)
a = pi * r**2
end
or
subroutine area_of_circle (r,a)
implicit none
real, intent(out) :: a
real, intent(in) :: r
real :: pi
pi = 4 * atan (1.0)
a = pi * r**2
end
Step 2:
After creating circle.f90, run the following code in the terminal:
python -m numpy.f2py -c circle.f90 -m circle
The specific steps are as shown in the figure below, and then you can see the generatedcircle.cpython-36m-x86_64-linux-gnu.so
Step 3:
In Python, you can directly import the function name above
import circle
print(circle.__doc__)
print(circle.area_of_circle(2))
Note that the above __doc__ is automatically generated by f2py. You can see that the fortran module contains several functions, and each function can also call doc to see the interface parameter type.
2.2 Using the dynamic link library to call Fortran
Step 1:
Modify the Fortran code above to use result to return the function result, specifying the input and return data types.
function area_of_circle(r) result(area) bind(c, name='area_of_circle')
use iso_c_binding
implicit none
real(c_double) :: area
real(c_double), intent(in) :: r
real :: pi
pi = 4 * atan (1.0)
area = pi * r**2
end function area_of_circle
Step 2:
As shown in Section 2.1 , enter the command in the system terminal or Pycharm terminal:
gfortran -shared circle2.f90 -o circle2.so
Step 3:
Write a Python calling script
import ctypes as ct
# import the shared library
fortlib = ct.CDLL('./circle2.so')
# Specify arguments and result types
fortlib.area_of_circle.argtypes = [ct.POINTER(ct.c_double)]
fortlib.area_of_circle.restype = ct.c_double
# Create a double and pass it to Fotran (by reference)
a = ct.c_double(2)
b = fortlib.area_of_circle(ct.byref(a))
print(b)
2.3 Using Python's os package to call Fortran
Step 1:
Take the Fortran code in Section 2.1 as an example and modify it slightly. This method requires that the Fortran code is a complete program and can be compiled into an executable program. The following code contains the main function, which is the body of the function that calls the function.
program calling_func
real :: a
a = area_of_circle(2.0)
Print *, "The area of a circle with radius 2.0 is"
Print *, a
end program calling_func
function area_of_circle(r)
! function result
implicit none
! dummy arguments
real :: area_of_circle
! local variables
real :: r
real :: pi
pi = 4 * atan (1.0)
area_of_circle = pi * r**2
end function area_of_circle
Step 2:
Compile and call, Windows system pay attention to modify the path, and the suffix of the executable program name should be exe, the suffix of the Linux executable program can be out or not.
import os
#编译
os.system(r"gfortran ./circle3.f90 -o circle")
#调用编译的circle程序
os.system('./circle')
The above code is similar to calling cmd in Windows.
3. Summary
Method 1: Recommended, for Python programming, if the return data type is complex, it is not too convenient;
Method 2: Too cumbersome and not recommended;
Method 3: It is an executable program that needs to be compiled first and then called, and the interaction is inconvenient. It is also a better choice if the input and output are written as fixed files, and then Python produces the input files and Python reads the output files.
Reference
[1] How to Call Fortran from Python
[2] Python and Fortran mixed programming
[3] Three forms of python calling fortran [f2py, dynamic link library, os command]