https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ComputeMultipleInelasticStressBase.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11
12#include "StressUpdateBase.h"
13#include "MooseException.h"
14#include "DamageBase.h"
15#include "libmesh/int_range.h"
16
19{
21 params.addClassDescription("Compute state (stress and internal parameters such as plastic "
22 "strains and internal parameters) using an iterative process. "
23 "Combinations of creep models and plastic models may be used.");
24 params.addParam<unsigned int>("max_iterations",
25 30,
26 "Maximum number of the stress update "
27 "iterations over the stress change after all "
28 "update materials are called");
29 params.addParam<Real>("relative_tolerance",
30 1e-5,
31 "Relative convergence tolerance for the stress "
32 "update iterations over the stress change "
33 "after all update materials are called");
34 params.addParam<Real>("absolute_tolerance",
35 1e-5,
36 "Absolute convergence tolerance for the stress "
37 "update iterations over the stress change "
38 "after all update materials are called");
39 params.addParam<bool>(
40 "internal_solve_full_iteration_history",
41 false,
42 "Set to true to output stress update iteration information over the stress change");
43 params.addParam<bool>("perform_finite_strain_rotations",
44 true,
45 "Tensors are correctly rotated in "
46 "finite-strain simulations. For "
47 "optimal performance you can set "
48 "this to 'false' if you are only "
49 "ever using small strains");
50 MooseEnum tangent_operator("elastic nonlinear", "nonlinear");
51 params.addParam<MooseEnum>(
52 "tangent_operator",
53 tangent_operator,
54 "Type of tangent operator to return. 'elastic': return the "
55 "elasticity tensor. 'nonlinear': return the full, general consistent tangent "
56 "operator.");
57 params.addParam<std::vector<Real>>("combined_inelastic_strain_weights",
58 "The combined_inelastic_strain Material Property is a "
59 "weighted sum of the model inelastic strains. This parameter "
60 "is a vector of weights, of the same length as "
61 "inelastic_models. Default = '1 1 ... 1'. This "
62 "parameter is set to 1 if the number of models = 1");
63 params.addParam<bool>(
64 "cycle_models", false, "At timestep N use only inelastic model N % num_models.");
65 params.addParam<MaterialName>("damage_model", "Name of the damage model");
66
67 return params;
68}
69
71 const InputParameters & parameters)
73 _max_iterations(parameters.get<unsigned int>("max_iterations")),
74 _relative_tolerance(parameters.get<Real>("relative_tolerance")),
75 _absolute_tolerance(parameters.get<Real>("absolute_tolerance")),
76 _internal_solve_full_iteration_history(getParam<bool>("internal_solve_full_iteration_history")),
77 _perform_finite_strain_rotations(getParam<bool>("perform_finite_strain_rotations")),
78 _elastic_strain_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "elastic_strain")),
79 _strain_increment(getMaterialProperty<RankTwoTensor>(_base_name + "strain_increment")),
80 _inelastic_strain(declareProperty<RankTwoTensor>(_base_name + "combined_inelastic_strain")),
81 _inelastic_strain_old(
82 getMaterialPropertyOld<RankTwoTensor>(_base_name + "combined_inelastic_strain")),
83 _tangent_operator_type(getParam<MooseEnum>("tangent_operator").getEnum<TangentOperatorEnum>()),
84 _tangent_calculation_method(TangentCalculationMethod::ELASTIC),
85 _cycle_models(getParam<bool>("cycle_models")),
86 _material_timestep_limit(declareProperty<Real>(_base_name + "material_timestep_limit")),
87 _identity_symmetric_four(RankFourTensor::initIdentitySymmetricFour),
88 _all_models_isotropic(true)
89{
90}
91
92void
98
99void
101{
102 _damage_model = isParamValid("damage_model")
103 ? dynamic_cast<DamageBaseTempl<false> *>(&getMaterial("damage_model"))
104 : nullptr;
105
108
109 std::vector<MaterialName> models = getInelasticModelNames();
110
111 _num_models = models.size();
114
115 _inelastic_weights = isParamValid("combined_inelastic_strain_weights")
116 ? getParam<std::vector<Real>>("combined_inelastic_strain_weights")
117 : std::vector<Real>(_num_models, 1.0);
118
119 if (_inelastic_weights.size() != _num_models)
120 mooseError("ComputeMultipleInelasticStressBase: combined_inelastic_strain_weights must contain "
121 "the same "
122 "number of entries as inelastic_models ",
123 _inelastic_weights.size(),
124 " ",
126
127 for (const auto i : make_range(_num_models))
128 {
129 StressUpdateBase * rrr = dynamic_cast<StressUpdateBase *>(&getMaterialByName(models[i]));
130
131 if (rrr)
132 {
133 _models.push_back(rrr);
136 mooseError("Model " + models[i] +
137 " requires an isotropic elasticity tensor, but the one supplied is not "
138 "guaranteed isotropic");
139 }
140 else
141 mooseError("Model " + models[i] +
142 " is not compatible with ComputeMultipleInelasticStressBase");
143 }
144
145 // Check if tangent calculation methods are consistent. If all models have
146 // TangentOperatorEnum::ELASTIC or tangent_operator is set by the user as elasic, then the tangent
147 // is never calculated: J_tot = C. If PARTIAL and NONE models are present, utilize PARTIAL
148 // formulation: J_tot = (I + J_1 + ... J_N)^-1 C. If FULL and NONE models are present, utilize
149 // FULL formulation: J_tot = J_1 * C^-1 * J_2 * C^-1 * ... J_N * C. If PARTIAL and FULL models are
150 // present, error out.
151
153 {
154 bool full_present = false;
155 bool partial_present = false;
156 for (const auto i : make_range(_num_models))
157 {
158 if (_models[i]->getTangentCalculationMethod() == TangentCalculationMethod::FULL)
159 {
160 full_present = true;
163 }
164 else if (_models[i]->getTangentCalculationMethod() == TangentCalculationMethod::PARTIAL)
165 {
166 partial_present = true;
169 }
170 }
171 if (full_present && partial_present)
172 mooseError("In ",
173 _name,
174 ": Models that calculate the full tangent operator and the partial tangent "
175 "operator are being combined. Either set tangent_operator to elastic, implement "
176 "the corrent tangent formulations, or use different models.");
177 }
178
179 if (isParamValid("damage_model") && !_damage_model)
180 paramError("damage_model",
181 "Damage Model " + _damage_model->name() +
182 " is not compatible with ComputeMultipleInelasticStressBase");
183
184 // This check prevents the hierarchy from silently skipping substepping without informing the user
185 for (const auto model_number : index_range(_models))
186 {
187 const bool use_substep = _models[model_number]->substeppingCapabilityRequested();
188 if (use_substep && !_models[model_number]->substeppingCapabilityEnabled())
189 {
190 std::stringstream error_message;
191 error_message << "Usage of substepping has been requested, but the inelastic model "
192 << _models[model_number]->name() << " does not implement substepping yet.";
193 mooseError(error_message.str());
194 }
195 }
196}
197
198void
225
226void
228{
229 RankTwoTensor elastic_strain_increment;
230 RankTwoTensor combined_inelastic_strain_increment;
231
232 if (_num_models == 0)
233 {
235
236 // If the elasticity tensor values have changed and the tensor is isotropic,
237 // use the old strain to calculate the old stress
240 else
241 {
242 if (_damage_model)
244 else
246 }
247 if (_fe_problem.currentlyComputingJacobian())
249
250 _material_timestep_limit[_qp] = std::numeric_limits<Real>::max();
251 }
252 else
253 {
254 if (_num_models == 1 || _cycle_models)
256 elastic_strain_increment,
257 combined_inelastic_strain_increment);
258 else
259 updateQpState(elastic_strain_increment, combined_inelastic_strain_increment);
260
261 _elastic_strain[_qp] = _elastic_strain_old[_qp] + elastic_strain_increment;
262 _inelastic_strain[_qp] = _inelastic_strain_old[_qp] + combined_inelastic_strain_increment;
263 }
264}
265
266void
268{
269 _elastic_strain[_qp] =
271 _stress[_qp] = _rotation_increment[_qp] * _stress[_qp] * _rotation_increment[_qp].transpose();
272 _inelastic_strain[_qp] =
273 _rotation_increment[_qp] * _inelastic_strain[_qp] * _rotation_increment[_qp].transpose();
274
275 if (force_elasticity_rotation ||
279 _Jacobian_mult[_qp].rotate(_rotation_increment[_qp]);
280}
281
282void
284{
288 {
290 for (const auto i_rmm : make_range(_num_models))
292 mooseAssert(A.isSymmetric(), "Tangent operator isn't symmetric");
293 _Jacobian_mult[_qp] = A.invSymm() * _elasticity_tensor[_qp];
294 }
295 else
296 {
297 const RankFourTensor E_inv = _elasticity_tensor[_qp].invSymm();
299 for (const auto i_rmm : make_range(1u, _num_models))
301 }
302}
303
304void
306 unsigned model_number,
307 RankTwoTensor & elastic_strain_increment,
308 RankTwoTensor & combined_inelastic_strain_increment)
309{
310 for (auto model : _models)
311 model->setQp(_qp);
312
313 elastic_strain_increment = _strain_increment[_qp];
314
315 // If the elasticity tensor values have changed and the tensor is isotropic,
316 // use the old strain to calculate the old stress
318 _stress[_qp] = _elasticity_tensor[_qp] * (_elastic_strain_old[_qp] + elastic_strain_increment);
319 else
320 {
321 if (_damage_model)
322 _stress[_qp] = _undamaged_stress_old + _elasticity_tensor[_qp] * elastic_strain_increment;
323 else
324 _stress[_qp] = _stress_old[_qp] + _elasticity_tensor[_qp] * elastic_strain_increment;
325 }
326
327 computeAdmissibleState(model_number,
328 elastic_strain_increment,
329 combined_inelastic_strain_increment,
331
332 if (_fe_problem.currentlyComputingJacobian())
333 {
337 {
339 mooseAssert(A.isSymmetric(), "Tangent operator isn't symmetric");
340 _Jacobian_mult[_qp] = A.invSymm() * _elasticity_tensor[_qp];
341 }
342 else
344 }
345
346 _material_timestep_limit[_qp] = _models[0]->computeTimeStepLimit();
347
348 /* propagate internal variables, etc, to this timestep for those inelastic models where
349 * "updateState" is not called */
350 for (const auto i_rmm : make_range(_num_models))
351 if (i_rmm != model_number)
352 _models[i_rmm]->propagateQpStatefulProperties();
353}
354
355void
357 unsigned model_number,
358 RankTwoTensor & elastic_strain_increment,
359 RankTwoTensor & inelastic_strain_increment,
360 RankFourTensor & consistent_tangent_operator)
361{
362 // Reset properties to the beginning of the time step (necessary if substepping is employed).
363 _models[model_number]->resetIncrementalMaterialProperties();
364
365 const bool jac = _fe_problem.currentlyComputingJacobian();
366 if (_damage_model)
367 _models[model_number]->updateState(elastic_strain_increment,
368 inelastic_strain_increment,
370 _stress[_qp],
374 (jac && _tangent_computation_flag[model_number]),
375 consistent_tangent_operator);
376 else if (_models[model_number]->substeppingCapabilityEnabled() &&
378 _models[model_number]->updateStateSubstep(elastic_strain_increment,
379 inelastic_strain_increment,
381 _stress[_qp],
382 _stress_old[_qp],
385 (jac && _tangent_computation_flag[model_number]),
386 consistent_tangent_operator);
387 else
388 _models[model_number]->updateState(elastic_strain_increment,
389 inelastic_strain_increment,
391 _stress[_qp],
392 _stress_old[_qp],
395 (jac && _tangent_computation_flag[model_number]),
396 consistent_tangent_operator);
397
398 if (jac && !_tangent_computation_flag[model_number])
399 {
401 consistent_tangent_operator.zero();
402 else
403 consistent_tangent_operator = _elasticity_tensor[_qp];
404 }
405}
const PertinentGeochemicalSystem model(database, {"H2O", "H+", "HCO3-", "O2(aq)", "Ca++", ">(s)FeOH", "radius_neg1", "radius_neg1.5"}, {"Calcite"}, {}, {"Calcite_asdf"}, {"CH4(aq)"}, {">(s)FeOCa+"}, "O2(aq)", "e-")
void mooseError(Args &&... args)
TangentCalculationMethod
TangentCalculationMethod is an enum that determines the calculation method for the tangent operator.
void ErrorVector unsigned int
ComputeFiniteStrainElasticStress computes the stress following elasticity theory for finite strains.
const std::string _elasticity_tensor_name
Name of the elasticity tensor material property.
const MaterialProperty< RankTwoTensor > & _rotation_increment
Rotation increment material property.
const MaterialProperty< RankFourTensor > & _elasticity_tensor
Elasticity tensor material property.
const MaterialProperty< RankTwoTensor > & _stress_old
Old state of the stress tensor material property.
MaterialProperty< RankFourTensor > & _Jacobian_mult
derivative of stress w.r.t. strain (_dstress_dstrain)
virtual void initQpStatefulProperties() override
MaterialProperty< RankTwoTensor > & _elastic_strain
Elastic strain material property.
MaterialProperty< RankTwoTensor > & _stress
Stress material property.
TangentCalculationMethod _tangent_calculation_method
Calculation method for the tangent modulus.
virtual void finiteStrainRotation(const bool force_elasticity_rotation=false)
Rotate _elastic_strain, _stress, _inelastic_strain, and _Jacobian_mult to the new configuration.
const MaterialProperty< RankTwoTensor > & _strain_increment
const bool _perform_finite_strain_rotations
after updateQpState, rotate the stress, elastic_strain, inelastic_strain and Jacobian_mult using _rot...
std::vector< Real > _inelastic_weights
_inelastic_strain = sum_i (_inelastic_weights_i * inelastic_strain_from_model_i)
std::vector< StressUpdateBase * > _models
The user supplied list of inelastic models to use in the simulation.
virtual std::vector< MaterialName > getInelasticModelNames()=0
const bool _cycle_models
whether to cycle through the models, using only one model per timestep
virtual void updateQpStateSingleModel(unsigned model_number, RankTwoTensor &elastic_strain_increment, RankTwoTensor &combined_inelastic_strain_increment)
An optimised version of updateQpState that gets used when the number of plastic models is unity,...
virtual void computeAdmissibleState(unsigned model_number, RankTwoTensor &elastic_strain_increment, RankTwoTensor &inelastic_strain_increment, RankFourTensor &consistent_tangent_operator)
Given a trial stress (_stress[_qp]) and a strain increment (elastic_strain_increment) let the model_n...
std::vector< bool > _tangent_computation_flag
Flags to compute tangent during updateState call.
DamageBaseTempl< false > * _damage_model
Pointer to the damage model.
MaterialProperty< RankTwoTensor > & _inelastic_strain
The sum of the inelastic strains that come from the plastic models.
ComputeMultipleInelasticStressBase(const InputParameters &parameters)
const RankFourTensor _identity_symmetric_four
Rank four symmetric identity tensor.
virtual void computeQpStressIntermediateConfiguration()
Compute the stress for the current QP, but do not rotate tensors from the intermediate configuration ...
virtual void updateQpState(RankTwoTensor &elastic_strain_increment, RankTwoTensor &combined_inelastic_strain_increment)=0
Given the _strain_increment[_qp], iterate over all of the user-specified recompute materials in order...
const MaterialProperty< RankTwoTensor > & _inelastic_strain_old
old value of inelastic strain
TangentOperatorEnum
what sort of Tangent operator to calculate
virtual void computeQpStress() override
Compute the stress and store it in the _stress material property for the current quadrature point.
enum ComputeMultipleInelasticStressBase::TangentOperatorEnum _tangent_operator_type
const MaterialProperty< RankTwoTensor > & _elastic_strain_old
Strain tensors.
bool _all_models_isotropic
are all inelastic models inherently isotropic? (not the case for e.g. weak plane plasticity models)
std::vector< RankFourTensor > _consistent_tangent_operator
the consistent tangent operators computed by each plastic model
bool _is_elasticity_tensor_guaranteed_isotropic
is the elasticity tensor guaranteed to be isotropic?
virtual void computeQpJacobianMult()
Using _elasticity_tensor[_qp] and the consistent tangent operators, _consistent_tangent_operator[....
DamageBase is a base class for damage models, which modify the stress tensor computed by another mode...
Definition DamageBase.h:26
virtual Real computeTimeStepLimit()
Compute the limiting value of the time step for this material.
Definition DamageBase.C:54
virtual void updateJacobianMultForDamage(RankFourTensor &jacobian_mult)=0
Update the material constitutive matrix.
void setQp(unsigned int qp)
Sets the value of the member variable _qp for use in inheriting classes.
Definition DamageBase.C:41
virtual void finiteStrainRotation(const GenericRankTwoTensor< is_ad > &rotation_increment)
Perform any necessary rotation of internal variables for finite strain.
Definition DamageBase.C:61
virtual void updateStressForDamage(GenericRankTwoTensor< is_ad > &stress_new)=0
Update the current stress tensor for effects of damage.
virtual void updateDamage()
Update the internal variable(s) that evolve the damage.
Definition DamageBase.C:48
virtual void computeUndamagedOldStress(RankTwoTensor &stress_old)=0
bool hasGuaranteedMaterialProperty(const MaterialPropertyName &prop, Guarantee guarantee)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
const std::string & name() const
RankFourTensorTempl< T > invSymm() const
RankTwoTensorTempl< T > transpose() const
StressUpdateBase is a material that is not called by MOOSE because of the compute=false flag set in t...
virtual bool requiresIsotropicTensor()=0
Does the model require the elasticity tensor to be isotropic?
virtual bool isIsotropic()
Is the implmented model isotropic? The safe default is 'false'.