登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 凉茶啦啦啦啦啦 于 2019-1-16 09:22 编辑
python调用Fortran程序一直是想要学习的内容,之前上一门python的课,为了完成大作业恶补了一下关于这一内容的知识,虽然了解得不是很深入,但起码能够简单地使用了。把之前的作业和程序总结了一下,希望能够给大家一点帮助,如有不对的地方也请多多指教!其中,有些内容是气象家园上面一些朋友总结出来的【参考链接:http://bbs.06climate.com/forum.p ... 7&fromuid=52493(出处: 气象家园)
】。例子是在李建平教授网站上下载的一个关于小波分析的程序,另外,图片上我忘记画显著性检验了。。。pdf文件和贴出来的内容是一样的可以不用下载,压缩包是相关的源代码。Python调用Fortran的方法 --命令行工具f2py介绍 1.引言 在海洋与大气研究领域,Fortran作为一门高效的编程语言被应用于各项研究中。但由于其本身的局限性,只能计算而无法绘制图像,不便于研究分析,这就使得MATLAB、NCL、IDL一类的软件流行起来。在之前的海洋与大气研究中,MATLAB的普及程度较高,但其软件过于庞大且收费。相比之下,Python作为一门开源免费的综合性程序设计语言,同时还拥有着许多标准扩展库,如Numpy、Scipy、Matplotlib等,开始逐渐取代MATLAB的位置,在国内外普及。 Python作为一门在海洋与大气领域刚刚兴起的语言,专业性计算代码是有限的,比如计算流体旋度、散度等。将大量的计算代码重新用Python语言编写,这在无形之中给我们增加了工作量。但是,已经有大量现成的Fortran代码来做这些工作了,倘若能实现在Python中调用Fortran,将计算的工作交给Fortran程序,而用Python作图,这将大大地提高我们的工作效率。因此,实现Python、Fortran混合编程对于海洋与大气研究领域,是一项非常有意义的工作。 2.命令行工具f2py 2.1 F2PY简介 F2PY项目的目的是在Python和Fortran语言之间建立一个连接。F2PY是一个Python 包(包含一个命令行工具f2py和一个模块f2py2e),用来建立Python C/API 扩展模块,从而能够: (1) 调用Fortran 77/90/95外部子程序、Fortran 90/95模块子程序以及C函数 (2) 访问Fortran 77 COMMON blocks和Fortran 90/95 模块数据,包括可变大小的动态数组。 2.2 命令行工具f2py使用方法 下述方法全部是基于Linux环境,需要先在Linux机上安装Linux版本的Anaconda,安装方法本文不再赘述。安装完成后,已经包括了命令行工具f2py,无需再另行安装,是非常方便的。如果在Windows环境下,考虑到要使用Fortran编译器,需要安装Mingw,在命令行的模式下使用,较为麻烦,因此,建议在Linux环境下使用该方法。 以下介绍具体使用方法,以下面的Fortran 90 代码为例说明。 表2.2.1为一个简单的Fortran 90 subroutine,名为test.f90,现在我们要在用f2py将其封装为一个Python模块,并在Python中调用它,在封装之前需要在原程序声明变量之后加入f2py的接口(表2.2.2,红色部分): !f2py intent(in)::a,b !f2py intent(out)::c,d 表示输入变量a,b,返回的变量为c,d。即在Python中调用该模块中的addsubroutine只需要两个参数,对应返回两个参数。 接下来,在终端中使用下述语句,其中-c 表示编译的Fortran文件,-m表示编译成的模块名: f2py -c test.f90 -m test 此时,在该目录下将会生成一个test.so的文件,即为Python调用的模块。 进入Python的命令行格式,如图2.2.1中操作,即可调用成功。 3.在海洋与大气研究中的应用——小波变换 小波变换是分析海洋与大气时间序列的一种常用方法,用以分析时间序列中的时域和频域信息。本文分析的时间序列是1870年-2000年的nino3指数,原Fortran程序是大气科学与地球流体力学数值模拟国家重点实验室的李建平教授编写的F77程序,其主要结构如图3.1.1所示。
图3.1.1 小波变换F77程序结构图 Wavetest是主程序,其中调用的subroutine都在wavelet.f、chisqr.f、cfftpack.f中。因此要将该程序封装成Python的模块,只需要将wavetest改成一个subroutine,并提前编译其他几个F77文件,在使用f2py命令时,指定特定的库即可。具体操作如下: (1)将主程序改成一个subroutine。可以通过编写接口自由指定所需要传出的变量,其中wave,signif,period分别表示功率谱变量,进行统计检验后的变量和时间尺度。
(2)编译库文件 gfortran -c -fPICwavelet.f chisqr.f cfftpack.f 最终生成,wavelet.o,chisqr.o,cfftpack.o库文件。 (3)f2py命令封装成Python模块 f2py -c –-fcompiler=gfortran -I wavelet.ochisqr.o cfftpack.o -m wave wavetest.f 其中,--fcompiler指定编译器,-I 指定链接的库文件,-m模块名,-c封装的subroutine (4)在python中调用模块并绘图 编写wave.py程序:
命令行: python wave.py 输出结果: 5.在使用中需要注意的问题 (1) 数据类型 Numpy 默认的数据类型为float64也就是双精度浮点数,所以Fortran里的浮点数也必须是双精度的,需要声明real*8,默认的real是单精度的,不会报错但是会造成内存溢出。 (2) 数组行列关系 一般在使用Fortran的时候需要注意二维数组的行列关系的问题。即Fortran里面的数组是先填充一列,再填充一行,而Python数组遵循C语法规范,先填充一行,再填充一列。利用f2py进行参数传递时,已经进行过智能转换,所以不需要考虑该问题,按照相同的方式使用即可。 (3) 数组的传递 在调用时,输入变量跟维数有关的信息必须放置在最后。例如,函数名为foo(a,b,c,d,n),这里的a、b、c、d都是普通的变量或数组,但n必须是一个跟维数有关的变量,用来在Fortran程序中定义数组使用。如果将维数放在最前面可能出现的错误是:“(shape(u,0)==m)failed for1st keyword m: vector2:m=0” (4)编写接口 加intent(out)之后,会把python对应函数中的相应变量隐藏,也就是不需要输入了。接口中的虚参不存在,intent(inout)属性,因为在python中不认可,如果一个虚参具备intent(inout)属性,则会出现以下报错:” ValueError:failed to initialize intent(inout) array -- inputnot fortran contiguous --input 'l' not compatible to 'd'” 6.总结 本文重点讲述了在Python中调用Fortran的方法,具体做法是将Fortran主程序改写成subroutine,并使用f2py封装,编译时指定Fortran程序调用的库文件。并且,通过改写一个小波变换的Fortran程序,展示了该方法在海洋与大气研究中的应用。总的说来,该方法使用起来非常的简单高效,掌握该方法,定会在以后的研究中有不小的助益。
说明:本文的所有代码均在压缩文件中,利用上述命令,在Linux环境下直接运行即可。
|