4

我从一篇论文中复制了一个 FORTRAN IV 程序,所以它可能在编写它的时候就可以工作。我用 gfortran 编译它。运行时,它停在一个积分子程序中。我曾尝试减轻残留物,但无济于事。我寻求帮助是因为(假设代码中没有错误)gfortran 可能不喜欢古老的 66/IV 代码,并且更新它超出了我的能力范围。

程序被第 9 行卡住了,所以我想知道 DO 循环是否负责。请注意,第 1 行和第 6 行对我来说是不寻常的,因为 ',1' 已添加到末尾:例如 =1,N,1。

我认为没有必要显示在第 5 行调用的 FUNC 子例程,但如果有必要,我很乐意提供它。

如果您需要更详细的信息,我很乐意提供。

00000001 13  DO 22 TDP=QDP,7,1
00000002     TD=TDP-1
00000003     X=X0+H0
00000004     IF(TD.EQ.QD) GOTO 15
00000005     CALL FUNC(N,DY,X,Y,J)   
00000006 15  DO 21 RD=1,N,1
00000007     GOTO (120,121,122,123,124,125,126),TDP
00000008 120     RK(5*N*RD)=Y(RD)
00000009     GOTO 21
00000010 121     RK(RD)=HD*DY(RD)
00000011     H0=0.5*HD
00000012     F0=0.5*RK(RD)
00000013     GOTO 20
00000014 122     RK(N+RD)=HD*DY(RD)
00000015     F0=0.25*(RK(RD)+RK(N+RD))
00000016     GOTO 20
00000017 123     RK(2*N+RD)=HD*DY(RD)
00000018     H0=HD
00000019     F0=-RK(N+RD)+2.*RK(2*N+RD)
00000020     GOTO 20
00000021 124     RK(3*N+RD)=HD*DY(RD)
00000022     H0=0.66666666667*HD
00000023     F0=(7.*RK(RD)+10.*RK(N+RD)+RK(3*N+RD))/27.
00000024     GOTO 20
00000025 125     RK(4*N+RD)=HD*DY(RD)
00000026     H0=0.2*HD
00000027     F0=(28.*RK(RD)-125.*RK(N+RD)+546.*RK(2*N+RD)+54.*RK(3*N+RD)-
00000028    1378.*RK(4*N+RD))/625.
00000029     GOTO 20
00000030 126     RK(6*N+RD)=HD*DY(RD)
00000031     F0=0.1666666667*(RK(RD)+4.*RK(2*N+RD)+RK(3*N+RD))
00000032     X=X0+HD
00000033     ER=(-42.*RK(RD)-224.*RK(2*N+RD)-21.*RK(3*N+RD)+162.*RK(4*N+RD)
00000034    1+125.*RK(6*N+RD))/67.2
00000035     YN=RK(5*N+RD)+F0
00000036     IF(ABS(YN).LT.1E-8) YN=1
00000037     ER=ABS(ER/YN)
00000038     IF(ER.GT.G0) GOTO 115
00000039     IF(ED.GT.ER) GOTO 20
00000040     QD=-1
00000041 20  Y(RD)=RK(5*N+RD)+F0
00000042 21  CONTINUE
00000043 22  CONTINUE
4

3 回答 3

3

很难确定(不完全确定您的代码段与源文件完全匹配),但您的问题可能来自旧的 FORTRAN 陷阱——0第 6 列中的 a 被(或者更确切地说是)视为空白。第 6 列中的任何其他(非空白)字符都被/被视为继续指示符,但不是0.

于 2013-06-07T12:51:57.567 回答
1

并非所有 f66 编译器都遵守至少执行一次循环的约定,但这是一个常见的(不可移植的)假设。同样,所有静态变量的假设也不是可移植的,但可以通过添加一条以 f77 开头的 SAVE 语句来实现。SAVE 变量将被零初始化的进一步假设更加不可移植,但大多数编译器都可以选择实现它。

如果正在尝试恢复旧代码,那么在逐步对其进行现代化改造以使其更具自我记录性之前,可能值得让它工作。计算出的 goto 看起来像是一个相对健全的 goto,可以用 select case 替换,但可能会以优化为代价。在这里,“现代化”一词最近的使用变得矛盾。

于 2015-10-09T14:00:36.663 回答
0

,1 位是为了让编译器发现错误。执行以下操作很常见

DO 10 I = 1.7

这是完全合法的,因为变量名中允许使用空格。如果您想避免这种情况,请输入额外的数字。以下会产生错误

DO 10 I = 1.7,1
DO 10 I = 1,7.1
DO 10 I = 1.7.1

如果程序被击中,请尝试在标签 21 和 22 之间放置一个续行。 if-goto 与 Fortran 更高版本中的 if-not-then 相同,并且计算的 goto 与 select 语句相同。您无需重新编码:除了年轻人看到 goto 时会感到困惑之外,它没有任何问题。您需要做的就是缩进它,它变得很明显。所以你将拥有的是

    DO 22 TDP = QDP, 7, 1
       ...
       DO 23 RD = 1, N, 1
          GOTO (...) TDP
             ...
             GOTO 21
             ...
             GOTO 20
             ...
             GOTO 20
             ...
20        CONTINUE
          Y(RD) = ...
21        CONTINUE
23      CONTINUE
22   CONTINUE

如果你尝试重新编码,你可能会得到更多的代码。它看起来完全一样,只是 gotos 已被其他单词替换。编译器可能会生成错误的代码,因此只需通过放置一些虚拟 (CONTINUE) 语句来帮助它。

于 2013-06-06T23:08:50.047 回答