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/numeric_vector.h" 25 #include "libmesh/sparse_matrix.h" 31 const std::string & name_in,
32 const unsigned int number_in) :
33 Parent(es, name_in, number_in),
34 continuation_parameter(nullptr),
36 continuation_parameter_tolerance(1.e-6),
37 solution_tolerance(1.e-6),
38 initial_newton_tolerance(0.01),
39 old_continuation_parameter(0.),
40 min_continuation_parameter(0.),
41 max_continuation_parameter(0.),
45 n_arclength_reductions(5),
48 newton_stepgrowth_aggressiveness(1.),
49 newton_progress_check(true),
51 tangent_initialized(false),
52 newton_solver(nullptr),
56 previous_dlambda_ds(0.),
61 libmesh_experimental();
292 libmesh_assert_not_equal_to (dlambda, 0.0);
363 "You must set the continuation_parameter pointer " 364 "to a member variable of the derived class, preferably in the " 365 "Derived class's init_data function. This is how the ContinuationSystem " 366 "updates the continuation parameter.");
392 std::pair<unsigned int, Real> rval;
395 bool arcstep_converged =
false;
408 bool newton_converged =
false;
411 Real nonlinear_residual_firststep = 0.;
414 Real nonlinear_residual_beforestep = 0.;
417 Real nonlinear_residual_afterstep = 0.;
420 double current_linear_tolerance = 0.;
446 const Real alp=0.5*(1.+std::sqrt(5.));
449 libmesh_assert_not_equal_to (nonlinear_residual_beforestep, 0.0);
450 libmesh_assert_not_equal_to (nonlinear_residual_afterstep, 0.0);
452 current_linear_tolerance =
453 double(std::min(gam*
std::pow(nonlinear_residual_afterstep/nonlinear_residual_beforestep, alp),
454 current_linear_tolerance*current_linear_tolerance));
457 if (current_linear_tolerance < 1.e-12)
458 current_linear_tolerance = 1.e-12;
462 libMesh::out <<
"Using current_linear_tolerance=" << current_linear_tolerance << std::endl;
476 nonlinear_residual_beforestep =
rhs->
l2_norm();
481 nonlinear_residual_firststep = nonlinear_residual_beforestep;
484 libMesh::out <<
" (before step) ||R||_{L2} = " << nonlinear_residual_beforestep << std::endl;
485 libMesh::out <<
" (before step) ||R||_{L2}/||u|| = " << nonlinear_residual_beforestep / old_norm_u << std::endl;
492 libMesh::out <<
"Initial guess satisfied linear tolerance, exiting with zero Newton iterations!" << std::endl;
497 newton_converged=
true;
504 nonlinear_residual_beforestep = nonlinear_residual_afterstep;
524 current_linear_tolerance,
531 libMesh::out <<
"Repeating initial solve with smaller linear tolerance!" << std::endl;
538 libmesh_error_msg(
"Linear solver did no work!");
541 }
while (rval.first==0);
547 <<
" linear tolerance = " 557 if ((rval.first == 0) && (rval.second > current_linear_tolerance*nonlinear_residual_beforestep))
560 libMesh::out <<
"Linear solver exited in zero iterations!" << std::endl;
588 libmesh_error_msg_if(yrhsnorm == 0.0,
"||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 libmesh_error_msg_if(!arcstep_converged,
"Arcstep failed to converge after max number of reductions! Exiting...");
964 cast_ptr<NewtonSolver *> (this->
time_solver->diff_solver().get());
977 std::pair<unsigned int, Real> rval =
988 libMesh::out <<
"G_u*y = G_{lambda} solver converged at step " 990 <<
" linear tolerance = " 1035 const Real sgn_dlambda_ds =
1039 if (sgn_dlambda_ds < 0.)
1042 libMesh::out <<
"dlambda_ds is negative." << std::endl;
1143 libmesh_assert_less (std::abs(
dlambda_ds), 1.);
1213 const Real yold_over_y = yoldnorm/ynorm;
1220 libMesh::out <<
"yoldnorm/ynorm=" << yoldnorm/ynorm << std::endl;
1241 if (yold_over_y > 1.e-6)
1266 const Real double_threshold = 0.5;
1267 const Real halve_threshold = 0.5;
1268 if (yold_over_y > double_threshold)
1270 else if (yold_over_y < halve_threshold)
1286 const Real newtonstep_growthfactor =
1291 libMesh::out <<
"newtonstep_growthfactor=" << newtonstep_growthfactor << std::endl;
1305 libMesh::out <<
"Enforcing minimum-allowed arclength stepsize of " <<
ds_min << std::endl;
1340 libMesh::out <<
"Updating the solution with the tangent guess." << std::endl;
1407 libmesh_error_msg(
"Unknown predictor!");
This is the EquationSystems class.
double initial_newton_tolerance
How much to try to reduce the residual by at the first (inexact) Newton step.
Real Theta
Arclength normalization parameter.
Real previous_dlambda_ds
The old parameter tangent value.
Real dlambda_ds
The most recent value of the derivative of the continuation parameter with respect to s...
NumericVector< Number > * previous_u
The solution at the previous value of the continuation variable.
virtual void clear() override
Clear all the data structures associated with the system.
std::streamsize precision() const
Get the associated write precision.
static std::unique_ptr< LinearSolver< T > > build(const libMesh::Parallel::Communicator &comm_in, const SolverPackage solver_package=libMesh::default_solver_package())
Builds a LinearSolver using the linear solver package specified by solver_package.
double continuation_parameter_tolerance
How tightly should the Newton iterations attempt to converge delta_lambda.
unsigned int max_nonlinear_iterations
The DiffSolver should exit in failure if max_nonlinear_iterations is exceeded and continue_after_max_...
Real old_continuation_parameter
The system also keeps track of the old value of the continuation parameter.
NumericVector< Number > * previous_du_ds
The value of du_ds from the previous solution.
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...
NumericVector< Number > * delta_u
Temporary vector "delta u" ...
NumericVector< Number > * rhs
The system matrix.
const Parallel::Communicator & comm() const
NumericVector< Number > & add_vector(std::string_view vec_name, const bool projections=true, const ParallelType type=PARALLEL)
Adds the additional vector vec_name to this system.
The libMesh namespace provides an interface to certain functionality in the library.
virtual T dot(const NumericVector< T > &v) const =0
This class provides a specific system class.
void continuation_solve()
Perform a continuation solve of the system.
virtual void zero()=0
Set all entries to zero.
void set_Theta_LOCA()
A centralized function for setting the other normalization parameter, i.e.
Real Theta_LOCA
Another normalization parameter, which is described in the LOCA manual.
Real ds_min
The minimum-allowed steplength, defaults to 1.e-8.
void advance_arcstep()
Call this function after a continuation solve to compute the tangent and get the next initial guess...
unsigned int n_arclength_reductions
Number of arclength reductions to try when Newton fails to reduce the residual.
bool tangent_initialized
False until initialize_tangent() is called.
virtual void scale(const T factor)=0
Scale each element of the vector by the given factor.
NumericVector< Number > * du_ds
Extra work vectors used by the continuation algorithm.
virtual Real l2_norm() const =0
Real max_continuation_parameter
The maximum-allowable value of the continuation parameter.
NumericVector< Number > * z
Temporary vector "z" ...
unsigned int max_linear_iterations
Each linear solver step should exit after max_linear_iterations is exceeded.
double solution_tolerance
How tightly should the Newton iterations attempt to converge ||delta_u|| Defaults to 1...
NumericVector< Number > * y_old
Temporary vector "y_old" ...
NumericVector< Number > * y
Temporary vector "y" ...
Real ds
The initial arclength stepsize, selected by the user.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used...
void apply_predictor()
Applies the predictor to the current solution to get a guess for the next solution.
void unsetf(std::ios_base::fmtflags mask)
Clear the associated flags.
Real newton_stepgrowth_aggressiveness
A measure of how rapidly one should attempt to grow the arclength stepsize based on the number of New...
bool quiet
If quiet==false, the System prints extra information about what it is doing.
Real previous_ds
The previous arcstep length used.
virtual void solve() override
Perform a standard "solve" of the system, without doing continuation.
void set_Theta()
A centralized function for setting the normalization parameter theta.
ContinuationSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
Real min_continuation_parameter
The minimum-allowable value of the continuation parameter.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
Real ds_current
Value of stepsize currently in use.
NewtonSolver * newton_solver
A pointer to the underlying Newton solver used by the DiffSystem.
void initialize_tangent()
Before starting arclength continuation, we need at least 2 prior solutions (both solution and u_previ...
void save_current_solution()
Stores the current solution and continuation parameter (as "previous_u" and "old_continuation_paramet...
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::ios_base::fmtflags setf(std::ios_base::fmtflags fmtfl)
Set the associated flags.
SparseMatrix< Number > * matrix
The system matrix.
virtual ~ContinuationSystem()
bool newton_progress_check
True by default, the Newton progress check allows the Newton loop to exit if half the allowed iterati...
unsigned int n_backtrack_steps
Another scaling parameter suggested by the LOCA people.
virtual void solve() override
Invokes the solver associated with the system.
virtual void clear() override
Clear all the data structures associated with the system.
void solve_tangent()
Special solve algorithm for solving the tangent system.
virtual void add(const numeric_index_type i, const T value)=0
Adds value to the vector entry specified by i.
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.
void update_solution()
This function (which assumes the most recent tangent vector has been computed) updates the solution a...
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used...
Second-order explicit Adams-Bashforth predictor.
First-order Euler predictor.
unsigned int newton_step
Loop counter for nonlinear (Newton) iteration loop.
bool prefix_with_name() const