12#ifndef DUMUX_COMMON_SCALAR_ROOT_FINDING_HH
13#define DUMUX_COMMON_SCALAR_ROOT_FINDING_HH
34template<
class Scalar,
class ResFunc,
class DerivFunc,
35 typename std::enable_if_t<std::is_invocable_r_v<Scalar, ResFunc, Scalar> &&
36 std::is_invocable_r_v<Scalar, DerivFunc, Scalar>>...>
38 const Scalar tol = 1e-13,
const int maxIter = 200)
41 Scalar r = residual(xNew);
44 Scalar relativeShift = std::numeric_limits<Scalar>::max();
45 while (relativeShift > tol && n > 0)
47 xNew = xOld - r/derivative(xOld);
50 using std::abs;
using std::max;
51 relativeShift = abs(xOld-xNew)/max(abs(xOld), abs(xNew));
58 DUNE_THROW(
NumericalProblem,
"Residual is not finite: " << r <<
" after " << maxIter - n <<
" iterations!");
60 if (relativeShift > tol)
61 DUNE_THROW(
NumericalProblem,
"Scalar newton solver did not converge after " << maxIter <<
" iterations!");
75template<
class Scalar,
class ResFunc,
76 typename std::enable_if_t<std::is_invocable_r_v<Scalar, ResFunc, Scalar>>...>
78 const Scalar tol = 1e-13,
const int maxIter = 200)
81 auto derivative = [&](
const auto x){
return (residual(x + eps)-residual(x))/eps; };
97template<
class Scalar,
class ResFunc,
98 typename std::enable_if_t<std::is_invocable_r_v<Scalar, ResFunc, Scalar>>...>
100 const Scalar tol = 1e-13,
const int maxIter = 200)
103 Scalar fa = residual(a);
104 Scalar fb = residual(b);
110 DUNE_THROW(
NumericalProblem,
"Brent's algorithm failed: [a,b] does not contain any, or no uniquely defined root!");
113 using std::abs;
using std::swap;
114 if (abs(fa) < abs(fb))
126 for (
int i = 0; i < maxIter; ++i)
130 if (abs(b-a) < tol*max(abs(a), abs(b)))
134 if (fa != fc && fb != fc)
136 const auto fab = fa-fb;
137 const auto fac = fa-fc;
138 const auto fbc = fb-fc;
139 s = a*fb*fc/(fab*fac) - b*fa*fc/(fab*fbc) + c*fa*fb/(fac*fbc);
145 s = b - fb*(b-a)/(fb-fa);
149 if ( (s < (3*a + b)*0.25 || s > b)
150 || (flag && abs(s-b) >= abs(b-c)*0.5)
151 || (!flag && abs(s-b) >= abs(c-d)*0.5)
152 || (flag && abs(b-c) < tol*max(abs(b), abs(c)))
153 || (!flag && abs(c-d) < tol*max(abs(c), abs(d))) )
180 if (abs(fa) < abs(fb))
187 DUNE_THROW(
NumericalProblem,
"Brent's algorithm didn't converge after " << maxIter <<
" iterations!");
static Scalar epsilon(const Scalar value, const Scalar baseEps=1e-10)
Computes the epsilon used for numeric differentiation.
Definition: numericdifferentiation.hh:35
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:27
Some exceptions thrown in DuMux
Scalar findScalarRootNewton(Scalar xOld, const ResFunc &residual, const DerivFunc &derivative, const Scalar tol=1e-13, const int maxIter=200)
Newton's root finding algorithm for scalar functions (secant method)
Definition: findscalarroot.hh:37
Scalar findScalarRootBrent(Scalar a, Scalar b, const ResFunc &residual, const Scalar tol=1e-13, const int maxIter=200)
Brent's root finding algorithm for scalar functions.
Definition: findscalarroot.hh:99
A class for numeric differentiation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.