20 params.
addClassDescription(
"Calculates the effective inelastic strain increment required to "
21 "return the isotropic stress state to a J2 yield surface. This class "
22 "is intended to be a parent class for classes with specific "
23 "constitutive models.");
25 params.
addParam<Real>(
"max_inelastic_increment",
27 "The maximum inelastic strain increment allowed in a time step");
29 "effective_inelastic_strain_name",
30 "Name of the material property that stores the effective inelastic strain");
31 params.
addParam<
bool>(
"use_substep",
false,
"Whether to use substepping");
33 MooseEnum substeppingType(
"NONE ERROR_BASED INCREMENT_BASED",
"NONE");
34 substeppingType.addDocumentation(
"NONE",
"Do not use substepping");
35 substeppingType.addDocumentation(
37 "Use substepping with a substep size that will yield, at most, the creep numerical "
38 "integration error given by substep_strain_tolerance.");
39 substeppingType.addDocumentation(
41 "Use substepping with a substep size that will keep each inelastic strain increment below "
42 "the maximum inelastic strain increment allowed in a time step.");
44 "use_substepping", substeppingType,
"Whether and how to use substepping");
46 "adaptive_substepping",
48 "Use adaptive substepping, where the number of substeps is successively doubled until the "
49 "return mapping model successfully converges or the maximum number of substeps is reached. ");
52 "use_substep",
false,
"Whether to use substepping",
"Use `use_substepping` instead");
53 params.
addParam<Real>(
"substep_strain_tolerance",
55 "Maximum ratio of the initial elastic strain increment at start of the "
56 "return mapping solve to the maximum inelastic strain allowable in a "
57 "single substep. Reduce this value to increase the number of substeps");
58 params.
addParam<
bool>(
"apply_strain",
true,
"Flag to apply strain. Used for testing.");
60 "effective_inelastic_strain_name substep_strain_tolerance apply_strain",
"Advanced");
61 params.
addParam<
bool>(
"use_substep_integration_error",
63 "If true, it establishes a substep size that will yield, at most,"
64 "the creep numerical integration error given by substep_strain_tolerance.");
65 params.
addParam<
unsigned>(
"maximum_number_substeps",
67 "The maximum number of substeps allowed before cutting the time step.");
76 _effective_inelastic_strain(this->template declareGenericProperty<Real, is_ad>(
78 this->template getParam<
std::string>(
"effective_inelastic_strain_name"))),
79 _effective_inelastic_strain_old(this->template getMaterialPropertyOld<Real>(
81 this->template getParam<
std::string>(
"effective_inelastic_strain_name"))),
82 _max_inelastic_increment(this->template getParam<Real>(
"max_inelastic_increment")),
83 _substep_tolerance(this->template getParam<Real>(
"substep_strain_tolerance")),
85 _identity_symmetric_four(
RankFourTensor::initIdentitySymmetricFour),
86 _deviatoric_projection_four(_identity_symmetric_four -
87 _identity_two.outerProduct(_identity_two) / 3.0),
88 _apply_strain(this->template getParam<bool>(
"apply_strain")),
91 _adaptive_substepping(this->template getParam<bool>(
"adaptive_substepping")),
92 _maximum_number_substeps(this->template getParam<unsigned>(
"maximum_number_substeps"))
98 "Remove this parameter and just keep `use_substepping` in the input");
100 if (parameters.
get<
bool>(
"use_substep"))
112 "maximum_number_substeps",
113 "The parameter maximum_number_substeps can only be used when the substepping option "
114 "(use_substepping) is not set to NONE");
118 "adaptive_substepping",
119 "The parameter adaptive_substepping can only be used when the substepping option "
120 "(use_substepping) is not set to NONE");
127 _effective_inelastic_strain[_qp] = 0.0;
144 _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp];
154 strain_increment.doubleContraction(strain_increment);
155 const Real effective_elastic_strain =
158 if (MooseUtils::absoluteFuzzyEqual(effective_elastic_strain, 0.0))
161 if (_use_substepping == SubsteppingType::INCREMENT_BASED)
163 const Real ratio = effective_elastic_strain / _max_inelastic_increment;
165 if (ratio > _substep_tolerance)
166 return std::ceil(ratio / _substep_tolerance);
170 if (_use_substepping == SubsteppingType::ERROR_BASED)
172 const Real accurate_time_step_ratio = _substep_tolerance / effective_elastic_strain;
174 if (accurate_time_step_ratio < 1.0)
175 return std::ceil(1.0 / accurate_time_step_ratio);
179 mooseError(
"calculateNumberSubsteps should not have been called. Notify a developer.");
188 mooseError(
"computeTangentOperator called: no tangent computation is needed for AD");
199 if (MooseUtils::absoluteFuzzyEqual(_effective_inelastic_strain_increment, 0.0))
200 tangent_operator.
zero();
210 mooseAssert(_three_shear_modulus != 0.0,
"Shear modulus is zero");
213 const Real norm_dev_stress_squared = deviatoric_stress.
doubleContraction(deviatoric_stress);
214 if (MooseUtils::absoluteFuzzyEqual(norm_dev_stress_squared, 0.0))
216 tangent_operator.
zero();
219 const Real norm_dev_stress = std::sqrt(norm_dev_stress_squared);
221 const RankTwoTensor flow_direction = deviatoric_stress / norm_dev_stress;
224 computeStressDerivative(effective_trial_stress, _effective_inelastic_strain_increment);
225 const Real scalar_one = _three_shear_modulus * _effective_inelastic_strain_increment /
226 std::sqrt(1.5) / norm_dev_stress;
228 tangent_operator = scalar_one * _deviatoric_projection_four +
229 (_three_shear_modulus * deriv - scalar_one) * flow_direction_dyad;
244 bool compute_full_tangent_operator,
255 deviatoric_trial_stress.doubleContraction(deviatoric_trial_stress);
257 ? sqrt(3.0 / 2.0 * dev_trial_stress_squared)
263 _three_shear_modulus != 0.0,
264 "Shear modulus is zero. Ensure that the base class computeStressInitialize() is called.");
267 _effective_inelastic_strain_increment = 0.0;
268 if (!MooseUtils::absoluteFuzzyEqual(effective_trial_stress, 0.0))
270 this->returnMappingSolve(
271 effective_trial_stress, _effective_inelastic_strain_increment, this->_console);
272 if (_effective_inelastic_strain_increment != 0.0)
273 inelastic_strain_increment =
274 deviatoric_trial_stress *
275 (1.5 * _effective_inelastic_strain_increment / effective_trial_stress);
277 inelastic_strain_increment.zero();
280 inelastic_strain_increment.zero();
284 strain_increment -= inelastic_strain_increment;
285 updateEffectiveInelasticStrain(_effective_inelastic_strain_increment);
293 computeStressFinalize(inelastic_strain_increment);
295 if constexpr (!is_ad)
297 if (compute_full_tangent_operator)
298 computeTangentOperator(effective_trial_stress, stress_new, tangent_operator);
302 libmesh_ignore(compute_full_tangent_operator);
303 libmesh_ignore(tangent_operator);
317 unsigned int total_number_substeps,
318 bool compute_full_tangent_operator,
324 if (total_number_substeps == 1)
326 updateState(strain_increment,
327 inelastic_strain_increment,
333 compute_full_tangent_operator,
336 this->storeIncrementalMaterialProperties(total_number_substeps);
340 if (total_number_substeps > _maximum_number_substeps)
341 mooseException(
"The number of substeps computed exceeds 'maximum_number_substeps'.");
344 _dt = _dt_original / total_number_substeps;
348 strain_increment / total_number_substeps;
360 for (
unsigned int step = 0; step < total_number_substeps; ++step)
366 Real effective_sub_stress_new;
367 if constexpr (!is_ad)
371 const Real dev_sub_stress_new_squared =
373 effective_sub_stress_new = sqrt(3.0 / 2.0 * dev_sub_stress_new_squared);
376 libmesh_ignore(effective_sub_stress_new);
379 updateState(sub_strain_increment,
380 sub_inelastic_strain_increment,
390 strain_increment += sub_strain_increment;
391 inelastic_strain_increment += sub_inelastic_strain_increment;
392 sub_elastic_strain_old += sub_strain_increment;
396 sub_effective_inelastic_strain_increment += _effective_inelastic_strain_increment;
398 if constexpr (!is_ad)
399 computeTangentOperator(effective_sub_stress_new, sub_stress_new, tangent_operator);
402 this->storeIncrementalMaterialProperties(total_number_substeps);
406 stress_new = sub_stress_new;
409 updateEffectiveInelasticStrain(sub_effective_inelastic_strain_increment);
422 bool compute_full_tangent_operator,
425 unsigned int num_substeps = calculateNumberSubsteps(strain_increment);
431 updateStateSubstepInternal(strain_increment,
432 inelastic_strain_increment,
439 compute_full_tangent_operator,
445 if (!_adaptive_substepping)
450 if (num_substeps <= _maximum_number_substeps)
465 mooseException(
"Adaptive substepping failed. Maximum number of substeps exceeded.");
483 return effective_trial_stress / _three_shear_modulus;
490 const Real scalar_inelastic_strain_incr =
492 _effective_inelastic_strain_old[_qp]);
493 if (!scalar_inelastic_strain_incr)
494 return std::numeric_limits<Real>::max();
496 return _dt * _max_inelastic_increment / scalar_inelastic_strain_incr;
502 const unsigned int total_it)
506 *iter_output <<
"At element " << _current_elem->id() <<
" _qp=" << _qp <<
" Coordinates "
507 << _q_point[_qp] <<
" block=" << _current_elem->subdomain_id() <<
'\n';
void mooseError(Args &&... args)
Moose::GenericType< RankFourTensor, is_ad > GenericRankFourTensor
Moose::GenericType< Real, is_ad > GenericReal
Moose::GenericType< RankTwoTensor, is_ad > GenericRankTwoTensor
const InputParameters & parameters() const
void paramError(const std::string ¶m, Args... args) const
const InputParameters & _pars
RadialReturnStressUpdate computes the radial return stress increment for an isotropic elastic-viscopl...
virtual void updateStateSubstepInternal(GenericRankTwoTensor< is_ad > &, GenericRankTwoTensor< is_ad > &, const GenericRankTwoTensor< is_ad > &, GenericRankTwoTensor< is_ad > &, const RankTwoTensor &, const GenericRankFourTensor< is_ad > &, const RankTwoTensor &, unsigned int total_number_substeps, bool compute_full_tangent_operator=false, RankFourTensor &tangent_operator=StressUpdateBaseTempl< is_ad >::_identityTensor)
void computeTangentOperator(Real effective_trial_stress, const RankTwoTensor &stress_new, RankFourTensor &tangent_operator)
Calculate the tangent_operator.
SubsteppingType _use_substepping
Whether user has requested the use of substepping technique to improve convergence [make const later]...
virtual void updateStateSubstep(GenericRankTwoTensor< is_ad > &, GenericRankTwoTensor< is_ad > &, const GenericRankTwoTensor< is_ad > &, GenericRankTwoTensor< is_ad > &, const RankTwoTensor &, const GenericRankFourTensor< is_ad > &, const RankTwoTensor &, bool compute_full_tangent_operator=false, RankFourTensor &tangent_operator=StressUpdateBaseTempl< is_ad >::_identityTensor) override
Similar to the updateState function, this method updates the strain and stress for one substep.
RadialReturnStressUpdateTempl(const InputParameters ¶meters)
void propagateQpStatefulPropertiesRadialReturn()
Propagate the properties pertaining to this intermediate class.
virtual Real computeReferenceResidual(const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar_effective_inelastic_strain) override
Compute a reference quantity to be used for checking relative convergence.
virtual void computeStressInitialize(const GenericReal< is_ad > &effective_trial_stress, const GenericRankFourTensor< is_ad > &elasticity_tensor)
Perform any necessary initialization before return mapping iterations.
static InputParameters validParams()
virtual void initQpStatefulProperties() override
virtual GenericReal< is_ad > maximumPermissibleValue(const GenericReal< is_ad > &effective_trial_stress) const override
Compute the maximum permissible value of the scalar.
virtual int calculateNumberSubsteps(const GenericRankTwoTensor< is_ad > &strain_increment) override
If substepping is enabled, calculate the number of substeps as a function of the elastic strain incre...
virtual Real computeTimeStepLimit() override
Compute the limiting value of the time step for this material.
const bool _adaptive_substepping
Use adaptive substepping, cutting substep sizes until convergence is achieved.
void outputIterationSummary(std::stringstream *iter_output, const unsigned int total_it) override
Output summary information for the convergence history of the model.
virtual void updateState(GenericRankTwoTensor< is_ad > &strain_increment, GenericRankTwoTensor< is_ad > &inelastic_strain_increment, const GenericRankTwoTensor< is_ad > &rotation_increment, GenericRankTwoTensor< is_ad > &stress_new, const RankTwoTensor &stress_old, const GenericRankFourTensor< is_ad > &elasticity_tensor, const RankTwoTensor &elastic_strain_old, bool compute_full_tangent_operator=false, RankFourTensor &tangent_operator=StressUpdateBaseTempl< is_ad >::_identityTensor) override
A radial return (J2) mapping method is performed with return mapping iterations.
T doubleContraction(const RankTwoTensorTempl< T > &a) const
RankFourTensorTempl< T > outerProduct(const RankTwoTensorTempl< T > &b) const
RankTwoTensorTempl< T > deviatoric() const
Base class that provides capability for Newton return mapping iterations on a single variable.
static InputParameters validParams()
virtual void outputIterationSummary(std::stringstream *iter_output, const unsigned int total_it)
Output summary information for the convergence history of the model.
StressUpdateBase is a material that is not called by MOOSE because of the compute=false flag set in t...
static InputParameters validParams()
void mooseSetToZero(T &v)
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)