12 #include "MooseException.h"
18 template <ComputeStage compute_stage>
23 params.addClassDescription(
"Compute state (stress and internal parameters such as plastic "
24 "strains and internal parameters) using an iterative process. "
25 "Combinations of creep models and plastic models may be used.");
26 params.addParam<
unsigned int>(
"max_iterations",
28 "Maximum number of the stress update "
29 "iterations over the stress change after all "
30 "update materials are called");
31 params.addParam<Real>(
"relative_tolerance",
33 "Relative convergence tolerance for the stress "
34 "update iterations over the stress change "
35 "after all update materials are called");
36 params.addParam<Real>(
"absolute_tolerance",
38 "Absolute convergence tolerance for the stress "
39 "update iterations over the stress change "
40 "after all update materials are called");
41 params.addParam<
bool>(
42 "internal_solve_full_iteration_history",
44 "Set to true to output stress update iteration information over the stress change");
45 params.addParam<
bool>(
"perform_finite_strain_rotations",
47 "Tensors are correctly rotated in "
48 "finite-strain simulations. For "
49 "optimal performance you can set "
50 "this to 'false' if you are only "
51 "ever using small strains");
52 params.addRequiredParam<std::vector<MaterialName>>(
54 "The material objects to use to calculate stress and inelastic strains. "
55 "Note: specify creep models first and plasticity models second.");
56 params.addParam<std::vector<Real>>(
"combined_inelastic_strain_weights",
57 "The combined_inelastic_strain Material Property is a "
58 "weighted sum of the model inelastic strains. This parameter "
59 "is a vector of weights, of the same length as "
60 "inelastic_models. Default = '1 1 ... 1'. This "
61 "parameter is set to 1 if the number of models = 1");
62 params.addParam<
bool>(
63 "cycle_models",
false,
"At time step N use only inelastic model N % num_models.");
67 template <ComputeStage compute_stage>
69 const InputParameters & parameters)
71 _max_iterations(parameters.get<unsigned int>(
"max_iterations")),
72 _relative_tolerance(parameters.get<Real>(
"relative_tolerance")),
73 _absolute_tolerance(parameters.get<Real>(
"absolute_tolerance")),
74 _internal_solve_full_iteration_history(getParam<bool>(
"internal_solve_full_iteration_history")),
75 _perform_finite_strain_rotations(getParam<bool>(
"perform_finite_strain_rotations")),
76 _inelastic_strain(declareADProperty<
RankTwoTensor>(_base_name +
"combined_inelastic_strain")),
77 _inelastic_strain_old(
78 getMaterialPropertyOld<
RankTwoTensor>(_base_name +
"combined_inelastic_strain")),
79 _num_models(getParam<std::vector<MaterialName>>(
"inelastic_models").size()),
80 _inelastic_weights(isParamValid(
"combined_inelastic_strain_weights")
81 ? getParam<std::vector<Real>>(
"combined_inelastic_strain_weights")
82 : std::vector<Real>(_num_models, true)),
83 _cycle_models(getParam<bool>(
"cycle_models")),
84 _matl_timestep_limit(declareProperty<Real>(
"matl_timestep_limit"))
87 paramError(
"combined_inelastic_strain_weights",
88 "must contain the same number of entries as inelastic_models ",
94 template <ComputeStage compute_stage>
99 _inelastic_strain[_qp].zero();
102 template <ComputeStage compute_stage>
106 _is_elasticity_tensor_guaranteed_isotropic =
109 std::vector<MaterialName> models = getParam<std::vector<MaterialName>>(
"inelastic_models");
111 for (
unsigned int i = 0; i < _num_models; ++i)
114 &this->
template getMaterialByName<compute_stage>(models[i]));
118 _models.push_back(rrr);
120 mooseError(
"Model " + models[i] +
121 " requires an isotropic elasticity tensor, but the one supplied is not "
122 "guaranteed isotropic");
125 mooseError(
"Model " + models[i] +
" is not compatible with ADComputeMultipleInelasticStress");
129 template <ComputeStage compute_stage>
133 computeQpStressIntermediateConfiguration();
134 if (_perform_finite_strain_rotations)
135 finiteStrainRotation();
138 template <ComputeStage compute_stage>
142 ADRankTwoTensor elastic_strain_increment;
143 ADRankTwoTensor combined_inelastic_strain_increment;
145 if (_num_models == 0)
147 _elastic_strain[_qp] = _elastic_strain_old[_qp] + _strain_increment[_qp];
151 if (_is_elasticity_tensor_guaranteed_isotropic || !_perform_finite_strain_rotations)
152 _stress[_qp] = _elasticity_tensor[_qp] * (_elastic_strain_old[_qp] + _strain_increment[_qp]);
154 _stress[_qp] = _stress_old[_qp] + _elasticity_tensor[_qp] * _strain_increment[_qp];
158 if (_num_models == 1 || _cycle_models)
159 updateQpStateSingleModel((_t_step - 1) % _num_models,
160 elastic_strain_increment,
161 combined_inelastic_strain_increment);
163 updateQpState(elastic_strain_increment, combined_inelastic_strain_increment);
165 _elastic_strain[_qp] = _elastic_strain_old[_qp] + elastic_strain_increment;
166 _inelastic_strain[_qp] = _inelastic_strain_old[_qp] + combined_inelastic_strain_increment;
170 template <ComputeStage compute_stage>
174 _elastic_strain[_qp] =
175 _rotation_increment[_qp] * _elastic_strain[_qp] * _rotation_increment[_qp].transpose();
176 _stress[_qp] = _rotation_increment[_qp] * _stress[_qp] * _rotation_increment[_qp].transpose();
177 _inelastic_strain[_qp] =
178 _rotation_increment[_qp] * _inelastic_strain[_qp] * _rotation_increment[_qp].transpose();
181 template <ComputeStage compute_stage>
184 ADRankTwoTensor & elastic_strain_increment,
185 ADRankTwoTensor & combined_inelastic_strain_increment)
187 if (_internal_solve_full_iteration_history ==
true)
189 _console << std::endl
190 <<
"iteration output for ADComputeMultipleInelasticStress solve:"
191 <<
" time=" << _t <<
" int_pt=" << _qp << std::endl;
193 Real l2norm_delta_stress;
194 Real first_l2norm_delta_stress = 1.0;
197 std::vector<ADRankTwoTensor> inelastic_strain_increment;
198 inelastic_strain_increment.resize(_num_models);
200 for (
unsigned i_rmm = 0; i_rmm < _models.size(); ++i_rmm)
201 inelastic_strain_increment[i_rmm].zero();
203 ADRankTwoTensor stress_max, stress_min;
207 for (
unsigned i_rmm = 0; i_rmm < _num_models; ++i_rmm)
209 _models[i_rmm]->setQp(_qp);
212 elastic_strain_increment = _strain_increment[_qp];
215 for (
unsigned j_rmm = 0; j_rmm < _num_models; ++j_rmm)
217 elastic_strain_increment -= inelastic_strain_increment[j_rmm];
220 if (_is_elasticity_tensor_guaranteed_isotropic || !_perform_finite_strain_rotations)
222 _elasticity_tensor[_qp] * (_elastic_strain_old[_qp] + elastic_strain_increment);
224 _stress[_qp] = _stress_old[_qp] + _elasticity_tensor[_qp] * elastic_strain_increment;
230 computeAdmissibleState(i_rmm, elastic_strain_increment, inelastic_strain_increment[i_rmm]);
234 stress_max = _stress[_qp];
235 stress_min = _stress[_qp];
239 for (
unsigned int i = 0; i < LIBMESH_DIM; ++i)
241 for (
unsigned int j = 0; j < LIBMESH_DIM; ++j)
243 if (_stress[_qp](i, j) > stress_max(i, j))
244 stress_max(i, j) = _stress[_qp](i, j);
245 else if (stress_min(i, j) > _stress[_qp](i, j))
246 stress_min(i, j) = _stress[_qp](i, j);
255 l2norm_delta_stress = MetaPhysicL::raw_value((stress_max - stress_min).
L2norm());
256 if (
counter == 0 && l2norm_delta_stress > 0.0)
257 first_l2norm_delta_stress = l2norm_delta_stress;
259 if (_internal_solve_full_iteration_history ==
true)
261 _console <<
"stress iteration number = " <<
counter <<
"\n"
262 <<
" relative l2 norm delta stress = "
263 << (0 == first_l2norm_delta_stress ? 0
264 : l2norm_delta_stress / first_l2norm_delta_stress)
266 <<
" stress convergence relative tolerance = " << _relative_tolerance <<
"\n"
267 <<
" absolute l2 norm delta stress = " << l2norm_delta_stress <<
"\n"
268 <<
" stress convergence absolute tolerance = " << _absolute_tolerance << std::endl;
271 }
while (counter < _max_iterations && l2norm_delta_stress > _absolute_tolerance &&
272 (l2norm_delta_stress / first_l2norm_delta_stress) > _relative_tolerance &&
275 if (
counter == _max_iterations && l2norm_delta_stress > _absolute_tolerance &&
276 (l2norm_delta_stress / first_l2norm_delta_stress) > _relative_tolerance)
278 "In ", _name,
": Max stress iteration hit during ADComputeMultipleInelasticStress solve!");
280 combined_inelastic_strain_increment.zero();
281 for (
unsigned i_rmm = 0; i_rmm < _num_models; ++i_rmm)
282 combined_inelastic_strain_increment +=
283 _inelastic_weights[i_rmm] * inelastic_strain_increment[i_rmm];
285 _matl_timestep_limit[_qp] = 0.0;
286 for (
unsigned i_rmm = 0; i_rmm < _num_models; ++i_rmm)
287 _matl_timestep_limit[_qp] += 1.0 / _models[i_rmm]->computeTimeStepLimit();
289 if (MooseUtils::absoluteFuzzyEqual(_matl_timestep_limit[_qp], 0.0))
290 _matl_timestep_limit[_qp] = std::numeric_limits<Real>::max();
292 _matl_timestep_limit[_qp] = 1.0 / _matl_timestep_limit[_qp];
295 template <ComputeStage compute_stage>
298 unsigned model_number,
299 ADRankTwoTensor & elastic_strain_increment,
300 ADRankTwoTensor & combined_inelastic_strain_increment)
302 for (
auto model : _models)
305 elastic_strain_increment = _strain_increment[_qp];
309 if (_is_elasticity_tensor_guaranteed_isotropic || !_perform_finite_strain_rotations)
310 _stress[_qp] = _elasticity_tensor[_qp] * (_elastic_strain_old[_qp] + elastic_strain_increment);
312 _stress[_qp] = _stress_old[_qp] + _elasticity_tensor[_qp] * elastic_strain_increment;
314 computeAdmissibleState(
315 model_number, elastic_strain_increment, combined_inelastic_strain_increment);
317 _matl_timestep_limit[_qp] = _models[0]->computeTimeStepLimit();
321 for (
unsigned i_rmm = 0; i_rmm < _num_models; ++i_rmm)
322 if (i_rmm != model_number)
323 _models[i_rmm]->propagateQpStatefulProperties();
326 template <ComputeStage compute_stage>
329 unsigned model_number,
330 ADRankTwoTensor & elastic_strain_increment,
331 ADRankTwoTensor & inelastic_strain_increment)
333 _models[model_number]->updateState(elastic_strain_increment,
334 inelastic_strain_increment,
335 _rotation_increment[_qp],
338 _elasticity_tensor[_qp],
339 _elastic_strain_old[_qp]);