1

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

1 回答 1

2

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

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

于 2014-09-22T02:38:44.313 回答