Pegasus method to find a root of f(x).
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(pegasus_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 pegasus(me,ax,bx,fax,fbx,xzero,fzero,iflag) implicit none class(pegasus_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) integer :: i !! counter real(wp) :: x1,x2,x3,f1,f2,f3,f1tmp,denom ! initialize: iflag = 0 x1 = ax x2 = bx f1 = fax f2 = fbx ! main loop: do i = 1, me%maxiter ! secant step x3 = secant(x1,x2,f1,f2,ax,bx) f3 = me%f(x3) ! calculate f3 if (me%solution(x3,f3,xzero,fzero)) return ! determine a new inclusion interval: if (f2*f3<0.0_wp) then ! root on (x2,x3) x1 = x2 f1 = f2 f1tmp = f1 else ! root on (x1,x3) f1tmp = f1 denom = f2 + f3 if (denom /= 0.0_wp) then ! proceed as normal f1 = f1 * f2 / denom else ! can't proceed, keep as is. ! [need a find a test case where this happens -TODO] end if end if x2 = x3 f2 = f3 call choose_best(x1,x2,f1tmp,f2,xzero,fzero) if (me%converged(x1,x2)) exit ! check for convergence if (i == me%maxiter) iflag = -2 ! max iterations exceeded end do end subroutine pegasus