19#include "libmesh/diff_system.h"
20#include "libmesh/dof_map.h"
21#include "libmesh/libmesh_logging.h"
22#include "libmesh/linear_solver.h"
23#include "libmesh/newton_solver.h"
24#include "libmesh/numeric_vector.h"
25#include "libmesh/sparse_matrix.h"
35 return b >= 0 ? std::abs(a) : -std::abs(a);
40 Real & current_residual,
46 if ((current_residual < last_residual) ||
61 (current_residual > last_residual &&
68 substepdivision = std::min(0.5, last_residual/current_residual);
69 substepdivision = std::max(substepdivision, tol*2.);
72 substepdivision = 0.5;
74 newton_iterate.
add (bx * (1.-substepdivision),
76 newton_iterate.
close();
77 bx *= substepdivision;
89 current_residual = rhs.
l2_norm();
92 << current_residual << std::endl;
96 (current_residual > last_residual)))
103 libmesh_convergence_failure();
123 Real x = bx, w = bx, v = bx;
126 Real fx = current_residual,
127 fw = current_residual,
128 fv = current_residual;
131 const unsigned int max_i = 20;
134 const Real golden_ratio = 1.-(std::sqrt(5.)-1.)/2.;
136 for (
unsigned int i=1; i <= max_i; i++)
138 Real xm = (ax+cx)*0.5;
139 Real tol1 = tol * std::abs(x) + tol*tol;
140 Real tol2 = 2.0 * tol1;
143 if (std::abs(x-xm) <= (tol2 - 0.5 * (cx - ax)))
149 if (std::abs(e) > tol1)
151 Real r = (x-w)*(fx-fv);
152 Real q = (x-v)*(fx-fw);
153 Real p = (x-v)*q-(x-w)*r;
159 if (std::abs(p) >= std::abs(0.5*q*e) ||
164 e = x >= xm ? ax-x : cx-x;
165 d = golden_ratio * e;
171 if (x+d-ax < tol2 || cx-(x+d) < tol2)
172 d =
SIGN(tol1, xm - x);
178 e = x >= xm ? ax-x : cx-x;
179 d = golden_ratio * e;
182 Real u = std::abs(d) >= tol1 ? x+d : x +
SIGN(tol1,d);
185 newton_iterate.
add (bx - u, linear_solution);
186 newton_iterate.
close();
209 fv = fw; fw = fx; fx = fu;
217 if (fu <= fw || w == x)
222 else if (fu <= fv || v == x || v == w)
231 libMesh::out <<
"Warning! Too many iterations used in Brent line search!"
239 require_residual_reduction(true),
240 require_finite_residual(true),
241 brent_line_search(true),
242 track_linear_convergence(false),
244 linear_tolerance_multiplier(1e-3),
282 LOG_SCOPE(
"solve()",
"NewtonSolver");
289 std::unique_ptr<NumericVector<Number>> linear_solution_ptr = newton_iterate.
zero_clone();
293 newton_iterate.
close();
294 linear_solution.
close();
297#ifdef LIBMESH_ENABLE_CONSTRAINTS
328 <<
" with residual Not-a-Number"
330 libmesh_convergence_failure();
339 <<
" meets absolute tolerance "
348 if (current_residual == 0)
362 Real last_residual = current_residual;
373 << current_residual << std::endl;
376 current_linear_tolerance =
377 double(std::min (current_linear_tolerance,
387 current_linear_tolerance =
388 double(std::max(current_linear_tolerance,
397 linear_solution.
zero();
401 << current_linear_tolerance << std::endl;
404 const std::pair<unsigned int, Real> rval =
406 linear_solution, rhs, current_linear_tolerance,
414 if (linear_c_reason < 0)
419 libMesh::out <<
"Linear solver failed during Newton step, dropping out."
428#ifdef LIBMESH_ENABLE_CONSTRAINTS
431 (
_system, &linear_solution,
true);
434 const unsigned int linear_steps = rval.first;
438 const bool linear_solve_finished =
442 libMesh::out <<
"Linear solve finished, step " << linear_steps
443 <<
", residual " << rval.second
452 newton_iterate.
add (-1., linear_solution);
453 newton_iterate.
close();
458 norm_total = newton_iterate.
l2_norm();
461 newton_iterate, norm_total,
477 current_residual = rhs.
l2_norm();
480 << current_residual << std::endl;
484 linear_solve_finished &&
485 current_residual <= last_residual))
494 norm_total = newton_iterate.
l2_norm();
500 norm_delta, linear_solve_finished &&
501 current_residual <= last_residual);
510 last_residual, current_residual,
511 newton_iterate, linear_solution);
512 norm_delta *= steplength;
524 libMesh::out <<
" Nonlinear solver reached maximum step "
526 << current_residual << std::endl;
534 libmesh_convergence_failure();
540 norm_total = newton_iterate.
l2_norm();
548 << norm_delta / norm_total
549 <<
", |du| = " << norm_delta
555 linear_solve_finished))
559 norm_delta / steplength,
560 linear_solve_finished);
567#ifdef LIBMESH_ENABLE_CONSTRAINTS
579 !max_nonlinear_iterations);
588 bool linear_solve_finished)
591 bool has_converged =
false;
597 has_converged =
true;
605 has_converged =
true;
609 if (!linear_solve_finished)
611 return has_converged;
618 has_converged =
true;
627 has_converged =
true;
630 return has_converged;
635 Real current_residual,
637 bool linear_solve_finished)
642 libMesh::out <<
" Nonlinear solver converged, step " << step_num
643 <<
", residual " << current_residual
650 << current_residual <<
" > "
658 libMesh::out <<
" Nonlinear solver converged, step " << step_num
659 <<
", residual reduction "
674 if (!linear_solve_finished)
680 libMesh::out <<
" Nonlinear solver converged, step " << step_num
681 <<
", absolute step size "
700 libMesh::out <<
" Nonlinear solver converged, step " << step_num
701 <<
", relative step size "
This is a generic class that defines a solver to handle ImplicitSystem classes, including NonlinearIm...
unsigned int _inner_iterations
The number of inner iterations used by the last solve.
Real absolute_residual_tolerance
The DiffSolver should exit after the residual is reduced to either less than absolute_residual_tolera...
Real absolute_step_tolerance
The DiffSolver should exit after the full nonlinear step norm is reduced to either less than absolute...
std::unique_ptr< LinearSolutionMonitor > linear_solution_monitor
Pointer to functor which is called right after each linear solve.
unsigned int max_linear_iterations
Each linear solver step should exit after max_linear_iterations is exceeded.
double minimum_linear_tolerance
The tolerance for linear solves is kept above this minimum.
bool continue_after_backtrack_failure
Defaults to false, telling the DiffSolver to throw an error when the backtracking scheme fails to fin...
Real max_residual_norm
The largest nonlinear residual which the DiffSolver has yet seen will be stored here,...
Real max_solution_norm
The largest solution norm which the DiffSolver has yet seen will be stored here, to be used for stopp...
virtual void init()
The initialization function.
sys_type & _system
A reference to the system we are solving.
bool continue_after_max_iterations
Defaults to true, telling the DiffSolver to continue rather than exit when a solve has reached its ma...
@ DIVERGED_BACKTRACKING_FAILURE
The DiffSolver failed to find a descent direction by backtracking (See newton_solver....
@ DIVERGED_MAX_NONLINEAR_ITERATIONS
The DiffSolver reached the maximum allowed number of nonlinear iterations before satisfying any conve...
@ CONVERGED_RELATIVE_STEP
The DiffSolver achieved the desired relative step size tolerance.
@ CONVERGED_ABSOLUTE_RESIDUAL
The DiffSolver achieved the desired absolute residual tolerance.
@ DIVERGED_LINEAR_SOLVER_FAILURE
The linear solver used by the DiffSolver failed to find a solution.
@ INVALID_SOLVE_RESULT
A default or invalid solve result.
@ CONVERGED_RELATIVE_RESIDUAL
The DiffSolver achieved the desired relative residual tolerance.
@ CONVERGED_ABSOLUTE_STEP
The DiffSolver achieved the desired absolute step size tolerance.
double initial_linear_tolerance
Any required linear solves will at first be done with this tolerance; the DiffSolver may tighten the ...
unsigned int _outer_iterations
The number of outer iterations used by the last solve.
Real relative_residual_tolerance
Real relative_step_tolerance
virtual void reinit()
The reinitialization function.
bool _exact_constraint_enforcement
Whether we should enforce exact constraints globally during a solve.
unsigned int _solve_result
Initialized to zero.
bool verbose
The DiffSolver may print a lot more to libMesh::out if verbose is set to true; default is false.
unsigned int max_nonlinear_iterations
The DiffSolver should exit in failure if max_nonlinear_iterations is exceeded and continue_after_max_...
bool quiet
The DiffSolver should not print anything to libMesh::out unless quiet is set to false; default is tru...
void enforce_constraints_exactly(const System &system, NumericVector< Number > *v=nullptr, bool homogeneous=false) const
Constrains the numeric vector v, which represents a solution defined on the mesh.
NumericVector< Number > * rhs
The system matrix.
Manages consistently variables, degrees of freedom, coefficient vectors, and matrices for implicit sy...
SparseMatrix< Number > * matrix
The system matrix.
virtual void assembly(bool, bool, bool=false, bool=false)
Assembles a residual in rhs and/or a jacobian in matrix, as requested.
This base class can be inherited from to provide interfaces to linear solvers from different packages...
bool require_residual_reduction
If this is set to true, the solver is forced to test the residual after each Newton step,...
double linear_tolerance_multiplier
The tolerance for linear solves is kept below this multiplier (which defaults to 1e-3) times the norm...
bool test_convergence(Real current_residual, Real step_norm, bool linear_solve_finished)
virtual void reinit() override
The reinitialization function.
bool require_finite_residual
If this is set to true, the solver is forced to test the residual after each Newton step,...
void print_convergence(unsigned int step_num, Real current_residual, Real step_norm, bool linear_solve_finished)
This prints output for the convergence criteria based on by the given residual and step size.
Real minsteplength
If the quasi-Newton step length must be reduced to below this factor to give a residual reduction,...
NewtonSolver(sys_type &system)
Constructor.
bool track_linear_convergence
If set to true, check for convergence of the linear solve.
virtual void init() override
The initialization function.
Real line_search(Real tol, Real last_residual, Real ¤t_residual, NumericVector< Number > &newton_iterate, const NumericVector< Number > &linear_solution)
This does a line search in the direction opposite linear_solution to try and minimize the residual of...
virtual ~NewtonSolver()
Destructor.
bool brent_line_search
If require_residual_reduction is true, the solver may reduce step lengths when required.
virtual unsigned int solve() override
This method performs a solve, using an inexact Newton-Krylov method with line search.
std::unique_ptr< LinearSolver< Number > > _linear_solver
The LinearSolver defines the interface used to solve the linear_implicit system.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
virtual Real l2_norm() const =0
virtual void zero()=0
Set all entries to zero.
virtual std::unique_ptr< NumericVector< T > > zero_clone() const =0
virtual void add(const numeric_index_type i, const T value)=0
Adds value to the vector entry specified by i.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
const std::string & name() const
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
virtual void update()
Update the local values to reflect the solution on neighboring processors.
const DofMap & get_dof_map() const
const SparseMatrix< Number > * request_matrix(std::string_view mat_name) const
The libMesh namespace provides an interface to certain functionality in the library.
static constexpr Real TOLERANCE
bool on_command_line(std::string arg)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
LinearConvergenceReason
Linear solver convergence flags (taken from the PETSc flags).