【问题标题】:Trouble with EQUIVALENCE statements in Fortran 77 CodeFortran 77 代码中 EQUIVALENCE 语句的问题
【发布时间】:2014-09-21 22:19:11
【问题描述】:

我正在努力让光线追踪代码正常工作,我想我可能已经隔离了这个问题。我是使用 Fortran 77 的新手,但想获得更多使用这种语言的经验(即使它已经过时了)。我在其中一个子例程中有一些 EQUIVALENCE 语句,可用于将变量传递到子例程中(这可能是问题的一半)。

子程序:

c   s/r qparxdp
  SUBROUTINE QPARAB                                                 PARA001 
implicit real*8 (a-h, o-z)
character*8 modx, id
C        PLAIN PARABOLIC OR QUASI-PARABOLIC PROFILE                     PARA002 
C        W(104) = 0. FOR A PLAIN PARABOLIC PROFILE                      PARA003 
C               = 1. FOR A QUASI-PARABOLIC PROFILE                      PARA004 
  COMMON /XX/ MODX(2),X,PXPR,PXPTH,PXPPH,PXPT,HMAX                  PARA005 
  COMMON R(6) /WW/ ID(10),W0,W(400)                                 PARA006 

 EQUIVALENCE (EARTHR,W(2)),(F,W(6)),(FC,W(101)),(HM,W(102)),       PARA007 
 1 (YM,W(103)),(QUASI,W(104)),(PERT,W(150))                         PARA008 
 data ipass / 0 /

 ENTRY ELECTX                                                      PARA010 
 print*, W(2), W(6), W(101), W(102), W(103), W(104), W(150)
 print*, ' Electx W(6), f ', F, EARTHR, FC, HM, YM, QUASI, PERT, ipass
ipass = ipass + 1
if(ipass.gt.10000) ipass = 2
if(ipass.eq.1) return
  modx(1) = 'qparab'
  HMAX=HM                                                           PARA011 
x = 0.d0
pxpr = 0.d0
pxpth = 0.d0
pxpph = 0.d0
  H=R(1)-EARTHR                                                     PARA013 
if(f.le.0.d0) print*, ' YM', YM
  FCF2=(FC/F)**2                                                    PARA014 
  CONST=1.d0                                                        PARA015 
  IF (QUASI.EQ.1.d0) CONST=(EARTHR+HM-YM)/R(1)                      PARA016 
  Z=(H-HM)/YM*CONST                                                 PARA017 
  X=dMAX1(0.d0,FCF2*(1.d0-Z*Z))                                     PARA018 
  print*, 'X in qparx', X, Z
  IF (X.EQ.0.d0) GO TO 50                                           PARA019 
  IF (QUASI.EQ.1.d0) CONST=(EARTHR+HM)*(EARTHR+HM-YM)/R(1)**2       PARA020 
  PXPR=-2.d0*Z*FCF2/YM*CONST                                        PARA021 
  50 IF (PERT.NE.0.d0) CALL ELECT1                                     PARA022 
  RETURN                                                            PARA023 
     END                                                            PARA024-

在调用子例程或条目 ELECTX 之前,我在 RINDEX 子例程/条目中放置了一些打印语句。
我在调用 RINDEX 之前检查了一些输入

      ENTRY RINDEX
  write(*,*), 'Starting Rindex in ahnwfnc', F
if(ray.eq.0.d0.and.ipass.eq.0) print*, '  no magnetic field'
ipass = 1
  OM=PIT2*1.d6*F
  C2=C*C
  K2=KR*KR+KTH*KTH+KPH*KPH
  OM2=OM*OM
  VR =C/OM*KR
  VTH=C/OM*KTH
  VPH=C/OM*KPH
  write(*,*), OM, C2, K2, OM2, VR, VTH, VPH, F
  CALL ELECTX

我从这段代码中得到的是:

fstep,fbeg,fend   1.  7.  8.
fbeg,fstep,f   7.  1.  0.
f  7.  7.
f before Rindex  7.
Starting Rindex in ahnwfnc  7.
43982297.2  8.98755431E+10  1.  1.93444246E+15  0.00640514066  0.00231408417
0.000282636641  7.
0.  0.  0.  0.  0.  0.  0.
Electx W(6),f   0.  0.  0.  0.  0.  0.  0. 1

所以这是一个冗长的询问方式 - 发生了什么事?例如,我希望像 f 这样的变量被传递到子程序 QPARAB 中,所以当我在子程序中打印时,我希望看到 F = 7。我可能从根本上误解了一些简单的东西。正如我所提到的,我似乎无法将 F 之类的变量放入子例程 QPARAB 中,这实际上是一个大问题,因为以下计算结果为 0 或 NaN。我希望它有一些价值。所以也许数据没有以某种方式进入?在某种程度上,其他一切(此时)似乎都在工作。

此代码的来源:

我正在使用一个小的 shell 脚本(这可能是一团糟):

g77 -c -O3  raytr_dp.for readw_dp.for trace_dp.for reach_dp.for backup_d.for dummy.for  \
polcar_d.for printr_d.for rkam_dp.for hamltn_d.for ahwfnc_d.for \
qparxdp.for dipoly_d.for spoints.for ggm_dp.for secnds.for

g77 -o main -O3 raytr_dp.o readw_dp.o trace_dp.o reach_dp.o backup_d.o dummy.o \
polcar_d.o printr_d.o rkam_dp.o hamltn_d.o ahwfnc_d.o \
qparxdp.o dipoly_d.o spoints.o ggm_dp.o secnds.o

我正在使用的 g77 例程在:http://hpc.sourceforge.net/ 下载,最后我使用 gfortran 得到同样的错误,

Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/local/gfortran/libexec/gcc/x86_64-apple-darwin13/4.9.0/lto-wrapper
Target: x86_64-apple-darwin13
Thread model: posix
gcc version 4.9.0 (GCC)

【问题讨论】:

  • Fortran 77 代码中的 EQUIVALENCE 语句存在问题 是的,这就是我们现在像避免瘟疫一样避免它们的原因。
  • 在这种情况下,等价似乎仅用于为数组w中的特定位置提供方便的名称。 f 之类的符号是子例程的本地。在子例程外部,这些东西需要由数组位置引用(当然,除非您在调用例程中有类似的equivalence 语句。

标签: fortran fortran77 equivalence fortran-common-block


【解决方案1】:

子程序QPARAB 不带参数,例如没有任何东西传递给它。它从公共块(范围之间共享的变量)中加载以下变量MODXXPXPRPXPTHPXPPHPXPTHMAXIDW0,和W。此外,它声明了局部范围变量modxid,然后将隐式类型分配给所有未声明的变量(在范围内是局部的)。

您感兴趣的变量F 相当于写W(6)。这表示隐式变量 F(类型 real*8)必须与 W(6) 具有相同的内存位置。 F 没有传递到这个子例程中,它是子例程的本地名称,它实际上是W 的特定数组成员。如果要将值传递给子程序到F,则需要在调用子程序之前设置变量W(6)。请注意,为了做到这一点,您将需要W 在范围内,因此您将需要在您调用的子程序中引用的/WW/ 公共块。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多