32 "relative_tolerance", 1e-8,
"Relative convergence tolerance for Newton iteration");
34 "absolute_tolerance", 1e-11,
"Absolute convergence tolerance for Newton iteration");
37 "Factor applied to relative and absolute " 38 "tolerance for acceptable convergence if " 39 "iterations are no longer making progress");
42 MooseEnum internal_solve_output_on_enum(
"never on_error always",
"on_error");
44 internal_solve_output_on_enum,
45 "When to output internal Newton solve information");
46 params.
addParam<
bool>(
"internal_solve_full_iteration_history",
48 "Set true to output full internal Newton iteration history at times " 49 "determined by `internal_solve_output_on`. If false, only a summary is " 54 params.
addParam<
bool>(
"automatic_differentiation_return_mapping",
56 "Whether to use automatic differentiation to compute the derivative.");
63 : _check_range(false),
65 _bracket_solution(true),
66 _internal_solve_output_on(
69 _internal_solve_full_iteration_history(
70 parameters.
get<bool>(
"internal_solve_full_iteration_history")),
71 _relative_tolerance(parameters.
get<
Real>(
"relative_tolerance")),
72 _absolute_tolerance(parameters.
get<
Real>(
"absolute_tolerance")),
73 _acceptable_multiplier(parameters.
get<
Real>(
"acceptable_multiplier")),
74 _ad_derivative(parameters.
get<bool>(
"automatic_differentiation_return_mapping")),
76 _residual_history(_num_resids,
std::numeric_limits<
Real>::
max()),
78 _initial_residual(0.0),
80 _svrms_name(parameters.
get<
std::string>(
"_object_name"))
89 return std::numeric_limits<Real>::lowest();
97 return std::numeric_limits<Real>::max();
100 template <
bool is_ad>
108 std::unique_ptr<std::stringstream> iter_output =
109 (_internal_solve_output_on == InternalSolveOutput::ALWAYS)
110 ? std::make_unique<std::stringstream>()
116 internalSolve(effective_trial_stress,
118 _internal_solve_full_iteration_history ? iter_output.get() :
nullptr);
119 if (solve_state != SolveState::SUCCESS &&
120 _internal_solve_output_on != InternalSolveOutput::ALWAYS)
123 if (_internal_solve_output_on == InternalSolveOutput::NEVER)
128 iter_output = std::make_unique<std::stringstream>();
133 case SolveState::NAN_INF:
134 *iter_output <<
"Encountered inf or nan in material return mapping iterations.\n";
137 case SolveState::EXCEEDED_ITERATIONS:
138 *iter_output <<
"Exceeded maximum iterations in material return mapping iterations.\n";
147 if (_internal_solve_full_iteration_history)
148 internalSolve(effective_trial_stress, scalar, iter_output.get());
151 outputIterationSummary(iter_output.get(), _iteration);
152 mooseException(iter_output->str());
155 if (_internal_solve_output_on == InternalSolveOutput::ALWAYS)
158 outputIterationSummary(iter_output.get(), _iteration);
159 console << iter_output->str() << std::flush;
163 template <
bool is_ad>
168 std::stringstream * iter_output)
170 scalar = initialGuess(effective_trial_stress);
173 const GenericReal<is_ad> min_permissible_scalar = minimumPermissibleValue(effective_trial_stress);
174 const GenericReal<is_ad> max_permissible_scalar = maximumPermissibleValue(effective_trial_stress);
179 computeResidualAndDerivativeHelper(effective_trial_stress, scalar);
180 _initial_residual = _residual;
184 Real reference_residual = computeReferenceResidual(effective_trial_stress, scalar);
186 if (converged(_residual, reference_residual))
188 iterationFinalize(scalar);
189 outputIterationStep(iter_output, effective_trial_stress, scalar, reference_residual);
190 return SolveState::SUCCESS;
193 _residual_history.assign(_num_resids, std::numeric_limits<Real>::max());
196 while (_iteration < _max_its && !converged(_residual, reference_residual) &&
197 !convergedAcceptable(_iteration, reference_residual))
199 preStep(scalar_old, _residual, _derivative);
201 scalar_increment = -_residual / _derivative;
202 scalar = scalar_old + scalar_increment;
205 checkPermissibleRange(scalar,
208 min_permissible_scalar,
209 max_permissible_scalar,
212 computeResidualAndDerivativeHelper(effective_trial_stress, scalar);
213 reference_residual = computeReferenceResidual(effective_trial_stress, scalar);
214 iterationFinalize(scalar);
216 if (_bracket_solution)
218 scalar, _residual, init_resid_sign, scalar_upper_bound, scalar_lower_bound, iter_output);
220 if (converged(_residual, reference_residual))
222 outputIterationStep(iter_output, effective_trial_stress, scalar, reference_residual);
227 bool modified_increment =
false;
232 if (residual_old - _residual != 0.0)
239 modified_increment =
true;
240 scalar_increment *=
alpha;
249 if (_bracket_solution)
253 if (scalar_old + scalar_increment >= scalar_upper_bound ||
254 scalar_old + scalar_increment <= scalar_lower_bound)
256 if (scalar_upper_bound != max_permissible_scalar &&
257 scalar_lower_bound != min_permissible_scalar)
259 const Real frac = 0.5;
261 (1.0 - frac) * scalar_lower_bound + frac * scalar_upper_bound - scalar_old;
262 modified_increment =
true;
264 *iter_output <<
" Trial scalar_increment exceeded bounds. Setting between " 265 "lower/upper bounds. frac: " 266 << frac << std::endl;
273 if (modified_increment)
275 scalar = scalar_old + scalar_increment;
276 computeResidualAndDerivativeHelper(effective_trial_stress, scalar);
277 reference_residual = computeReferenceResidual(effective_trial_stress, scalar);
278 iterationFinalize(scalar);
280 if (_bracket_solution)
290 outputIterationStep(iter_output, effective_trial_stress, scalar, reference_residual);
293 residual_old = _residual;
299 return SolveState::NAN_INF;
301 if (_iteration == _max_its)
302 return SolveState::EXCEEDED_ITERATIONS;
304 return SolveState::SUCCESS;
307 template <
bool is_ad>
316 _residual = residual_and_derivative.value();
317 _derivative = residual_and_derivative.derivatives();
321 _residual = computeResidual(effective_trial_stress, scalar);
322 _derivative = computeDerivative(effective_trial_stress, scalar);
326 template <
bool is_ad>
329 const Real reference)
332 return (
std::abs(residual) <= _absolute_tolerance ||
333 std::abs(residual / reference) <= _relative_tolerance);
336 template <
bool is_ad>
339 const Real reference)
343 if (it < _num_resids)
349 const Real convergence_history_factor = 10.0;
350 if (
std::abs(_residual * convergence_history_factor) <
351 std::abs(_residual_history[(it + 1) % _num_resids]))
356 return converged(_residual / _acceptable_multiplier, reference);
359 template <
bool is_ad>
367 std::stringstream * iter_output)
369 if (scalar > max_permissible_scalar)
371 scalar_increment = (max_permissible_scalar - scalar_old) / 2.0;
372 scalar = scalar_old + scalar_increment;
374 *iter_output <<
"Scalar greater than maximum (" 379 else if (scalar < min_permissible_scalar)
381 scalar_increment = (min_permissible_scalar - scalar_old) / 2.0;
382 scalar = scalar_old + scalar_increment;
390 template <
bool is_ad>
395 const Real init_resid_sign,
398 std::stringstream * iter_output)
401 if (residual * init_resid_sign < 0.0 && scalar < scalar_upper_bound)
403 scalar_upper_bound = scalar;
404 if (scalar_upper_bound < scalar_lower_bound)
406 scalar_upper_bound = scalar_lower_bound;
407 scalar_lower_bound = 0.0;
409 *iter_output <<
" Corrected for scalar_upper_bound < scalar_lower_bound" << std::endl;
414 else if (residual * init_resid_sign > 0.0 && scalar > scalar_lower_bound &&
415 scalar < scalar_upper_bound)
416 scalar_lower_bound = scalar;
419 template <
bool is_ad>
422 std::stringstream * iter_output,
425 const Real reference_residual)
429 const unsigned int it = _iteration;
432 *iter_output <<
" iteration=" << it
435 <<
" ref_res=" << reference_residual
436 <<
" rel_res=" <<
std::abs(residual) / reference_residual
437 <<
" rel_tol=" << _relative_tolerance <<
" abs_res=" <<
std::abs(residual)
438 <<
" abs_tol=" << _absolute_tolerance <<
'\n';
442 template <
bool is_ad>
445 std::stringstream * iter_output,
const unsigned int total_it)
448 *iter_output <<
"In " << total_it <<
" iterations the residual went from "
virtual void outputIterationStep(std::stringstream *iter_output, const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar, const Real reference_residual)
Output information for a single iteration step to build the convergence history of the model...
virtual GenericReal< is_ad > maximumPermissibleValue(const GenericReal< is_ad > &effective_trial_stress) const
Compute the maximum permissible value of the scalar.
void mooseError(Args &&... args)
bool convergedAcceptable(const unsigned int it, const Real reference)
Check to see whether the residual is within acceptable convergence limits.
SolveState internalSolve(const GenericReal< is_ad > effective_trial_stress, GenericReal< is_ad > &scalar, std::stringstream *iter_output=nullptr)
Method called from within this class to perform the actual return mappping iterations.
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...
static InputParameters validParams()
auto max(const L &left, const R &right)
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. ...
virtual GenericReal< is_ad > minimumPermissibleValue(const GenericReal< is_ad > &effective_trial_stress) const
Compute the minimum permissible value of the scalar.
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
void returnMappingSolve(const GenericReal< is_ad > &effective_trial_stress, GenericReal< is_ad > &scalar, const ConsoleStream &console)
Perform the return mapping iterations.
virtual void outputIterationSummary(std::stringstream *iter_output, const unsigned int total_it)
Output summary information for the convergence history of the model.
Base class that provides capability for Newton return mapping iterations on a single variable...
SingleVariableReturnMappingSolutionTempl(const InputParameters ¶meters)
typename Moose::GenericType< ChainedReal, is_ad > GenericChainedReal
void computeResidualAndDerivativeHelper(const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar)
Helper function to compute and set the _residual and _derivative.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string alpha
bool converged(const GenericReal< is_ad > &residual, const Real reference)
Check to see whether the residual is within the convergence limits.
typename Moose::GenericType< Real, is_ad > GenericReal
T clamp(const T &x, T2 lowerlimit, T2 upperlimit)
const Elem & get(const ElemType type_in)