我编写了一个简单的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