Main wrapper routine for all the methods.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(root_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(out) | :: | xzero |
abscissa approximating a zero of |
||
real(kind=wp), | intent(out) | :: | fzero |
value of |
||
integer, | intent(out) | :: | iflag |
status flag ( |
||
real(kind=wp), | intent(in), | optional | :: | fax |
if |
|
real(kind=wp), | intent(in), | optional | :: | fbx |
if |
|
logical, | intent(in), | optional | :: | bisect_on_failure |
if true, then if the specified method fails,
it will be retried using the bisection method.
(default is False). Note that this can use up
to |
subroutine solve(me,ax,bx,xzero,fzero,iflag,fax,fbx,bisect_on_failure) implicit none class(root_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(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 (`-1`=error, `0`=root found, `-4`=ax must be /= bx) real(wp),intent(in),optional :: fax !! if `f(ax)` is already known, it can be input here real(wp),intent(in),optional :: fbx !! if `f(bx)` is already known, it can be input here logical,intent(in),optional :: bisect_on_failure !! if true, then if the specified method fails, !! it will be retried using the bisection method. !! (default is False). Note that this can use up !! to `maxiter` additional function evaluations. real(wp) :: fa !! `f(ax)` passed to the lower level routine real(wp) :: fb !! `f(bx)` passed to the lower level routine if (ax==bx) then ! ax must be /= bx iflag = -4 xzero = ax ! just to return something fzero = fa ! else call me%get_fa_fb(ax,bx,fax,fbx,fa,fb) ! check trivial cases first: if (me%solution(ax,fa,xzero,fzero)) then iflag = 0 else if (me%solution(bx,fb,xzero,fzero)) then iflag = 0 else if (fa*fb>0.0_wp) then ! f(ax) and f(bx) do not have different signs iflag = -1 xzero = ax ! just to return something fzero = fa ! else ! call the root solver. ! make sure order is correct. if (ax<bx) then call me%find_root(ax,bx,fa,fb,xzero,fzero,iflag) else call me%find_root(bx,ax,fb,fa,xzero,fzero,iflag) end if ! if it failed, then we have the option to then try bisection if (iflag /= 0) then if (present(bisect_on_failure)) then if (bisect_on_failure) then ! use the wrapper routine for that with the input class call root_scalar(root_method_bisection,& func_wrapper,ax,bx,xzero,fzero,iflag,& me%ftol,me%rtol,me%atol,me%maxiter,fa,fb,& bisect_on_failure = .false.) end if end if end if end if end if contains function func_wrapper(x) result(f) !! wrapper function to use bisection implicit none real(wp),intent(in) :: x real(wp) :: f f = me%f(x) end function func_wrapper end subroutine solve