一、f2py调用fortran
基于 F2PY,在 Python 中调用 Fortran 函数的基本流程是:
- Fortran 代码
- 使用f2py编译 Fortran 代码,产生动态库
- 在 Python 中通过import引入动态库
注意: F2py 支持有限的 Fortran 子集。
"""======================1.fortran程序========================="""
function foo(a) result(b)!kind说明精度implicit nonereal(kind=8), intent(in) :: a(:,:)complex(kind=8) :: b(size(a,1),size(a,2))b = exp((0,1)*a)
end function foo"""=============2.编译fortran程序,生成动态链接库==============="""
f2py -c -m myflib testfun.f90
#myflib为包名,testfun.f90为上面fortran代码
#在cmd输入上面的命令"""===================3.import引入动态链接库===================="""
import myflib
import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8]], order='F')
print(myflib.foo(a))
二、使用动态链接库
Fortran 2003 标准引入了 iso_c_bindings 作为提高与 C 互操作性的一种手段。
在 Python 方面,ctypes 是 stdlib 的一部分,它实现了与外部函数的接口。
这两个工具可以结合起来创建一个支持 Fortran 和 Python 兼容性的接口。
注意:
ctypes不支持复数,可以包装依赖其他函数。
处理多维数组:c和fortran函数返回类型不能是数组。
这是Python 中使用 Fortran 的最通用方式。
2.1 fortran程序:定义了两个函数
1.sum2函数实现双精度浮点数并添加数字 2。
2.double_array函数实现多维数组运算
3.保存为ctypes_test.f90
!bind() 方法创建一个新的函数,在 bind() 被调用时,
!这个新函数的 this 被指定为 bind() 的第一个参数,
!而其余参数将作为新函数的参数,供调用时使用。
function sum2(a) result(b) bind(c, name='sum2')use iso_c_binding !fortran自带的implicit nonereal(c_double), intent(in) :: areal(c_double) :: bb = a + 2.d0
end function sum2! 多维数组函数
subroutine double_array(x,N) bind(C, name="double_array")use iso_c_bindingimplicit noneinteger(c_int), intent(in), value :: Nreal(c_double), intent(inout) :: x(N,N)x = exp(x)
end subroutine double_array
2.2 生成动态链接库
在cmd输入下面的命令
gfortran -shared ctypes_test.f90 -o myflib_ctype.so
2.3 python调用fortran
1.导入动态链接库
2.明确输入输出类型
3.传值调用fortran
import ctypes as ct
import numpy as np # 为处理fortran的多维数组
"=======================调用sum2()========================="
# 1.导入动态链接库,最好写绝对路径
fortlib = ct.CDLL('C:/fortranDM/myflib_ctype.so')
# 2.导出fortran函数
f = fortlib.sum2
# 3.指定输入输出类型
# ct.POINTER 类似指针
f.argtypes = [ct.POINTER(ct.c_double)]
f.restype = ct.c_double
# 4.创建double对象并将其传递给Fotran(通过引用)
a = ct.c_double(5)
b = f(ct.byref(a))
print(str(f.__name__)+"函数输出:\n",b)"=======================调用double_array()========================="
# 1.导出fortran函数
f = fortlib.double_array
# 2.指定输入类型
f.argtypes=[ct.POINTER(ct.c_double), ct.c_int]
# 3.创建一个double数组
x = np.ones((3,3), order="F")
x_ptr = x.ctypes.data_as(ct.POINTER(ct.c_double))
# 4.创建double对象并将其传递给Fotran(通过引用)
rint = f(x_ptr, ct.c_int(3))
print(str(f.__name__)+"函数输出:\n",x)
参考文献:https://www.matecdev.com/posts/fortran-in-python.html
三、利用python的os包调用fortran
下面是fortran程序,分别求半径R=1,3,12.5时的圆周长。
此源程序由二部分组成:主程序和子程序。
!主程序
real :: r(3)
data r /1, 3, 12.5/
do i=1,3print *, '半径=', r(i), '圆周长=', C(r(i))
end do
end
!次程序
function c(radius)pi=acos(-1.0)c=2*pi*radiusreturn
end
3.1 os.system命令
os.system(“cmd”) 调用外部命令,程序只能返回命令运行返回码:0正常,1异常;但无法捕获cmd进程执行结果。
import os
os.system(r"gfortran C:/fortranDM/test.f90")
# 只能输出0
优点:使用简单,可以执行一句话cmd行。
缺点:无法获取cmd执行结果,不能进行交互式调用,以及复杂调用操作。