23 #include "libmesh/dense_matrix.h" 41 template <
typename T,
typename Functor>
45 const Real z_initial_guess,
48 const std::string & caller_name,
49 const unsigned int max_its = 100)
53 std::function<bool(const T &, const T &)> abs_tol_check =
54 [tolerance](
const T &
R,
const T & )
56 std::function<bool(const T &, const T &)> rel_tol_check = [tolerance](
const T &
R,
const T &
y)
62 T z = z_initial_guess,
R, new_y, dy_dx, dy_dz;
63 unsigned int iteration = 0;
67 func(
x, z, new_y, dy_dx, dy_dz);
76 static constexpr
Real perturbation_factor = 1 + 1e-8;
77 T perturbed_y, dummy, dummy2;
78 func(
x, perturbation_factor * z, perturbed_y, dummy, dummy2);
80 auto J_differenced = (perturbed_y - new_y) / (1e-8 * z);
82 mooseDoOnce(
mooseWarning(caller_name +
": Bad Jacobian in NewtonSolve"));
89 mooseException(caller_name +
": NaN detected in Newton solve");
93 }
while (++iteration < max_its);
96 if (iteration >= max_its)
97 mooseException(caller_name +
98 ": Newton solve convergence failed: maximum number of iterations, ",
123 template <
typename T,
typename Functor1,
typename Functor2>
133 const Functor1 & func1,
134 const Functor2 & func2,
135 const unsigned int max_its = 100)
138 constexpr
unsigned int system_size = 2;
139 DenseVector<T> targets = {{
f, g}};
140 DenseVector<Real> tolerances = {{f_tol, g_tol}};
142 auto convergence_check = [&targets, &tolerances](
const auto & minus_R)
148 : minus_R(i) / targets(i));
149 if (error >= tolerances(i))
155 DenseVector<T> u = {{x0, y0}};
156 DenseVector<T> minus_R(system_size), func_evals(system_size), u_update;
157 DenseMatrix<T> J(system_size, system_size);
158 unsigned int iteration = 0;
160 DenseVector<Real> svs(system_size), evs_real(system_size), evs_imag(system_size);
161 DenseMatrix<Real> raw_J(system_size, system_size), raw_J2(system_size, system_size);
164 typedef std::function<void(const T &, const T &, T &, T &, T &)> FuncType;
165 std::array<FuncType, 2> func = {{func1, func2}};
167 auto assign_solution = [&u, &x_final, &y_final]()
176 func[i](u(0), u(1), func_evals(i), J(i, 0), J(i, 1));
179 minus_R(i) = targets(i) - func_evals(i);
184 const bool converged = convergence_check(minus_R);
189 if (std::isnan(minus_R(i)))
192 mooseException(
"NaN detected in Newton solve");
198 const auto rowmax = std::max(std::abs(J(i, 0)), std::abs(J(i, 1)));
201 minus_R(i) /= rowmax;
215 raw_J2.
evd(evs_real, evs_imag);
218 J.lu_solve(minus_R, u_update);
225 if (std::isnan(u(i)))
228 mooseException(
"NaN detected in Newton solve");
233 }
while (++iteration < max_its);
238 if (iteration >= max_its)
240 "Newton solve convergence failed: maximum number of iterations, ", max_its,
", exceeded");
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void mooseWarning(Args &&... args)
const std::vector< double > y
std::pair< T, T > NewtonSolve(const T &x, const T &y, const Real z_initial_guess, const Real tolerance, const Functor &func, const std::string &caller_name, const unsigned int max_its=100)
NewtonSolve does a 1D Newton Solve to solve the equation y = f(x, z) for variable z...
bool converged(const std::vector< std::pair< unsigned int, Real >> &residuals, const std::vector< Real > &abs_tolerances)
Based on the residuals, determine if the iterative process converged or not.
void NewtonSolve2D(const T &f, const T &g, const Real x0, const Real y0, T &x_final, T &y_final, const Real f_tol, const Real g_tol, const Functor1 &func1, const Functor2 &func2, const unsigned int max_its=100)
NewtonSolve2D does a 2D Newton Solve to solve for the x and y such that: f = func1(x, y) and g = func2(x, y).
FunctorEnvelope< T > Functor
const std::vector< double > x
Real f(Real x)
Test function for Brents method.
static const std::string R
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void evd(DenseVector< Real > &lambda_real, DenseVector< Real > &lambda_imag)
bool relativeFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
IntRange< T > make_range(T beg, T end)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
auto index_range(const T &sizable)