Brent's method is used to find the root of a function f(x), i.e., find x such that f(x) = 0.
More...
Brent's method is used to find the root of a function f(x), i.e., find x such that f(x) = 0.
First, brackets x1 and x2 are found such that f(x) changes sign between x1 and x2, implying that there is a root between the points.
| void BrentsMethod::bracket |
( |
std::function< Real(Real)> const & |
f, |
|
|
Real & |
x1, |
|
|
Real & |
x2 |
|
) |
| |
Function to bracket a root of a given function.
Adapted from Numerical Recipes in C
- Parameters
-
| f | reference to function to find bracketing interval |
| [out] | x1 | reference one bound |
| [out] | x2 | reference to other bound |
Increment counter
Increment counter
Definition at line 17 of file BrentsMethod.C.
18{
19 Real f1, f2;
20
21 Real factor = 1.6;
22
23 unsigned int n = 50;
24
26
27
28 if (x1 == x2)
29 throw MooseException(
"Bad initial range (0) used in BrentsMethod::bracket");
30
33
34 if (f1 * f2 > 0.0)
35 {
36 unsigned int iter = 0;
37 std::stringstream debug_ss;
38 while (f1 * f2 > 0.0)
39 {
40#ifdef DEBUG
41 debug_ss << " iteration " << iter << ": (x1,x2) = (" << x1 << "," << x2 << "), (f1,f2) = ("
42 << f1 << "," << f2 << ")\n";
43#endif
44 if (std::abs(f1) < std::abs(f2))
45 {
46 x1 += factor * (x1 - x2);
47 x1 = (x1 <
eps ?
eps : x1);
49 }
50 else
51 {
52 x2 += factor * (x2 - x1);
53 x2 = (x2 <
eps ?
eps : x2);
55 }
57 iter++;
58 if (iter >= n)
59 throw MooseException(
"No bracketing interval found by BrentsMethod::bracket after " +
61 }
62 }
63}
Real f(Real x)
Test function for Brents method.
std::string stringify(const T &t)
Referenced by CaloricallyImperfectGas::rho_from_p_s(), CO2FluidProperties::rho_from_p_T(), HelmholtzFluidProperties::rho_from_p_T(), CaloricallyImperfectGas::setupLookupTables(), and TEST().
| Real BrentsMethod::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.
Adapted from Numerical Recipes in C
- Parameters
-
| f | reference to function to find root of |
| x1 | one end of bracketing interval |
| x2 | other end of bracketing interval |
| tolerance | root finding tolerance (default is 1e-12) |
Definition at line 66 of file BrentsMethod.C.
67{
68 Real
a = x1,
b = x2,
c = x2,
d = 0.0, e = 0.0, min1, min2;
71 Real fc,
p, q, r, s, tol1, xm = 0;
72 unsigned int iter_max = 100;
74
75 if (fa * fb > 0.0)
76 throw MooseException(
"Root must be bracketed in BrentsMethod::root");
77
78 fc = fb;
79 std::stringstream debug_ss;
80 for (unsigned int i = 1; i <= iter_max; ++i)
81 {
82#ifdef DEBUG
83 debug_ss <<
" iteration " << i <<
": dx = " << xm <<
", x = " <<
b <<
", f(x) = " << fb
84 << "\n";
85#endif
86 if (fb * fc > 0.0)
87 {
88
90 fc = fa;
93 }
94 if (std::abs(fc) < std::abs(fb))
95 {
99 fa = fb;
100 fb = fc;
101 fc = fa;
102 }
103
104 tol1 = 2.0 *
eps * std::abs(b) + 0.5 *
tol;
106
107 if (std::abs(xm) <= tol1 || fb == 0.0)
108 return b;
109
110 if (std::abs(e) >= tol1 && std::abs(fa) > std::abs(fb))
111 {
112
113 s = fb / fa;
115 {
117 q = 1.0 - s;
118 }
119 else
120 {
121 q = fa / fc;
122 r = fb / fc;
123 p = s * (2.0 * xm * q * (q - r) - (b -
a) * (r - 1.0));
124 q = (q - 1.0) * (r - 1.0) * (s - 1.0);
125 }
126
128 q = -q;
130 min1 = 3.0 * xm * q - std::abs(tol1 * q);
131 min2 = std::abs(e * q);
132
133 if (2.0 *
p < (min1 < min2 ? min1 : min2))
134 {
135
138 }
139 else
140 {
141
144 }
145 }
146 else
147 {
148
151 }
152
154 fa = fb;
155
156 if (std::abs(
d) > tol1)
158 else
159 {
162 }
163
165 }
166
167 throw MooseException(
"Maximum number of iterations exceeded in BrentsMethod::root.\n" +
168 debug_ss.str());
169 return 0.0;
170}
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
int sgn(T val)
The sign function.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Referenced by CaloricallyImperfectGas::rho_from_p_s(), CO2FluidProperties::rho_from_p_T(), HelmholtzFluidProperties::rho_from_p_T(), CaloricallyImperfectGas::setupLookupTables(), and TEST().