2014-02-13 6 views
0

나는 내 f90 코드를 실행하려고합니다. 그것은 '입니다. 변환 된 버전의 오래된 f77 코드입니다. F90 컴파일러 종속 코드

내가 다른 컴파일러로 컴파일하려고

(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 사이의 컴파일의 차이는 작지만 0이 아닌 위치 : 코멘트에서 권장하는

나는 내 코드에 약간의 변화를 넣어. 다른 처방전으로 더 많은 코드를 개선 할 수 있습니까? 예 : 전화 또는 기능 변경, 서브 루틴 분할 또는 다른 모듈 소개?

고맙습니다.

+0

두 컴파일러 모두에서 F77 버전을 실행할 때 차이점이 있습니까? – cup

+0

두 파일 모두'(0,0)'에서'(48000,13000)'까지의 직선처럼 보입니다. 나는 어떤 종류의 "매우 다른"것들을보아야합니까? –

+1

나는 코드를 실행하지 않고 내장을 통해 문제를 발견하게 될 것입니다. 너 자신을 찾기 위해 무엇을 했니? 정말로 '공통'블록에 있다고 생각한다면 단순히 모든 범위의 매개 변수로 대체하지 않는 이유는 두 개의 변수 만 포함하고 있기 때문입니다. –

답변

2

중간 출력 명령문을 삽입하고 결과가 처음으로 분기되는 위치를 확인하는 것이 좋습니다. Possiblities : 하나의 컴파일러에서만 발견되는 버그. 갑작스런 이산 변화가 나타날 수 있습니다. 변화가 처음 발생하는 곳을 문제의 단서로 삼아보십시오. 또는 차이점은 알고리즘의 수치 적 불안정성의 결과 일 수 있습니다. 이 경우 차이가 매우 작아지고 커집니다. 수치 연산의 순서는 2 개의 컴파일러에 의해 만들어진 실행 파일에 대해 정확히 동일하지 않을 수 있으며 이는 일부 계산에서 차이를 만들 수 있습니다.

레거시 FORTRAN 77 코드를 현대 컴파일러로 이식하는 데 공통적으로 발생하는 문제는 많은 구형 FORTRAN 77 프로그램이 모든 로컬 변수가 save 인 것으로 가정했기 때문입니다. 이것은 언어 표준에 의해 보장되었지만 보증되지는 않았지만 일반적인 행동이었습니다. 컴파일러 옵션을 사용하여 해당 동작을 복원 할 수 있습니다. Are local variables in Fortran 77 static or stack dynamic?