爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 41121|回复: 60

[经验总结] 如何使用ncl调用Fortran子函数

  [复制链接]

新浪微博达人勋

发表于 2014-6-12 09:18:52 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
如何使用ncl调用Fortran子函数
首先申明,调用在cygwin下是行不通的,如果只能用cygwin,那本文不适合你。
如果你想从ncl下调用Fortran程序,那基本思想是把Fortran子程序编译成一个可以被ncl调用的共享对象(shared object),再利用"external" statemen将其载入ncl并调用该程序。那如何将Fortran子程序编译成共享对象(sharedobject)呢?下面我们讲如何利用WRAPITFortran子程序编译成共享对象。
首先,写一段包装文本:
对于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快很多,灵活使用该方法可以节省很多计算时间。

评分

参与人数 7威望 +2 金钱 +91 贡献 +22 收起 理由
DDJBHPXJ + 20 + 2 很给力!
winters + 5 赞一个!
si_su + 2 很给力!
chongzika + 2 赞一个!
mofangbao + 20 + 10
言深深 + 20 + 8
二爷名声在外 + 2 + 22 + 2

查看全部评分

本帖被以下淘专辑推荐:

  • · WRAPIT|主题: 1, 订阅: 0
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 0
发表于 2014-6-12 09:19:34 | 显示全部楼层
沙发走起!
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

发表于 2014-6-12 09:31:27 | 显示全部楼层
好贴啊!
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

发表于 2014-6-12 09:35:05 | 显示全部楼层
不明觉厉
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2014-6-12 09:49:15 | 显示全部楼层
你们太给面子了……
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 32430
发表于 2014-6-12 09:54:41 | 显示全部楼层

光顾着给分忘记抢沙发了……
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 0
发表于 2014-6-12 14:29:04 | 显示全部楼层
二爷名声在外 发表于 2014-6-12 09:54
光顾着给分忘记抢沙发了……

你抢了评分的沙发···
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 32430
发表于 2014-6-12 14:46:20 | 显示全部楼层
言深深 发表于 2014-6-12 14:29
你抢了评分的沙发···

这个……
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2014-6-12 19:16:41 | 显示全部楼层
看起来好高大上,学习一下…
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2014-6-16 19:45:47 | 显示全部楼层
支持  前段时间用官网上的说明 尝试了一下 没成功   这次在试试楼主的  但愿能够成功
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表