Go to the documentation of this file.
19 #include "libmesh/equation_systems.h"
20 #include "libmesh/continuation_system.h"
21 #include "libmesh/linear_solver.h"
22 #include "libmesh/time_solver.h"
23 #include "libmesh/newton_solver.h"
24 #include "libmesh/sparse_matrix.h"
30 const std::string & name_in,
31 const unsigned int number_in) :
32 Parent(es, name_in, number_in),
33 continuation_parameter(nullptr),
35 continuation_parameter_tolerance(1.e-6),
36 solution_tolerance(1.e-6),
37 initial_newton_tolerance(0.01),
38 old_continuation_parameter(0.),
39 min_continuation_parameter(0.),
40 max_continuation_parameter(0.),
44 n_arclength_reductions(5),
47 newton_stepgrowth_aggressiveness(1.),
48 newton_progress_check(true),
51 tangent_initialized(false),
52 newton_solver(nullptr),
56 previous_dlambda_ds(0.),
61 libmesh_experimental();
291 libmesh_assert_not_equal_to (dlambda, 0.0);
362 libmesh_error_msg(
"You must set the continuation_parameter pointer " \
363 <<
"to a member variable of the derived class, preferably in the " \
364 <<
"Derived class's init_data function. This is how the ContinuationSystem " \
365 <<
"updates the continuation parameter.");
391 std::pair<unsigned int, Real> rval;
394 bool arcstep_converged =
false;
407 bool newton_converged =
false;
410 Real nonlinear_residual_firststep = 0.;
413 Real nonlinear_residual_beforestep = 0.;
416 Real nonlinear_residual_afterstep = 0.;
419 double current_linear_tolerance = 0.;
448 libmesh_assert_not_equal_to (nonlinear_residual_beforestep, 0.0);
449 libmesh_assert_not_equal_to (nonlinear_residual_afterstep, 0.0);
451 current_linear_tolerance =
452 double(std::min(gam*
std::pow(nonlinear_residual_afterstep/nonlinear_residual_beforestep, alp),
453 current_linear_tolerance*current_linear_tolerance));
456 if (current_linear_tolerance < 1.e-12)
457 current_linear_tolerance = 1.e-12;
461 libMesh::out <<
"Using current_linear_tolerance=" << current_linear_tolerance << std::endl;
475 nonlinear_residual_beforestep =
rhs->
l2_norm();
480 nonlinear_residual_firststep = nonlinear_residual_beforestep;
483 libMesh::out <<
" (before step) ||R||_{L2} = " << nonlinear_residual_beforestep << std::endl;
484 libMesh::out <<
" (before step) ||R||_{L2}/||u|| = " << nonlinear_residual_beforestep / old_norm_u << std::endl;
491 libMesh::out <<
"Initial guess satisfied linear tolerance, exiting with zero Newton iterations!" << std::endl;
496 newton_converged=
true;
503 nonlinear_residual_beforestep = nonlinear_residual_afterstep;
523 current_linear_tolerance,
530 libMesh::out <<
"Repeating initial solve with smaller linear tolerance!" << std::endl;
537 libmesh_error_msg(
"Linear solver did no work!");
540 }
while (rval.first==0);
546 <<
" linear tolerance = "
556 if ((rval.first == 0) && (rval.second > current_linear_tolerance*nonlinear_residual_beforestep))
559 libMesh::out <<
"Linear solver exited in zero iterations!" << std::endl;
588 libmesh_error_msg(
"||G_Lambda|| = 0");
592 const double ysystemtol =
593 double(current_linear_tolerance*(nonlinear_residual_beforestep/yrhsnorm));
595 libMesh::out <<
"ysystemtol=" << ysystemtol << std::endl;
621 libMesh::out <<
" G_u*y = G_{lambda} solver converged at step "
623 <<
", linear tolerance = "
632 if ((rval.first == 0) && (rval.second > ysystemtol))
635 libMesh::out <<
"Linear solver exited in zero iterations!" << std::endl;
666 const Number N = N1+N2-N3;
681 libmesh_assert_not_equal_to (delta_lambda_denominator, 0.0);
684 const Number delta_lambda_comp = delta_lambda_numerator /
685 delta_lambda_denominator;
706 nonlinear_residual_afterstep =
rhs->
l2_norm();
715 libMesh::out <<
" norm_du_norm_R=" << norm_du_norm_R << std::endl;
719 Real newton_stepfactor = 1.;
721 const bool attempt_backtracking =
723 && (nonlinear_residual_afterstep > nonlinear_residual_beforestep)
725 && (norm_du_norm_R > 1.)
729 if (attempt_backtracking)
732 libMesh::out <<
"Newton step did not reduce residual." << std::endl;
741 for (
unsigned int backtrack_step=0; backtrack_step<
n_backtrack_steps; ++backtrack_step)
743 newton_stepfactor *= 0.5;
746 libMesh::out <<
"Shrinking step size by " << newton_stepfactor << std::endl;
757 nonlinear_residual_afterstep =
rhs->
l2_norm();
762 <<
", nonlinear_residual_afterstep="
763 << nonlinear_residual_afterstep
766 if (nonlinear_residual_afterstep < nonlinear_residual_beforestep)
789 if ((attempt_backtracking) && (nonlinear_residual_afterstep > nonlinear_residual_beforestep))
804 libMesh::out <<
"Backtracking could not reduce residual ... continuing anyway!" << std::endl;
822 if ((nonlinear_residual_afterstep > nonlinear_residual_firststep) &&
825 libMesh::out <<
"Progress check failed: the current residual: "
826 << nonlinear_residual_afterstep
828 <<
"larger than the initial residual, and half of the allowed\n"
829 <<
"number of Newton iterations have elapsed.\n"
830 <<
"Exiting Newton iterations with converged==false." << std::endl;
839 libMesh::out <<
"Continuation parameter fell below min-allowable value." << std::endl;
847 libMesh::out <<
"Current continuation parameter value: "
849 <<
" exceeded max-allowable value."
859 libMesh::out <<
" delta_lambda = " << delta_lambda << std::endl;
860 libMesh::out <<
" newton_stepfactor*delta_lambda = " << newton_stepfactor*delta_lambda << std::endl;
862 libMesh::out <<
" ||delta_u|| = " << norm_delta_u << std::endl;
863 libMesh::out <<
" ||delta_u||/||u|| = " << norm_delta_u / norm_u << std::endl;
873 libMesh::out <<
" ||R||_{L2} = " << norm_residual << std::endl;
874 libMesh::out <<
" ||R||_{L2}/||u|| = " << norm_residual / norm_u << std::endl;
886 libMesh::out <<
"Newton iterations converged!" << std::endl;
888 newton_converged =
true;
893 if (!newton_converged)
895 libMesh::out <<
"Newton iterations of augmented system did not converge!" << std::endl;
911 arcstep_converged=
true;
919 if (!arcstep_converged)
920 libmesh_error_msg(
"Arcstep failed to converge after max number of reductions! Exiting...");
965 cast_ptr<NewtonSolver *> (this->
time_solver->diff_solver().get());
978 std::pair<unsigned int, Real> rval =
989 libMesh::out <<
"G_u*y = G_{lambda} solver converged at step "
991 <<
" linear tolerance = "
1036 const Real sgn_dlambda_ds =
1040 if (sgn_dlambda_ds < 0.)
1043 libMesh::out <<
"dlambda_ds is negative." << std::endl;
1214 const Real yold_over_y = yoldnorm/ynorm;
1221 libMesh::out <<
"yoldnorm/ynorm=" << yoldnorm/ynorm << std::endl;
1242 if (yold_over_y > 1.e-6)
1267 const Real double_threshold = 0.5;
1268 const Real halve_threshold = 0.5;
1269 if (yold_over_y > double_threshold)
1271 else if (yold_over_y < halve_threshold)
1287 const Real newtonstep_growthfactor =
1289 static_cast<Real>(Nmax) / static_cast<Real>(
newton_step+1);
1292 libMesh::out <<
"newtonstep_growthfactor=" << newtonstep_growthfactor << std::endl;
1306 libMesh::out <<
"Enforcing minimum-allowed arclength stepsize of " <<
ds_min << std::endl;
1341 libMesh::out <<
"Updating the solution with the tangent guess." << std::endl;
1408 libmesh_error_msg(
"Unknown predictor!");
Real Theta_LOCA
Another normalization parameter, which is described in the LOCA manual.
virtual ~ContinuationSystem()
Destructor.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
NumericVector< Number > * du_ds
Extra work vectors used by the continuation algorithm.
virtual void zero()=0
Set all entries to zero.
Real ds_current
Value of stepsize currently in use.
virtual void add(const numeric_index_type i, const T value)=0
Adds value to each entry of the vector.
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
bool tangent_initialized
False until initialize_tangent() is called.
NumericVector< Number > * rhs
The system matrix.
std::ios_base::fmtflags setf(std::ios_base::fmtflags fmtfl)
Set the associated flags.
void unsetf(std::ios_base::fmtflags mask)
Clear the associated flags.
Real ds_min
The minimum-allowed steplength, defaults to 1.e-8.
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
virtual void solve() override
Perform a standard "solve" of the system, without doing continuation.
The libMesh namespace provides an interface to certain functionality in the library.
NumericVector< Number > * z
Temporary vector "z" ...
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
MetaPhysicL::DualNumber< T, D > sqrt(const MetaPhysicL::DualNumber< T, D > &in)
Real ds
The initial arclength stepsize, selected by the user.
NumericVector< Number > * y
Temporary vector "y" ...
This class provides a specific system class.
Real min_continuation_parameter
The minimum-allowable value of the continuation parameter.
void continuation_solve()
Perform a continuation solve of the system.
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use.
Real * continuation_parameter
The continuation parameter must be a member variable of the derived class, and the "continuation_para...
First-order Euler predictor.
std::unique_ptr< LinearSolver< Number > > linear_solver
We maintain our own linear solver interface, for solving custom systems of equations and/or things wh...
Real previous_ds
The previous arcstep length used.
MetaPhysicL::DualNumber< T, D > abs(const MetaPhysicL::DualNumber< T, D > &in)
Real previous_dlambda_ds
The old parameter tangent value.
NumericVector< Number > * delta_u
Temporary vector "delta u" ...
void solve_tangent()
Special solve algorithm for solving the tangent system.
NumericVector< Number > * y_old
Temporary vector "y_old" ...
Real max_continuation_parameter
The maximum-allowable value of the continuation parameter.
NumericVector< Number > * previous_du_ds
The value of du_ds from the previous solution.
void set_Theta_LOCA()
A centralized function for setting the other normalization parameter, i.e.
virtual void solve() override
Invokes the solver associated with the system.
bool newton_progress_check
True by default, the Newton progress check allows the Newton loop to exit if half the allowed iterati...
SparseMatrix< Number > * matrix
The system matrix.
unsigned int n_backtrack_steps
Another scaling parameter suggested by the LOCA people.
void apply_predictor()
Applies the predictor to the current solution to get a guess for the next solution.
unsigned int newton_step
Loop counter for nonlinear (Newton) iteration loop.
virtual void clear() override
Clear all the data structures associated with the system.
double pow(double a, int b)
double solution_tolerance
How tightly should the Newton iterations attempt to converge ||delta_u|| Defaults to 1....
Real old_continuation_parameter
The system also keeps track of the old value of the continuation parameter.
void save_current_solution()
Stores the current solution and continuation parameter (as "previous_u" and "old_continuation_paramet...
virtual void assembly(bool get_residual, bool get_jacobian, bool apply_heterogeneous_constraints=false, bool apply_no_constraints=false) override
Prepares matrix or rhs for matrix assembly.
virtual void clear() override
Clear all the data structures associated with the system.
This is the EquationSystems class.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
bool quiet
If quiet==false, the System prints extra information about what it is doing.
const std::string & name() const
This base class can be inherited from to provide interfaces to linear solvers from different packages...
Real newton_stepgrowth_aggressiveness
A measure of how rapidly one should attempt to grow the arclength stepsize based on the number of New...
void advance_arcstep()
Call this function after a continuation solve to compute the tangent and get the next initial guess.
unsigned int max_linear_iterations
Each linear solver step should exit after max_linear_iterations is exceeded.
unsigned int n_arclength_reductions
Number of arclength reductions to try when Newton fails to reduce the residual.
std::streamsize precision() const
Get the associated write precision.
Second-order explicit Adams-Bashforth predictor.
void initialize_tangent()
Before starting arclength continuation, we need at least 2 prior solutions (both solution and u_previ...
ContinuationSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
virtual Real l2_norm() const =0
bool on_command_line(std::string arg)
virtual void scale(const T factor)=0
Scale each element of the vector by the given factor.
NumericVector< Number > & add_vector(const std::string &vec_name, const bool projections=true, const ParallelType type=PARALLEL)
Adds the additional vector vec_name to this system.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int max_nonlinear_iterations
The DiffSolver should exit in failure if max_nonlinear_iterations is exceeded and continue_after_max_...
Real Theta
Arclength normalization parameter.
double initial_newton_tolerance
How much to try to reduce the residual by at the first (inexact) Newton step.
void set_Theta()
A centralized function for setting the normalization parameter theta.
double continuation_parameter_tolerance
How tightly should the Newton iterations attempt to converge delta_lambda.
void update_solution()
This function (which assumes the most recent tangent vector has been computed) updates the solution a...
NumericVector< Number > * previous_u
The solution at the previous value of the continuation variable.
virtual T dot(const NumericVector< T > &v) const =0
Real dlambda_ds
The most recent value of the derivative of the continuation parameter with respect to s.
NewtonSolver * newton_solver
A pointer to the underlying Newton solver used by the DiffSystem.