7 module subroutine brent_solve(this, fcn, x, lim, f, ib, err)
9 class(brent_solver),
intent(inout) :: this
10 class(fcn1var_helper),
intent(in) :: fcn
11 real(real64),
intent(inout) :: x
12 type(value_pair),
intent(in) :: lim
13 real(real64),
intent(out),
optional :: f
14 type(iteration_behavior),
optional :: ib
15 class(errors),
intent(inout),
optional,
target :: err
18 real(real64),
parameter :: zero = 0.0d0
19 real(real64),
parameter :: half = 0.5d0
20 real(real64),
parameter :: one = 1.0d0
21 real(real64),
parameter :: two = 2.0d0
22 real(real64),
parameter :: three = 3.0d0
25 logical :: fcnvrg, xcnvrg
26 integer(int32) :: neval, maxeval, flag, iter
27 real(real64) :: ftol, xtol, a, b, c, fa, fb, fc, p, q, r, s, xm, e, d, &
28 mn1, mn2, eps, tol1, temp
29 class(errors),
pointer :: errmgr
30 type(errors),
target :: deferr
31 character(len = 256) :: errmsg
37 a = min(lim%x1, lim%x2)
38 b = max(lim%x1, lim%x2)
42 ftol = this%get_fcn_tolerance()
43 xtol = this%get_var_tolerance()
44 maxeval = this%get_max_fcn_evals()
45 if (
present(f)) f = zero
51 ib%converge_on_fcn = fcnvrg
52 ib%converge_on_chng = xcnvrg
53 ib%converge_on_zero_diff = .false.
55 if (
present(err))
then
62 if (.not.fcn%is_fcn_defined())
then
64 call errmgr%report_error(
"brent_solve", &
65 "No function has been defined.", &
66 nl_invalid_operation_error)
69 if (abs(a - b) < eps)
then
71 write(errmsg, 100)
"Search limits have no " // &
72 "appreciable difference between them. Lower Limit: ", a, &
74 call errmgr%report_error(
"brent_solve", trim(errmsg), &
75 nl_invalid_operation_error)
90 if ((fb > zero .and. fc >= zero) .or. &
91 (fb < zero .and. fc < zero))
then
97 if (abs(fc) < abs(fb))
then
107 tol1 = two * eps * abs(b) + half * xtol
109 if (abs(fb) < ftol)
then
114 if (abs(xm) <= tol1)
then
121 if (abs(e) >= tol1 .and. abs(fa) > abs(fb))
then
125 if (abs(a - c) < eps)
then
131 p = s * (two * xm * q * (q - r) - (b - a) * (r - one))
132 q = (q - one) * (r - one) * (s - one)
138 mn1 = three * xm * q - abs(tol1 * q)
145 if (two * p < temp)
then
163 if (abs(d) > tol1)
then
166 b = b + sign(tol1, xm)
172 if (this%get_print_status())
then
173 call print_status(iter, neval, 0, xm, fb)
177 if (neval >= maxeval)
then
184 if (
present(f)) f = fb
185 if (
present(ib))
then
188 ib%jacobian_count = 0
189 ib%gradient_count = 0
190 ib%converge_on_fcn = fcnvrg
191 ib%converge_on_chng = xcnvrg
192 ib%converge_on_zero_diff = .false.
197 write(errmsg, 101)
"The algorithm failed to " // &
198 "converge. Function evaluations performed: ", neval, &
199 "." // new_line(
'c') //
"Change in Variable: ", xm, &
200 new_line(
'c') //
"Residual: ", fb
201 call errmgr%report_error(
"brent_solve", trim(errmsg), &
202 nl_convergence_error)
206100
format(a, e10.3, a, e10.3)
207101
format(a, i0, a, e10.3, a, e10.3)