在FORTRAN 77

时间:2017-01-25 16:35:09

标签: loops fortran iteration fortran77

我编写了一个简单的FORTRAN 77 code,用于使用特定的迭代方案(Neta的第六顺序)数值求解方程。

然后我做了一个简单的改变。特别是,我将整个迭代方案从主循环内部转移到外部子程序中。但是,新revised code的结果与之前的结果不匹配。

任何想法为什么?我想一定有一个简单的琐碎错误,但是我看不到!毋庸置疑,任何有关使代码更高效或更快的评论都非常受欢迎。

非常感谢提前。

原始代码

  PROGRAM NETA_P6

  DOUBLE PRECISION tol,acc,Re0,Im0,Re,Im,Ref,Imf
  DOUBLE PRECISION b,d1,d2
  DOUBLE COMPLEX z0,z1,zf,dz,F,DF
  DOUBLE COMPLEX un,yn,zn
  INTEGER iter,iterf,max_iter

  DOUBLE PRECISION a,Q
  COMMON /param/a,Q

  Re0=-5d0
  Im0=-5d0

  a=0d0
  Q=0d0
  tol=1d-15
  acc=1d-10
  max_iter=500

  z0=DCMPLX(Re0,Im0)
  iter=0

  DO
    un=F(z0)/DF(z0)
    b=-0.5d0
    yn=z0-un
    zn=yn-F(yn)/DF(z0)*(F(z0)+b*F(yn))/(F(z0)+(b-2d0)*F(yn))
    d1=ABS(yn)
    d2=ABS(yn-zn)
    IF(d1.LT.tol)THEN
      z1=z0
    ELSEIF(d2.LT.tol)THEN
      z1=yn  
    ELSE  
      z1=zn-F(zn)/DF(z0)*(F(z0)-F(yn))/(F(z0)-3d0*F(yn)) 
    ENDIF
    dz=z1-z0
    Re=DABS(DBLE(dz))
    Im=DABS(DIMAG(dz))
    iter=iter+1
    WRITE(*,10)iter,dz,z1
    IF((Re.LT.tol.AND.Im.LT.tol).OR.iter.GE.max_iter)GOTO 7
    z0=z1
  END DO

  7    CONTINUE

  zf=z1
  Ref=DBLE(zf)
  Imf=DIMAG(zf)
  iterf=iter

 c     ELIMINATING VERY SMALL NUMBERS < 1d-15 

  IF(DABS(Ref).LT.acc)Ref=0d0
  IF(DABS(Imf).LT.acc)Imf=0d0

  WRITE(*,*)
  WRITE(*,*)'------------------------------------------'      
  IF(iter.LT.max_iter)THEN
    WRITE(*,*)'FOR THE INITIAL POINT WITH:'
    WRITE(*,11)Re0
    WRITE(*,12)Im0
    WRITE(*,*)'THE METHOD CONVERGED TO: '
    WRITE(*,13)Ref
    WRITE(*,14)Imf
    WRITE(*,15)iter
  ELSEIF(iter.GE.max_iter)THEN
    WRITE(*,*)'FOR THE INITIAL POINT WITH:'
    WRITE(*,11)Re0
    WRITE(*,12)Im0
    WRITE(*,*)'THE METHOD DID NOT CONVERGE' 
    WRITE(*,15)iter
  ENDIF
  WRITE(*,*)'------------------------------------------'

c     FORMATS
10   FORMAT(2x,'i = ',i3,/2x,'dz  = ',2(2x,E22.16),/2x,
 & 'z_0 = ',2(2x,E22.16))
11   FORMAT(1x,'Re[z0]  = ',F22.16)   
12   FORMAT(1x,'Im[z0]  = ',F22.16)
13   FORMAt(1x,'Re[zf]  = ',E22.16)
14   FORMAT(1x,'Im[zf]  = ',E22.16)
15   FORMAT(1x,'AFTER N = ',i3,' ITERATIONS')

  PAUSE

  END
  DOUBLE COMPLEX FUNCTION F(z)  ! main function
  DOUBLE COMPLEX z

  DOUBLE PRECISION a,Q
  COMMON /param/a,Q

  F=3d0*z-z/(SQRT(z**2))**3*(1d0+3d0*a/2d0/(SQRT(z**2))**2)-Q

  RETURN
  END
  DOUBLE COMPLEX FUNCTION DF(z)  ! first order derivative
  DOUBLE COMPLEX z

  DOUBLE PRECISION a,Q
  COMMON /param/a,Q

  DF=(3d0*z**6+2d0*SQRT(z**2)*(3d0*a+z**2))/z**6

  RETURN
  END

修订后的代码

  PROGRAM NETA2_P6

  DOUBLE PRECISION tol,acc,Re0,Im0,Re,Im,Ref,Imf
  DOUBLE PRECISION b,d1,d2
  DOUBLE COMPLEX z0,z1,zf,dz,F,DF
  DOUBLE COMPLEX un,yn,zn,inz,outz
  INTEGER iter,iterf,max_iter

  DOUBLE PRECISION a,Q
  COMMON /param/a,Q

  Re0=-5d0
  Im0=-5d0

  a=0d0
  Q=0d0
  tol=1d-15
  acc=1d-10
  max_iter=500

  z0=DCMPLX(Re0,Im0)
  iter=0

  DO
    inz=z0
    CALL N6(inz,outz)  
    z1=outz
    dz=z1-z0
    Re=DABS(DBLE(dz))
    Im=DABS(DIMAG(dz))
    iter=iter+1
    WRITE(*,10)iter,dz,z1
    IF((Re.LT.tol.AND.Im.LT.tol).OR.iter.GE.max_iter)GOTO 7
    z0=z1
  END DO

   7    CONTINUE

  zf=z1
  Ref=DBLE(zf)
  Imf=DIMAG(zf)
  iterf=iter

 c     ELIMINATING VERY SMALL NUMBERS < 1d-15 

  IF(DABS(Ref).LT.acc)Ref=0d0
  IF(DABS(Imf).LT.acc)Imf=0d0

  WRITE(*,*)
  WRITE(*,*)'------------------------------------------'      
  IF(iter.LT.max_iter)THEN
    WRITE(*,*)'FOR THE INITIAL POINT WITH:'
    WRITE(*,11)Re0
    WRITE(*,12)Im0
    WRITE(*,*)'THE METHOD CONVERGED TO: '
    WRITE(*,13)Ref
    WRITE(*,14)Imf
    WRITE(*,15)iter
  ELSEIF(iter.GE.max_iter)THEN
    WRITE(*,*)'FOR THE INITIAL POINT WITH:'
    WRITE(*,11)Re0
    WRITE(*,12)Im0
    WRITE(*,*)'THE METHOD DID NOT CONVERGE' 
    WRITE(*,15)iter
  ENDIF
  WRITE(*,*)'------------------------------------------'

 c     FORMATS
 10   FORMAT(2x,'i = ',i3,/2x,'dz  = ',2(2x,E22.16),/2x,
 & 'z_0 = ',2(2x,E22.16))
 11   FORMAT(1x,'Re[z0]  = ',F22.16)   
 12   FORMAT(1x,'Im[z0]  = ',F22.16)
 13   FORMAt(1x,'Re[zf]  = ',E22.16)
 14   FORMAT(1x,'Im[zf]  = ',E22.16)
 15   FORMAT(1x,'AFTER N = ',i3,' ITERATIONS')

  PAUSE

  END
  DOUBLE COMPLEX FUNCTION F(z)  ! main function
  DOUBLE COMPLEX z

  DOUBLE PRECISION a,Q
  COMMON /param/a,Q

  F=3d0*z-z/(SQRT(z**2))**3*(1d0+3d0*a/2d0/(SQRT(z**2))**2)-Q

  RETURN
  END
  DOUBLE COMPLEX FUNCTION DF(z)  ! first order derivative
  DOUBLE COMPLEX z

  DOUBLE PRECISION a,Q
  COMMON /param/a,Q

  DF=(3d0*z**6+2d0*SQRT(z**2)*(3d0*a+z**2))/z**6

  RETURN
  END
  SUBROUTINE N6(z0,z1)

  DOUBLE PRECISION b,d1,d2,tol      
  DOUBLE COMPLEX z0,z1,F,DF
  DOUBLE COMPLEX un,yn,zn

  tol=1d-15
  un=F(z0)/DF(z0)
  b=-0.5d0
  yn=z0-un
  zn=yn-F(yn)/DF(z0)*(F(z0)+b*F(yn))/(F(z0)+(b-2d0)*F(yn))
  d1=ABS(yn)
  d2=ABS(yn-zn)
  IF(d1.LT.tol)THEN
    z1=z0
  ELSEIF(d2.LT.tol)THEN
    z1=yn  
  ELSE  
    z1=zn-F(zn)/DF(z0)*(F(z0)-F(yn))/(F(z0)-3d0*F(yn)) 
  ENDIF

  RETURN
  END

0 个答案:

没有答案