F90编译器相关代码

时间:2014-02-13 17:05:59

标签: fortran fortran90 gfortran intel-fortran fortran77

我尝试运行我的f90代码。它是旧f77代码的转换版本。

当我尝试用不同的编译器(IFORT,GFORTRAN)编译它时,我有两个不同的结果: 使用两个编译器自己运行程序,看看,对于GNUplot的istance,情节:

plot 'orbitm.txt' u 1:2

使用两个编译器,绘图的输出非常不同!

我认为这种不同依赖于COMMON命令以这种方式,我尝试用MODULE替换它,但我发现了一些错误。

我按照评论的建议对我的代码进行了一些更改:

     module data
      REAL*8 :: OME = 1.D0
      REAL*8 :: MU = 0.000954
     end module


      PROGRAM MAIN
      use data
      IMPLICIT NONE
      REAL*8  :: dist0 , dt , duepi , e , e0 , ermed , errh , H , k_max_r8
      REAL*8  :: ptau , ptau0 , px , px0 , py , py0 , t , tau , tau0 , n_step_r8
      REAL*8  :: t_per, x , x0 , y , y0, k_r8 , m_per
      INTEGER :: k , k_max  , n_step

      duepi = 8.d0*DATAN(1.D0)
      !duepi = 2.d0*3.1415926535897932d0
      t_per = duepi/OME
      n_step = 1000

!         do iX0=1,6
!          do iY0=-50,50

!       x0 = (0.5d0-MU)+(0.0001*iX0) !và da 0.449 a 0.599
!                y0 = (sqrt(3.d0)/2.d0)+(0.0001*iY0) ! va da 0.868 a 0.864

      OPEN (UNIT=11,FILE='orbitm.txt') 
      x0 = 0.47
      y0 = SQRT(3.D0)/2.D0
      tau0 = 0.d0
      px0 = OME*y0
      py0 = -OME*x0
      ptau0 = 1.d0

      x = x0
      y = y0
      tau = tau0
      px = px0
      py = py0
      ptau = ptau0
      n_step_r8 = real(n_step)
      dt = t_per/n_step_r8
      e0 = H(x,y,tau,px,py,ptau)

      k_max = 1000*n_step

      k = 0
      t = 0.d0
      errh = 0.d0

!---------
!  inizio loop integrazione
!--------
      ermed = 0.d0

      DO k = 1 , k_max
         k_r8 = real(k)
         CALL SYM4(x,y,tau,px,py,ptau,dt)
         e = H(x,y,tau,px,py,ptau)
         errh = ABS(e-e0)
         t = k_r8*dt
         IF ( MOD(k,n_step).EQ.0 ) THEN
            WRITE (11,'(4g12.5)') x , y , px , py
         ENDIF
      ENDDO
      k_max_r8 = real(k_max)



      DO k = 1 , k_max
         CALL SYM4(x,y,tau,px,py,ptau,-dt)
         e = H(x,y,tau,px,py,ptau)
         errh = ABS(e-e0)
         t = t - dt
      ENDDO
!           write(*,*) ix0,ermed,errh
!              enddo ! iY0
!            enddo ! iX0

!           close(11)
      END


      REAL*8 FUNCTION H(X,Y,Tau,Px,Py,Ptau)
      use data
      IMPLICIT NONE
      REAL*8 :: c , Ptau , Px , Py , r1 , r2 , s , Tau , X , Y

      c = COS(OME*Tau)
      s = SIN(OME*Tau)

      r1 = SQRT((X+MU*c)**2+(Y-MU*s)**2)
      r2 = SQRT((X-(1.d0-MU)*c)**2+(Y+s*(1.d0-MU))**2)

      H = (Px*Px)/2.D0 + (Py*Py)/2.D0 + Ptau - (1.d0-MU)/r1 - MU/r2

      END


      SUBROUTINE F(X,Y,Tau,Fx,Fy,Ftau)
      use data
      IMPLICIT NONE
      REAL*8 :: c, Ftau , Fx , Fy , r1 , r2 , s , Tau , X , Y

      c = COS(OME*Tau)
      s = SIN(OME*Tau)

      r1 = SQRT((X+MU*c)**2+(Y-MU*s)**2)
      r2 = SQRT((X-(1.d0-MU)*c)**2+(Y+s*(1.d0-MU))**2)


      Fx = -((1.d0-MU)*(X+MU*c))/r1**3 - (MU*(X-c*(1.d0-MU)))/r2**3
      Fy = -((1.d0-MU)*(Y-MU*s))/r1**3 - (MU*(Y+s*(1.d0-MU)))/r2**3

      Ftau = -( (1.d0-MU)*OME*MU*(-s*(X+MU*c)-c*(Y-MU*s)) )/r1**3.d0 - ( MU*(1.d0-MU)*OME*(s*(X-(1.d0-MU)*c)+c*(Y+(1.d0-MU)*s)) )/r2**3.d0

      END



      SUBROUTINE SYM2(X,Y,Tau,Px,Py,Ptau,Dt)
      IMPLICIT NONE
      REAL*8 :: Dt , ftau , ftaunew , fx , fxnew , fy , fynew , Ptau
      REAL*8 :: ptaunew , Px , pxnew , Py , pynew , Tau , taunew , X
      REAL*8 :: xnew , Y , ynew

      CALL F(X,Y,Tau,fx,fy,ftau)


      xnew = X + Px*Dt + fx*(Dt**2.d0)/2.D0

      ynew = Y + Py*Dt + fy*(Dt**2.d0)/2.D0

      taunew = Tau + Dt

      CALL F(xnew,ynew,taunew,fxnew,fynew,ftaunew)
      pxnew = Px + Dt*(fx+fxnew)/2.D0
      pynew = Py + Dt*(fy+fynew)/2.D0
      ptaunew = Ptau + Dt*(ftau+ftaunew)/2.D0

      X = xnew
      Y = ynew
      Tau = taunew
      Px = pxnew
      Py = pynew
      Ptau = ptaunew

      END

      SUBROUTINE SYM4(X,Y,Tau,Px,Py,Ptau,Dt)
      IMPLICIT NONE
      REAL*8 :: alpha , beta , Dt , dt1 , dt2 , Ptau , Px , Py , sq2
      REAL*8 :: Tau , X , Y
      sq2 = 2.d0**(1.D0/3.D0)
      alpha = 1.D0/(2.d0-sq2)
      beta = sq2/(2.d0-sq2)
      dt1 = Dt*alpha
      dt2 = -Dt*beta
      CALL SYM2(X,Y,Tau,Px,Py,Ptau,dt1)
      CALL SYM2(X,Y,Tau,Px,Py,Ptau,dt2)
      CALL SYM2(X,Y,Tau,Px,Py,Ptau,dt1)
      END

现在,IFORT和GFORTRAN之间的编译差异很小但不等于零。 我可以用其他处方改进更多的代码,例如:更改调用或函数,拆分子程序或引入其他模块吗?

非常感谢!

1 个答案:

答案 0 :(得分:2)

我建议插入中间输出语句并查看结果首先分歧的位置。 Possiblities:仅在一个编译器中显示的错误。您可能会看到突然的,离散的变化。尝试回到最初发生变化的地方作为问题的线索。或者差异可能是算法中数值不稳定的结果。在这种情况下,差异将开始非常小并且增长。对于两个编译器生成的可执行文件,数值运算的顺序可能不完全相同,这可能会对某些计算产生影响。

我发现将遗留的FORTRAN 77代码移植到现代编译器中的一个常见问题是许多旧的FORTRAN 77程序假定所有局部变量都是save。这是语言标准的保证,但并不是一种常见的行为。您可以使用编译器选项恢复该行为。见Are local variables in Fortran 77 static or stack dynamic?