30 "relative_tolerance", 1e-8,
"Relative convergence tolerance for Newton iteration");
32 "absolute_tolerance", 1e-11,
"Absolute convergence tolerance for Newton iteration");
35 "Factor applied to relative and absolute " 36 "tolerance for acceptable convergence if " 37 "iterations are no longer making progress");
40 MooseEnum internal_solve_output_on_enum(
"never on_error always",
"on_error");
42 internal_solve_output_on_enum,
43 "When to output internal Newton solve information");
44 params.
addParam<
bool>(
"internal_solve_full_iteration_history",
46 "Set true to output full internal Newton iteration history at times " 47 "determined by `internal_solve_output_on`. If false, only a summary is " 56 : _check_range(false),
58 _bracket_solution(false),
59 _internal_solve_output_on(
62 _internal_solve_full_iteration_history(
63 parameters.
get<bool>(
"internal_solve_full_iteration_history")),
64 _relative_tolerance(parameters.
get<
Real>(
"relative_tolerance")),
65 _absolute_tolerance(parameters.
get<
Real>(
"absolute_tolerance")),
66 _acceptable_multiplier(parameters.
get<
Real>(
"acceptable_multiplier")),
68 _residual_history(_num_resids,
std::numeric_limits<
Real>::
max()),
70 _initial_residual(0.0),
72 _svrms_name(parameters.getObjectName())
81 return std::numeric_limits<Real>::lowest();
89 return std::numeric_limits<Real>::max();
101 std::unique_ptr<std::stringstream> iter_output =
102 (_internal_solve_output_on == InternalSolveOutput::ALWAYS)
103 ? std::make_unique<std::stringstream>()
109 internalSolve(stress_dev,
112 _internal_solve_full_iteration_history ? iter_output.get() :
nullptr);
113 if (solve_state != SolveState::SUCCESS &&
114 _internal_solve_output_on != InternalSolveOutput::ALWAYS)
117 if (_internal_solve_output_on == InternalSolveOutput::NEVER)
122 iter_output = std::make_unique<std::stringstream>();
127 case SolveState::NAN_INF:
128 *iter_output <<
"Encountered inf or nan in material return mapping iterations.\n";
131 case SolveState::EXCEEDED_ITERATIONS:
132 *iter_output <<
"Exceeded maximum iterations in material return mapping iterations.\n";
141 if (_internal_solve_full_iteration_history)
142 internalSolve(stress_dev, stress_new, scalar, iter_output.get());
145 outputIterationSummary(iter_output.get(), _iteration);
146 mooseException(iter_output->str());
149 if (_internal_solve_output_on == InternalSolveOutput::ALWAYS)
152 outputIterationSummary(iter_output.get(), _iteration);
153 console << iter_output->str();
157 template <
bool is_ad>
163 std::stringstream * iter_output)
165 delta_gamma = initialGuess(stress_dev);
168 const GenericReal<is_ad> min_permissible_scalar = minimumPermissibleValue(stress_dev);
169 const GenericReal<is_ad> max_permissible_scalar = maximumPermissibleValue(stress_dev);
174 _initial_residual = _residual = computeResidual(stress_dev, stress_new, delta_gamma);
177 Real reference_residual =
178 computeReferenceResidual(stress_dev, stress_new, _residual, delta_gamma);
180 if (
converged(_residual, reference_residual))
182 iterationFinalize(delta_gamma);
183 outputIterationStep(iter_output, stress_dev, delta_gamma, reference_residual);
184 return SolveState::SUCCESS;
187 _residual_history.assign(_num_resids, std::numeric_limits<Real>::max());
190 while (_iteration < _max_its && !
converged(_residual, reference_residual) &&
191 !convergedAcceptable(_iteration, reference_residual))
193 scalar_increment = -_residual / computeDerivative(stress_dev, stress_new, delta_gamma);
194 delta_gamma = scalar_old + scalar_increment;
197 checkPermissibleRange(delta_gamma,
200 min_permissible_scalar,
201 max_permissible_scalar,
204 _residual = computeResidual(stress_dev, stress_new, delta_gamma);
206 reference_residual = computeReferenceResidual(stress_dev, stress_new, _residual, delta_gamma);
207 iterationFinalize(delta_gamma);
209 if (_bracket_solution)
210 updateBounds(delta_gamma,
217 if (
converged(_residual, reference_residual))
219 outputIterationStep(iter_output, stress_dev, delta_gamma, reference_residual);
224 bool modified_increment =
false;
226 if (_bracket_solution)
230 if (scalar_old + scalar_increment >= scalar_upper_bound ||
231 scalar_old + scalar_increment <= scalar_lower_bound)
233 if (scalar_upper_bound != max_permissible_scalar &&
234 scalar_lower_bound != min_permissible_scalar)
236 const Real frac = 0.5;
238 (1.0 - frac) * scalar_lower_bound + frac * scalar_upper_bound - scalar_old;
239 modified_increment =
true;
241 *iter_output <<
" Trial scalar_increment exceeded bounds. Setting between " 242 "lower/upper bounds. frac: " 243 << frac << std::endl;
250 if (modified_increment)
252 delta_gamma = scalar_old + scalar_increment;
253 _residual = computeResidual(stress_dev, stress_new, delta_gamma);
255 computeReferenceResidual(stress_dev, stress_new, _residual, delta_gamma);
256 iterationFinalize(delta_gamma);
258 if (_bracket_solution)
259 updateBounds(delta_gamma,
268 outputIterationStep(iter_output, stress_dev, delta_gamma, reference_residual);
271 scalar_old = delta_gamma;
275 using std::isnan, std::isinf;
277 return SolveState::NAN_INF;
279 if (_iteration == _max_its)
280 return SolveState::EXCEEDED_ITERATIONS;
282 return SolveState::SUCCESS;
285 template <
bool is_ad>
288 const Real & reference)
291 return (std::abs(residual) <= _absolute_tolerance ||
292 std::abs(residual / reference) <= _relative_tolerance);
295 template <
bool is_ad>
298 const Real & reference)
304 if (it < _num_resids)
310 const Real convergence_history_factor = 10.0;
311 if (
abs(_residual * convergence_history_factor) <
abs(_residual_history[(it + 1) % _num_resids]))
316 return converged(_residual / _acceptable_multiplier, reference);
319 template <
bool is_ad>
327 std::stringstream * iter_output)
329 if (scalar > max_permissible_scalar)
331 scalar_increment = (max_permissible_scalar - scalar_old) / 2.0;
332 scalar = scalar_old + scalar_increment;
334 *iter_output <<
"Scalar greater than maximum (" 339 else if (scalar < min_permissible_scalar)
341 scalar_increment = (min_permissible_scalar - scalar_old) / 2.0;
342 scalar = scalar_old + scalar_increment;
350 template <
bool is_ad>
354 const Real init_resid_sign,
357 std::stringstream * iter_output)
360 if (residual * init_resid_sign < 0.0 && scalar < scalar_upper_bound)
362 scalar_upper_bound = scalar;
363 if (scalar_upper_bound < scalar_lower_bound)
365 scalar_upper_bound = scalar_lower_bound;
366 scalar_lower_bound = 0.0;
368 *iter_output <<
" Corrected for scalar_upper_bound < scalar_lower_bound" << std::endl;
373 else if (residual * init_resid_sign > 0.0 && scalar > scalar_lower_bound &&
374 scalar < scalar_upper_bound)
375 scalar_lower_bound = scalar;
378 template <
bool is_ad>
381 std::stringstream * iter_output,
388 const unsigned int it = _iteration;
391 *iter_output <<
" iteration=" << it
394 <<
" ref_res=" << reference_residual
395 <<
" rel_res=" << std::abs(residual) / reference_residual
396 <<
" rel_tol=" << _relative_tolerance <<
" abs_res=" << std::abs(residual)
397 <<
" abs_tol=" << _absolute_tolerance <<
'\n';
401 template <
bool is_ad>
404 std::stringstream * iter_output,
const unsigned int total_it)
407 *iter_output <<
"In " << total_it <<
" iterations the residual went from " MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
Moose::GenericType< Real, is_ad > GenericReal
void returnMappingSolve(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, GenericReal< is_ad > &scalar, const ConsoleStream &console)
Perform the return mapping iterations.
void mooseError(Args &&... args)
void updateBounds(const GenericReal< is_ad > &scalar, const GenericReal< is_ad > &residual, const Real init_resid_sign, GenericReal< is_ad > &scalar_upper_bound, GenericReal< is_ad > &scalar_lower_bound, std::stringstream *iter_output)
Update the upper and lower bounds of the root for the effective inelastic strain. ...
Moose::GenericType< DenseVector< Real >, is_ad > GenericDenseVector
bool converged(const GenericReal< is_ad > &residual, const Real &reference)
Check to see whether the residual is within the convergence limits.
auto max(const L &left, const R &right)
bool converged(const std::vector< std::pair< unsigned int, Real >> &residuals, const std::vector< Real > &abs_tolerances)
Based on the residuals, determine if the iterative process converged or not.
virtual void outputIterationStep(std::stringstream *iter_output, const GenericDenseVector< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar, const GenericReal< is_ad > reference_residual)
Output information for a single iteration step to build the convergence history of the model...
void checkPermissibleRange(GenericReal< is_ad > &scalar, GenericReal< is_ad > &scalar_increment, const GenericReal< is_ad > &scalar_old, const GenericReal< is_ad > min_permissible_scalar, const GenericReal< is_ad > max_permissible_scalar, std::stringstream *iter_output)
Check to see whether solution is within admissible range, and set it within that range if it is not...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static InputParameters validParams()
Base class that provides capability for Newton generalized (anisotropic) return mapping iterations on...
bool convergedAcceptable(const unsigned int it, const Real &reference)
Check to see whether the residual is within acceptable convergence limits.
virtual void outputIterationSummary(std::stringstream *iter_output, const unsigned int total_it)
Output summary information for the convergence history of the model.
SolveState internalSolve(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, GenericReal< is_ad > &scalar, std::stringstream *iter_output=nullptr)
Method called from within this class to perform the actual return mappping iterations.
virtual GenericReal< is_ad > maximumPermissibleValue(const GenericDenseVector< is_ad > &effective_trial_stress) const
Compute the maximum permissible value of the scalar.
virtual GenericReal< is_ad > minimumPermissibleValue(const GenericDenseVector< is_ad > &effective_trial_stress) const
Compute the minimum permissible value of the scalar.
GeneralizedReturnMappingSolutionTempl(const InputParameters ¶meters)
const Elem & get(const ElemType type_in)