登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
如何使用ncl调用Fortran子函数 首先申明,调用在cygwin下是行不通的,如果只能用cygwin,那本文不适合你。 如果你想从ncl下调用Fortran程序,那基本思想是把Fortran子程序编译成一个可以被ncl调用的共享对象(shared object),再利用"external" statemen将其载入ncl并调用该程序。那如何将Fortran子程序编译成共享对象(sharedobject)呢?下面我们讲如何利用WRAPIT将Fortran子程序编译成共享对象。 首先,写一段包装文本: 对于Fortran77程序,将该程序改写,用分隔文本"C NCLFORTSTART" 和 "CNCLEND"把申明部分包在中间。例如:对于一段"ex01.f"的程序: C NCLFORTSTART subroutine cquad (a, b, c, nq, x, quad) real x(nq), quad(nq) C NCLEND C C Calculate quadratic polynomial values. C do 10 i=1,nq quad(i) = a*x(i)**2 + b*x(i) + c 10continue return end C NCLFORTSTART function arcln (numpnt, pointx, pointy) dimension pointx(numpnt),pointy(numpnt) C NCLEND C C Calculate arc lengths. C if (numpnt .lt. 2) then print *, 'arcln: number of points must be at least 2' stop endif arcln = 0. do 10 i=2,numpnt pdist = sqrt((pointx(i)-pointx(i-1))**2 + + (pointy(i)-pointy(i-1))**2) arcln = arcln + pdist 10continue return end 只需要将所有的变量用分隔文本"C NCLFORTSTART" 和 "CNCLEND"括住。 然而对于Fortran90程序,则需要另写一份文本(以.stub结尾):对于一个名为"cquad.f90"的程序: subroutine cquad(a,b,c,nq,x,quad) implicit none integer, intent(in) ::nq real, intent(in) ::a,b,c,x(nq) real, intent(out) ::quad(nq) integer ::i quad = a*x**2+b*x+c return end subroutine cquad 需要另外创建一份名为"cquad90.stub"的文本: C NCLFORTSTART subroutine cquad(a,b,c,nq,x,quad) real a,b,c integer nq dimension x(nq),quad(nq) C NCLEND 第二步,用WRAPIT编译 对于前面的Fortran77程序ex01.f 使用 WRAPIT ex01.f 生成一个名为"ex01.so"的文件 而对于前面的Fortran90程序cquad.f90则使用 WRAPIT cquad90.stub cquad.f90 生成"cquad90.so" 第三步使用ncl调用共享对象 有两种方法: 方法一:使用external声明 在begin之前用"external"声明载入共享对象,例如external EX01 "./ex01.so" external后面跟你想要的共享对象的名称,之后再给路径。然后就可以在ncl中调用该函数(函数之前需要加上你命名的共享对象和两个冒号如(EX01::arcln)完整例子如下: external EX01 "./ex01.so" begin ; ; Calculate three values of a quadraticequation ; nump = 3 x = (/ -1., 0.0, 1.0 /) qval = new(nump,float) EX01::cquad(-1., 2., 3., nump, x, qval) ; Call the NCL version of ;your Fortran subroutine. print("Polynomial value = " + qval) ; Should be (/0,3,4/) ; ; Calculate an arc length. ; xc= (/ 0., 1., 2. /) yc= (/ 0., 1., 0. /) arclen = EX01::arcln(nump,xc,yc) ; Call the NCL version of ; yourFortran function. print("Arc length = " + arclen) ; should be 2.82843 end 第二种方法用环境变量载入共享对象 建立一个共享对象的目录设成NCL_DEF_LIB_DIR的环境变量 如setenv NCL_DEF_LIB_DIR /home/haley/shared_objects 也可以添加多个目录 setenv NCL_DEF_LIB_DIR/home/shea/shared_objects/:/home/haley/shared_objects 现在你就可以直接像调用内部函数一样调用Fortran函数了 仍然是刚刚的例子: begin ; ; Calculate three values of a quadraticequation ; nump = 3 x = (/ -1., 0.0, 1.0 /) qval = new(nump,float) cquad(-1., 2., 3., nump, x, qval) ; Call the NCL version of ;your Fortran subroutine. print("Polynomial value = " + qval) ; Should be (/0,3,4/) ; ; Calculate an arc length. ; xc= (/ 0., 1., 2. /) yc= (/ 0., 1., 0. /) arclen = arcln(nump,xc,yc) ; Call the NCL version of ; yourFortran function. print("Arc length = " + arclen) ; should be 2.82843 end 基本上的方法就这些,个人比较建议建立一套自己的Fortran程序库,做成共享对象放在环境变量NCL_DEF_LIB_DIR中供ncl调用。Fortran计算速度较ncl快很多,灵活使用该方法可以节省很多计算时间。
|