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 |
||
| real(kind=wp), | intent(in) | :: | F0 |
function to find root is FR(x)-F0 |
||
| class(c_newton_Root1D) | :: | fobj |
on output =f(x)
FUNCTION NewtonRoot1D(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 REAL(wp),INTENT(IN) :: F0 !! function to find root is FR(x)-F0 !----------------------------------------------------------------------------------------------------------------------------------- ! OUTPUT VARIABLES CLASS(c_newton_Root1D) :: fobj REAL(wp) :: xout !! on output =f(x) !----------------------------------------------------------------------------------------------------------------------------------- ! LOCAL VARIABLES INTEGER :: iter,maxiter REAL(wp) :: x,dx LOGICAL :: converged LOGICAL :: converged2 !=================================================================================================================================== converged=.FALSE. x=xin maxiter=20 DO iter=1,maxiter dx=-(fobj%FR(x)-F0)/fobj%dFR(x) dx = MAX(-(x-a),MIN(b-x,dx)) !respect bounds x = x+dx IF(ABS(dx).GT.maxstep) dx=dx/ABS(dx)*maxstep converged=(ABS(dx).LT.tol).AND.(x.GT.a).AND.(x.LT.b) IF(converged) EXIT END DO !iter IF(.NOT.converged) THEN !repeat with maxstep /10 and a little change in the initial condition x=MIN(b,MAX(a,xin+0.01_wp*(b-a))) maxiter=200 DO iter=1,maxiter dx=-(fobj%FR(x)-F0)/fobj%dFR(x) 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.GT.a).AND.(x.LT.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 not converged') END IF xout=x END FUNCTION NewtonRoot1D