Newton's iterative algorithm to find the root of function FR(x(:)) in the interval [a(:),b(:)], using d/dx(:)F(x)=0 and the derivative
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | tol |
abort tolerance |
||
| real(kind=wp), | intent(in) | :: | a |
search interval |
||
| real(kind=wp), | intent(in) | :: | b |
search interval |
||
| real(kind=wp), | intent(in) | :: | maxstep |
max|dx| allowed |
||
| real(kind=wp), | intent(in) | :: | xin |
initial guess on input |
||
| real(kind=wp), | intent(in) | :: | F0 |
function to find root is FR(x)-F0 |
||
| class(c_newton_Root1D_FdF) | :: | fobj |
function to find root f(x) & derivative d/dx f(x) as FRdFR method |
output x for f(x)=0
FUNCTION NewtonRoot1D_FdF(tol,a,b,maxstep,xin,F0,fobj) RESULT (xout) ! MODULES IMPLICIT NONE !----------------------------------------------------------------------------------------------------------------------------------- ! INPUT VARIABLES REAL(wp),INTENT(IN) :: tol !! abort tolerance REAL(wp),INTENT(IN) :: a,b !! search interval REAL(wp),INTENT(IN) :: maxstep !! max|dx| allowed REAL(wp),INTENT(IN) :: xin !! initial guess on input REAL(wp),INTENT(IN) :: F0 !! function to find root is FR(x)-F0 !----------------------------------------------------------------------------------------------------------------------------------- ! OUTPUT VARIABLES CLASS(c_newton_Root1D_FdF) :: fobj !! function to find root f(x) & derivative d/dx f(x) as FRdFR method REAL(wp) :: xout !! output x for f(x)=0 !----------------------------------------------------------------------------------------------------------------------------------- ! LOCAL VARIABLES INTEGER :: iter,maxiter REAL(wp) :: x,dx REAL(wp) :: FRdFRx(2) !1: FR(x), 2: dFR(x) LOGICAL :: converged LOGICAL :: converged2 !=================================================================================================================================== converged=.FALSE. x=xin maxiter=20 DO iter=1,maxiter FRdFRx=fobj%FRdFR(x) dx=-(FRdFRx(1)-F0)/FRdFRx(2) dx = MAX(-(x-a),MIN(b-x,dx)) !respect bounds IF(ABS(dx).GT.maxstep) dx=dx/ABS(dx)*maxstep x = x+dx converged=(ABS(dx).LT.tol).AND.(x.GE.a).AND.(x.LE.b) IF(converged) EXIT END DO !iter IF(.NOT.converged) THEN !repeat with maxstep /10 and a little change in the initial condition converged2=.FALSE. x=MIN(b,MAX(a,xin+0.01_wp*(b-a))) maxiter=200 DO iter=1,maxiter FRdFRx=fobj%FRdFR(x) dx=-(FRdFRx(1)-F0)/FRdFRx(2) dx = MAX(-(x-a),MIN(b-x,dx)) !respect bounds IF(ABS(dx).GT.maxstep) dx=dx/ABS(dx)*0.1_wp*maxstep x = x+dx converged2=(ABS(dx).LT.tol).AND.(x.GE.a).AND.(x.LE.b) IF(converged2) EXIT END DO !iter IF(converged2) THEN xout=x RETURN END IF WRITE(UNIT_stdout,*)'Newton abs(dx)<tol',ABS(dx),tol,ABS(dx).LT.tol WRITE(UNIT_stdout,*)'Newton x>a',x,a,(x.GT.a) WRITE(UNIT_stdout,*)'Newton x<b',x,b,(x.LT.b) WRITE(UNIT_stdout,*)'after iter',iter-1 CALL abort(__STAMP__,& 'NewtonRoot1D_FdF not converged') END IF xout=x END FUNCTION NewtonRoot1D_FdF