www.mooseframework.org
BrentsMethod.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "BrentsMethod.h"
11 #include "MooseError.h"
12 #include "Conversion.h"
13 
14 namespace BrentsMethod
15 {
16 void
17 bracket(std::function<Real(Real)> const & f, Real & x1, Real & x2)
18 {
19  Real f1, f2;
20  // Factor to scale the interval by
21  Real factor = 1.6;
22  // Maximum number of times to attempt bracketing the interval
23  unsigned int n = 50;
24  // Small positive value to keep guess above
25  Real eps = 1.0e-10;
26 
27  // If the initial guesses are identical
28  if (x1 == x2)
29  throw MooseException("Bad initial range (0) used in BrentsMethod::bracket");
30 
31  f1 = f(x1);
32  f2 = f(x2);
33 
34  if (f1 * f2 > 0.0)
35  {
36  unsigned int iter = 0;
37  while (f1 * f2 > 0.0)
38  {
39  if (std::abs(f1) < std::abs(f2))
40  {
41  x1 += factor * (x1 - x2);
42  x1 = (x1 < eps ? eps : x1);
43  f1 = f(x1);
44  }
45  else
46  {
47  x2 += factor * (x2 - x1);
48  x2 = (x2 < eps ? eps : x2);
49  f2 = f(x2);
50  }
52  iter++;
53  if (iter >= n)
54  throw MooseException("No bracketing interval found by BrentsMethod::bracket after " +
55  Moose::stringify(n) + " iterations");
56  }
57  }
58 }
59 
60 Real
61 root(std::function<Real(Real)> const & f, Real x1, Real x2, Real tol)
62 {
63  Real a = x1, b = x2, c = x2, d = 0.0, e = 0.0, min1, min2;
64  Real fa = f(a);
65  Real fb = f(b);
66  Real fc, p, q, r, s, tol1, xm;
67  unsigned int iter_max = 100;
68  Real eps = 1.0e-12;
69 
70  if (fa * fb > 0.0)
71  throw MooseException("Root must be bracketed in BrentsMethod::root");
72 
73  fc = fb;
74  for (unsigned int i = 1; i <= iter_max; ++i)
75  {
76  if (fb * fc > 0.0)
77  {
78  // Rename a,b and c and adjust bounding interval d
79  c = a;
80  fc = fa;
81  d = b - a;
82  e = d;
83  }
84  if (std::abs(fc) < std::abs(fb))
85  {
86  a = b;
87  b = c;
88  c = a;
89  fa = fb;
90  fb = fc;
91  fc = fa;
92  }
93  // Convergence check tolerance
94  tol1 = 2.0 * eps * std::abs(b) + 0.5 * tol;
95  xm = 0.5 * (c - b);
96 
97  if (std::abs(xm) <= tol1 || fb == 0.0)
98  return b;
99 
100  if (std::abs(e) >= tol1 && std::abs(fa) > std::abs(fb))
101  {
102  // Attempt inverse quadratic interpolation
103  s = fb / fa;
104  if (a == c)
105  {
106  p = 2.0 * xm * s;
107  q = 1.0 - s;
108  }
109  else
110  {
111  q = fa / fc;
112  r = fb / fc;
113  p = s * (2.0 * xm * q * (q - r) - (b - a) * (r - 1.0));
114  q = (q - 1.0) * (r - 1.0) * (s - 1.0);
115  }
116  // Check whether in bounds
117  if (p > 0.0)
118  q = -q;
119  p = std::abs(p);
120  min1 = 3.0 * xm * q - std::abs(tol1 * q);
121  min2 = std::abs(e * q);
122 
123  if (2.0 * p < (min1 < min2 ? min1 : min2))
124  {
125  // Accept interpolation
126  e = d;
127  d = p / q;
128  }
129  else
130  {
131  // Interpolation failed, use bisection
132  d = xm;
133  e = d;
134  }
135  }
136  else
137  {
138  // Bounds decreasing too slowly, use bisection
139  d = xm;
140  e = d;
141  }
142  // Move last best guess to a
143  a = b;
144  fa = fb;
145  // Evaluate new trial root
146  if (std::abs(d) > tol1)
147  b += d;
148  else
149  {
150  Real sgn = (xm >= 0.0 ? std::abs(tol1) : -std::abs(tol1));
151  b += sgn;
152  }
153 
154  fb = f(b);
155  }
156 
157  throw MooseException("Maximum number of iterations exceeded in BrentsMethod::root");
158  return 0.0; // Should never get here
159 }
160 } // namespace BrentsMethod
BrentsMethod
Definition: BrentsMethod.h:18
BrentsMethod::root
Real root(std::function< Real(Real)> const &f, Real x1, Real x2, Real tol=1.0e-12)
Finds the root of a function using Brent's method.
Definition: BrentsMethod.C:61
tol
const double tol
Definition: Setup.h:18
BrentsMethod.h
BrentsMethod::bracket
void bracket(std::function< Real(Real)> const &f, Real &x1, Real &x2)
Function to bracket a root of a given function.
Definition: BrentsMethod.C:17