FORTRAN IV/66程序在DO循环中暂停

FORTRAN IV/66程序在DO循环中暂停,fortran,gfortran,Fortran,Gfortran,我从一篇论文中复制了一个FORTRAN IV程序,所以它大概在编写时起作用。我用gfortran编译了它。运行时,它在集成子例程中暂停。我尝试过减少残留量,但没有效果。我请求帮助是因为假定gfortran代码中没有错误可能不喜欢古老的66/IV代码,更新它超出了我的能力 程序被第9行卡住了,所以我想知道是DO循环造成的。注意,第1行和第6行对我来说是不寻常的,因为“1”已添加到末尾:例如=1,N,1 我认为没有必要显示在第5行调用的FUNC子例程,但如果必要,我很乐意提供它 如果您需要更详细的信

我从一篇论文中复制了一个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

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与if-not-then在更高版本的Fortran中相同,并且计算的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语句来帮助编译器。

很难确定您的代码片段是否与源文件完全匹配,但您的问题可能来自旧的FORTRAN gotcha—第6列中的0被视为或被视为空白。第6列中的任何其他非空字符被视为连续指示符,但不是0。

并非所有f66编译器都遵守至少执行一次循环的约定,但这是一种常见的不可移植假设。 类似地,假设所有静态变量都不是可移植的,但可以通过添加SAVE语句(从f77开始)来实现。保存变量将被零初始化的进一步假设甚至更不可移植,但大多数编译器都有实现该假设的选项


如果有人试图恢复旧代码,那么在对其进行增量现代化以使其更加自文档化之前,让它工作起来可能是值得的。计算出的goto看起来是一个相对合理的goto,可以用select case替换,但可能会以优化为代价。在这里,术语现代化的最新用法变得相互矛盾。

我不知道它是否有任何帮助,但FORTRAN 66用于至少执行一次循环,即使QDP>7,或者没有一种方法是使用现代f77结构更新代码。例如,整个计算的goto-mess第7行变成了一个大的if-then构造。我同意george的观点:编写自己的代码来解决这个代码使用F90+所做的系统问题。将其翻译成现代Fortran将是一件相当繁琐的事情。gfortran似乎支持FORTRAN 77和更高版本,因此FORTRAN IV和FORTRAN 77之间的任何差异都可能导致问题,例如,一次循环功能。FORTRAN 77和早期程序中的一个常见问题是错误地假设保存了所有局部变量。您可以使用编译器选项-fno automatic在gfortran中恢复此行为,值得一试。do循环中的第三个值是步长。。。1至少是FORTRAN 77中的默认值,因此没有必要指定此值。我同意更新到现代FORTRAN将是一件麻烦事,但我认为他是从一篇旧论文中获得此值的,因为他的论文需要它。