【问题标题】:Convert common block to module将公共块转换为模块
【发布时间】:2014-05-05 20:29:17
【问题描述】:

我是一名研究人员,正在研究一个用 Fortran 编写的程序。我有非常基本的编码技能,所以我需要一些帮助才能正确编译一些代码。

在显示代码之前,我将提供一些背景知识。我正在处理大量数据,这将需要 64 位编译和大于 2 GB 的内存。我在代码中注意到的第一件事是许多变量被写成“真实”,但在我的研究中我发现“双精度”允许更大的变量,并且会是一个更灵活的选择,所以我改变了所有“真实”变量到“双精度”变量。

还有一个包含在 fortran 构建文件“dist.f”的编译中的文件,称为“geocoord.inc”。我发现变量被保存到一个公共块中,但我再次需要一些可以容纳大量数据的东西。正如我一直相信的那样,模块将是一个更好的程序。我需要一些建议来将此包含文件转换为与模块程序一起正常工作,我将在下面列出。

Dist.f:

c Convert latitude and longitude to kilometers relative
c to center of coordinates by short distance conversion.

subroutine dist(xlat, xlon, xkm, ykm)

implicit none

c   Parameters:
double precision    xlat, xlon  ! (input)
double precision        xkm, ykm    ! (output)

c   Local variables:
double precision lat1, lat2, lat3
double precision    q
double precision    xx
double precision    yp

include "geocoord.inc"

c Set up short distance conversion by subr. SETORG
  q=60*xlat-olat
  yp=q+olat
  lat1=datan(rlatc*dtan(RAD*yp/60.0))
  lat2=datan(rlatc*dtan(RAD*OLAT/60.0))
  LAT3=(LAT2+LAT1)/2.
  xx=60*xlon-olon  !  - wegen LON E
  q=q*aa
  xx = xx*bb*dcos(LAT3)
  IF(rotate.ne.0.) then
c** rotate coordinate system anticlockwise
    yp=cost*q+sint*xx
    xx=cost*xx-sint*q
    q=yp
  ENDIF

  xkm=xx
  ykm=q

  return
  end

Geocoord.inc:

double precision rearth
double precision ellip
double precision rlatc
double precision rad
double precision olat, olon
double precision aa, bb, bc
double precision sint, cost
double precision rotate
integer icoordsystem

common /GEO_COORSYSTEM/ rearth, ellip, rlatc, rad,
&    olat, olon, aa, bb, bc, sint, cost, rotate,
&    icoordsystem

感谢您提供的任何建议,并为我对 Fortran 的所有事情的相对无知表示歉意!

【问题讨论】:

    标签: module fortran fortran90 double-precision fortran-common-block


    【解决方案1】:

    对旧代码进行现代化改造通常不是一件容易的事。至少对于初学者来说。从real 到double precision 的转变不符合现代Fortran 的精神,但在你引入模块之前它是可以的。当你有模块时,最好这样做:

    module precisions
      integer, parameter :: rp = kind(1.d0) !if you insist on double, otherwise use selected_real_kind()
    end module
    

    并且在任何地方都使用新的类型常量来表示您的真实精度:

      use precisions
    
          real(rp) :: variables
    

    对于常见的块,您展示的将是:

    module geo_coordsystem
      use precisions
    
      implicit none
    
      real(rp) :: rearth
      real(rp) ::  ellip
      real(rp) ::  rlatc
      real(rp) ::  rad
      real(rp) ::  olat, olon
      real(rp) ::  aa, bb, bc
      real(rp) ::  sint, cost
      real(rp) ::  rotate
      integer icoordsystem
    
    end module
    

    那你就用它吧:

    subroutine dist(xlat, xlon, xkm, ykm)
      use precisions
      use geo_coordsystem
    
      implicit none
    

    您还可以不断地将子例程移动到模块中。以小步骤执行此操作,并始终检查您没有引入一些错误。

    【讨论】:

    • 小步骤进行更改和测试的建议非常明智!您可能想要创建一组回归测试。
    【解决方案2】:

    一些 Fortran 编译器可以选择将实变量提升为双精度。在 gfortran 中,选项是 -fdefault-real-8 ,如 http://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html 中所述。从长远来看,最好按照 Vladimir F 的建议使用种类。

    【讨论】:

      猜你喜欢
      • 2016-06-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2018-05-21
      • 1970-01-01
      • 2020-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多