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!");
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.
std::streamsize precision() const
Get the associated write precision.
Real previous_dlambda_ds
The old parameter tangent value.
Real ds
The initial arclength stepsize, selected by the user.
Real ds_current
Value of stepsize currently in use.
void save_current_solution()
Stores the current solution and continuation parameter (as "previous_u" and "old_continuation_paramet...
NumericVector< Number > * z
Temporary vector "z" ... the solution of .
void set_Theta_LOCA()
A centralized function for setting the other normalization parameter, i.e.
bool quiet
If quiet==false, the System prints extra information about what it is doing.
NewtonSolver * newton_solver
A pointer to the underlying Newton solver used by the DiffSystem.
NumericVector< Number > * delta_u
Temporary vector "delta u" ... the Newton step update in our custom augmented PDE solve.
virtual ~ContinuationSystem()
Real min_continuation_parameter
The minimum-allowable value of the continuation parameter.
unsigned int n_arclength_reductions
Number of arclength reductions to try when Newton fails to reduce the residual.
virtual void solve() override
Perform a standard "solve" of the system, without doing continuation.
NumericVector< Number > * du_ds
Extra work vectors used by the continuation algorithm.
virtual void clear() override
Clear all the data structures associated with the system.
Real Theta
Arclength normalization parameter.
void apply_predictor()
Applies the predictor to the current solution to get a guess for the next solution.
void advance_arcstep()
Call this function after a continuation solve to compute the tangent and get the next initial guess.
void solve_tangent()
Special solve algorithm for solving the tangent system.
void update_solution()
This function (which assumes the most recent tangent vector has been computed) updates the solution a...
Real max_continuation_parameter
The maximum-allowable value of the continuation parameter.
ContinuationSystem(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
Real previous_ds
The previous arcstep length used.
Real ds_min
The minimum-allowed steplength, defaults to 1.e-8.
void continuation_solve()
Perform a continuation solve of the system.
bool newton_progress_check
True by default, the Newton progress check allows the Newton loop to exit if half the allowed iterati...
bool tangent_initialized
False until initialize_tangent() is called.
double initial_newton_tolerance
How much to try to reduce the residual by at the first (inexact) Newton step.
Real dlambda_ds
The most recent value of the derivative of the continuation parameter with respect to s.
Real * continuation_parameter
The continuation parameter must be a member variable of the derived class, and the "continuation_para...
Real old_continuation_parameter
The system also keeps track of the old value of the continuation parameter.
unsigned int newton_step
Loop counter for nonlinear (Newton) iteration loop.
virtual void init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
double continuation_parameter_tolerance
How tightly should the Newton iterations attempt to converge delta_lambda.
void initialize_tangent()
Before starting arclength continuation, we need at least 2 prior solutions (both solution and u_previ...
@ AB2
Second-order explicit Adams-Bashforth predictor.
@ Euler
First-order Euler predictor.
double solution_tolerance
How tightly should the Newton iterations attempt to converge ||delta_u|| Defaults to 1....
Real newton_stepgrowth_aggressiveness
A measure of how rapidly one should attempt to grow the arclength stepsize based on the number of New...
NumericVector< Number > * previous_u
The solution at the previous value of the continuation variable.
NumericVector< Number > * previous_du_ds
The value of du_ds from the previous solution.
void set_Theta()
A centralized function for setting the normalization parameter theta.
unsigned int n_backtrack_steps
Another scaling parameter suggested by the LOCA people.
Real Theta_LOCA
Another normalization parameter, which is described in the LOCA manual.
NumericVector< Number > * y
Temporary vector "y" ... stores -du/dlambda, the solution of .
NumericVector< Number > * y_old
Temporary vector "y_old" ... stores the previous value of -du/dlambda, which is the solution of .
unsigned int max_linear_iterations
Each linear solver step should exit after max_linear_iterations is exceeded.
unsigned int max_nonlinear_iterations
The DiffSolver should exit in failure if max_nonlinear_iterations is exceeded and continue_after_max_...
virtual void clear() override
Clear all the data structures associated with the system.
std::unique_ptr< TimeSolver > time_solver
A pointer to the solver object we're going to use.
virtual void solve() override
Invokes the solver associated with the system.
This is the EquationSystems class.
NumericVector< Number > * rhs
The system matrix.
This class provides a specific system class.
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 init_data() override
Initializes the member data fields associated with the system, so that, e.g., assemble() may be used.
SparseMatrix< Number > * matrix
The system matrix.
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
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.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
virtual T dot(const NumericVector< T > &v) const =0
virtual Real l2_norm() const =0
virtual void scale(const T factor)=0
Scale each element of the vector by the given factor.
virtual void zero()=0
Set all entries to zero.
virtual void add(const numeric_index_type i, const T value)=0
Adds value to the vector entry specified by i.
const Parallel::Communicator & comm() const
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
bool prefix_with_name() 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.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
std::string prefix() const
The libMesh namespace provides an interface to certain functionality in the library.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real