Fortran 77 Code中的EQUIVALENCE语句出现问题

时间:2014-09-21 22:19:12

标签: fortran fortran77 equivalence fortran-common-block

我正在努力让光线跟踪代码正常工作,我想我可能已经解决了这个问题。我是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)

1 个答案:

答案 0 :(得分:2)

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

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