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

Usage of intent in Fortran

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

insert image description here
Step 3:
In Python, you can directly import the function name above

import circle
print(circle.__doc__)
print(circle.area_of_circle(2))

insert image description here
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)

insert image description here

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]

Guess you like

Origin blog.csdn.net/wokaowokaowokao12345/article/details/128918409