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.