Regula Falsi-Bisection-Parabolic Algorithm (RBP)
Note
This differs from the reference in that it will fallback to bisection if the parabolic interpolation fails.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(rbp_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 rbp(me,ax,bx,fax,fbx,xzero,fzero,iflag) implicit none class(rbp_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) real(wp) :: xa,xb,xc,x0p,fa,fb,fc,xp,fp,df,dx integer :: i !! iteration counter logical :: root_found iflag = 0 xa = ax xb = bx xc = bisect(xa,xb) x0p = xc ! function values: fa = fax fb = fbx fc = me%f(xc) if (me%solution(xc,fc,xzero,fzero)) return do i = 1, me%maxiter ! parabolic interpolation: xp = parabolic(xa,xb,xc,fa,fb,fc) fp = me%f(xp) if (me%solution(xp,fp,xzero,fzero)) return ! we can check for convergence here. ! since everything below is used for the next iteration root_found = me%converged(x0p,xp) .and. i>1 if (root_found .or. i==me%maxiter) then xzero = xp fzero = fp if (.not. root_found) iflag = -2 ! max iterations reached exit end if ! new endpoints of the interval: if (fa*fp < 0.0_wp) then xb = xp fb = fp if (fa*fc > 0.0_wp) then xa = xc fa = fc end if else xa = xp fa = fp if (fb*fc > 0.0_wp) then xb = xc fb = fc end if end if ! switching mechanism between bisection and regula falsi: df = abs(fa-fb) dx = abs(xa-xb) if (df>10.0_wp*dx .or. df<0.1_wp*dx) then xc = bisect(xa,xb) else xc = regula_falsi_step(xa,xb,fa,fb,ax,bx) end if fc = me%f(xc) if (me%solution(xc,fc,xzero,fzero)) return x0p = xp end do end subroutine rbp