Ridders method to find a root of f(x).
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(ridders_solver), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in) | :: | ax |
left endpoint of initial interval |
||
real(kind=wp), | intent(in) | :: | bx |
right endpoint of initial interval |
||
real(kind=wp), | intent(in) | :: | fax |
|
||
real(kind=wp), | intent(in) | :: | fbx |
|
||
real(kind=wp), | intent(out) | :: | xzero |
abscissa approximating a zero of |
||
real(kind=wp), | intent(out) | :: | fzero |
value of |
||
integer, | intent(out) | :: | iflag |
status flag ( |
subroutine ridders(me,ax,bx,fax,fbx,xzero,fzero,iflag) implicit none class(ridders_solver),intent(inout) :: me real(wp),intent(in) :: ax !! left endpoint of initial interval real(wp),intent(in) :: bx !! right endpoint of initial interval real(wp),intent(in) :: fax !! `f(ax)` real(wp),intent(in) :: fbx !! `f(ax)` real(wp),intent(out) :: xzero !! abscissa approximating a zero of `f` in the interval `ax`,`bx` real(wp),intent(out) :: fzero !! value of `f` at the root (`f(xzero)`) integer,intent(out) :: iflag !! status flag (`0`=root found, `-2`=max iterations reached, `-3`=singularity in the algorithm) integer :: i !! counter real(wp) :: fh,fl,fm,fnew,denom,xh,xl,xm,xnew ! initialize: iflag = 0 fl = fax fh = fbx xl = ax xh = bx xzero = huge(1.0_wp) do i = 1, me%maxiter xm = bisect(xl,xh) fm = me%f(xm) if (me%solution(xm,fm,xzero,fzero)) return denom = sqrt(fm**2-fl*fh) if (denom == 0.0_wp) then xzero = xm fzero = fm iflag = -3 ! can't proceed: denominator is zero [TODO: add a bisection if this happens] exit end if xnew = xm + (xm-xl)*(sign(1.0_wp,fl-fh)*fm/denom) if (me%converged(xzero,xnew)) then ! relative convergence in x ! additional check to prevent false convergence if (me%converged(xl,xm) .or. me%converged(xm,xh)) exit end if xzero = xnew fnew = me%f(xzero) fzero = fnew if (abs(fnew) <= me%ftol) exit ! abs convergence in f ! to keep the root bracketed: if (sign(fm,fnew) /= fm) then xl = xm fl = fm xh = xzero fh = fnew else if (sign(fl,fnew) /= fl) then xh = xzero fh = fnew else if (sign(fh,fnew) /= fh) then xl = xzero fl = fnew end if if (me%converged(xl,xh)) exit ! relative convergence in x if (i == me%maxiter) iflag = -2 ! max iterations exceeded end do end subroutine ridders