https://mooseframework.inl.gov
ComputeCreepPlasticityStress.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 "ElasticityTensorTools.h"
13 
14 #include "MooseException.h"
15 #include "libmesh/int_range.h"
16 
18 
21 {
23  params.addClassDescription("Compute state (stress and internal parameters such as inelastic "
24  "strains and internal parameters) using an Newton process for one "
25  "creep and one plasticity model");
26  params.addRequiredParam<MaterialName>("creep_model",
27  "Creep model that derives from PowerLawCreepStressUpdate.");
28  params.addRequiredParam<MaterialName>(
29  "plasticity_model", "Plasticity model that derives from IsotropicPlasticityStressUpdate.");
30 
31  return params;
32 }
33 
36 {
37 }
38 
39 std::vector<MaterialName>
41 {
42  std::vector<MaterialName> names = {getParam<MaterialName>("creep_model"),
43  getParam<MaterialName>("plasticity_model")};
44  return names;
45 }
46 
47 void
49 {
51 
52  if (_models.size() != 2)
53  mooseError("Error in ComputeCreepPlasticityStress: two models are required.");
54 
55  _creep_model = dynamic_cast<PowerLawCreepStressUpdate *>(_models[0]);
56  if (!_creep_model)
57  mooseError("Model " + getParam<MaterialName>("creep_model") +
58  " is not a compatible creep model in ComputeCreepPlasticityStress.");
59 
61  if (!_plasticity_model)
62  mooseError("Model " + getParam<MaterialName>("plasticity_model") +
63  " is not a compatible plasticity model in ComputeCreepPlasticityStress.");
64 }
65 
66 void
68  RankTwoTensor & combined_inelastic_strain_increment)
69 {
71  {
72  _console << std::endl
73  << "iteration output for ComputeCreepPlasticityStress solve:"
74  << " time=" << _t << " int_pt=" << _qp << std::endl;
75  }
76 
77  for (const auto i_rmm : index_range(_models))
78  _inelastic_strain_increment[i_rmm].zero();
79 
80  elastic_strain_increment = _strain_increment[_qp];
81  computeStress(elastic_strain_increment, _stress[_qp]);
82 
83  const RankTwoTensor trial_stress = _stress[_qp];
84  const RankTwoTensor deviatoric_trial_stress = trial_stress.deviatoric();
85  const Real effective_trial_stress =
86  std::sqrt(1.5 * deviatoric_trial_stress.doubleContraction(deviatoric_trial_stress));
87 
88  //
89  // First, compute creep response assuming no plasticity
90  //
93  0, elastic_strain_increment, _inelastic_strain_increment[0], _consistent_tangent_operator[0]);
95 
96  //
97  // Now check the plasticity model.
98  // If no yielding, we are done.
99  //
102  1, elastic_strain_increment, _inelastic_strain_increment[1], _consistent_tangent_operator[1]);
104  const Real yield_condition = _plasticity_model->yieldCondition();
105 
106  if (yield_condition > 0.0) // yielding even with maximum creep strain
107  {
108  const Real max_effective_creep_strain_increment = _effective_creep_strain_increment;
109 
110  //
111  // Compute plastic response given no creep
112  //
113  elastic_strain_increment = _strain_increment[_qp];
114  _stress[_qp] = trial_stress;
116  elastic_strain_increment,
119  const Real max_effective_plastic_strain_increment =
121 
122  //
123  // Reset plasticity model
124  //
126 
127  //
128  // The residual for the creep law is (creep rate)*dt - (creep strain increment)
129  // We want the creep rate calculation to depend on both creep and plasticity.
130  // Since we send in the total scalar inelastic strain (creep and plasticity), we need to correct
131  // the second term by adding the plastic strain.
132  //
133  Real creep_residual = _creep_model->computeResidual(effective_trial_stress,
136  creep_residual += _effective_plastic_strain_increment;
137 
138  //
139  // We want the plasticity resdiual to be (effective_trial_stress - r - yield_stress)/3G - (total
140  // inelastic increment)
141  // The standard residual for plasticity is (effective_trial_stress - r - yield_stress)/3G -
142  // (plasticity strain increment)
143  // Since we send in the plastic inelastic strain (for calculation of r), we must subtract the
144  // creep strain to correct the final term in our desired residual
145  //
146  Real plasticity_residual = _plasticity_model->computeResidual(
147  effective_trial_stress, _effective_plastic_strain_increment);
148  plasticity_residual -= _effective_creep_strain_increment;
149 
150  unsigned int counter = 0;
151  Real residual = 0;
152  const Real threeG =
154  const Real reference_residual = effective_trial_stress / threeG;
155 
156  do
157  {
158  //
159  // Solve Ax=b where x is the vector of creep and plastic inelastic strains
160  //
161  // x1 => creep
162  // x2 => plasticity
163  //
164  //
165  // A11 (creep,creep)
166  //
167  Real A11 = _creep_model->computeDerivative(effective_trial_stress,
170  //
171  // A12 (creep,plasticity)
172  //
173  Real A12 = A11 + 1.0;
174  //
175  // A21 (plasticity,creep)
176  //
177  Real A21 = -1.0;
178  //
179  // A22 (plasticity,plasticity)
180  //
181  Real A22 = _plasticity_model->computeDerivative(effective_trial_stress,
183 
184  Real rhs1 = creep_residual;
185  Real rhs2 = plasticity_residual;
186 
187  //
188  // Solve
189  //
190  // A11*a + A21 = 0
191  // A11*a = -A21
192  // a = -A21/A11
193  const Real a = -A21 / A11;
194  A21 = 0;
195  A22 += a * A12;
196  rhs2 += a * rhs1;
197 
198  Real x2 = rhs2 / A22;
199  Real x1 = (rhs1 - A12 * x2) / A11;
200 
201  while (_effective_creep_strain_increment - x1 < 0)
202  x1 *= 0.5;
203  while (_effective_plastic_strain_increment - x2 < 0)
204  x2 *= 0.5;
205 
206  while (_effective_creep_strain_increment - x1 > max_effective_creep_strain_increment)
207  x1 *= 0.5;
208  while (_effective_plastic_strain_increment - x2 > max_effective_plastic_strain_increment)
209  x2 *= 0.5;
210 
211  // This check is to avoid a fpe in the creep law.
212  // Maybe it is better to check for this condition in the creep law
213  if (effective_trial_stress < threeG * (_effective_creep_strain_increment - x1 +
215  {
216  const Real sum =
218  const Real factor = 0.9 * effective_trial_stress / (threeG * sum);
219  const Real cNew = (_effective_creep_strain_increment - x1) * factor;
220  const Real pNew = (_effective_plastic_strain_increment - x2) * factor;
223  }
224 
227 
228  //
229  // The residual for the creep law is (creep rate)*dt - (creep strain increment)
230  //
231  creep_residual = _creep_model->computeResidual(effective_trial_stress,
234  creep_residual += _effective_plastic_strain_increment;
235  //
236  // The residual for plasticity is (effective_trial_stress - r - yield_stress)/3G - scalar
237  //
238  plasticity_residual = _plasticity_model->computeResidual(effective_trial_stress,
240  plasticity_residual -= _effective_creep_strain_increment;
241 
242  residual =
243  std::sqrt(creep_residual * creep_residual + plasticity_residual * plasticity_residual);
244 
246  {
247  _console << "stress iteration number = " << counter << "\n relative residual = "
248  << (0 == reference_residual ? 0 : residual / reference_residual)
249  << "\n stress convergence relative tolerance = " << _relative_tolerance
250  << "\n absolute residual = " << residual
251  << "\n creep residual = " << creep_residual
252  << "\n plasticity residual = " << plasticity_residual
253  << "\n creep iteration increment = " << x1
254  << "\n plasticity iteration increment = " << x2
255  << "\n creep scalar strain = " << _effective_creep_strain_increment
256  << "\n plasticity scalar strain = " << _effective_plastic_strain_increment
257  << "\n max creep scalar strain = " << max_effective_creep_strain_increment
258  << "\n max plasticity scalar strain = " << max_effective_plastic_strain_increment
259  << "\n stress convergence absolute tolerance = " << _absolute_tolerance
260  << std::endl;
261  }
262  ++counter;
263  } while (counter < _max_iterations && residual > _absolute_tolerance &&
264  (residual / reference_residual) > _relative_tolerance);
265 
266  if (counter == _max_iterations && residual > _absolute_tolerance &&
267  (residual / reference_residual) > _relative_tolerance)
268  {
269  std::stringstream msg;
270  msg << "\n relative residual = "
271  << (0 == reference_residual ? 0 : residual / reference_residual)
272  << "\n stress convergence relative tolerance = " << _relative_tolerance
273  << "\n absolute residual = " << residual << "\n creep residual = " << creep_residual
274  << "\n plasticity residual = " << plasticity_residual
275  << "\n creep scalar strain = " << _effective_creep_strain_increment
276  << "\n plasticity scalar strain = " << _effective_plastic_strain_increment
277  << "\n max creep scalar strain = " << max_effective_creep_strain_increment
278  << "\n max plasticity scalar strain = " << max_effective_plastic_strain_increment
279  << "\n stress convergence absolute tolerance = " << _absolute_tolerance << std::endl;
280 
281  throw MooseException("Max stress iteration hit during ComputeCreepPlasticityStress solve! " +
282  _name + msg.str());
283  }
284  }
285  computeInelasticStrainIncrements(effective_trial_stress, deviatoric_trial_stress);
286 
288 
289  combined_inelastic_strain_increment.zero();
290  for (const auto i_rmm : make_range(_num_models))
291  combined_inelastic_strain_increment += _inelastic_strain_increment[i_rmm];
292 
293  if (yield_condition > 0.0)
294  {
295  elastic_strain_increment = _strain_increment[_qp] - combined_inelastic_strain_increment;
296  _stress[_qp] = _elasticity_tensor[_qp] * (elastic_strain_increment + _elastic_strain_old[_qp]);
297 
299  }
300  else
301  {
302  // The tangent for creep was called in the initial creep solve.
303 
304  // Set the tangent for plasticity to zero
306  }
307 
310 
312  for (const auto i_rmm : make_range(_num_models))
313  _material_timestep_limit[_qp] += 1.0 / _models[i_rmm]->computeTimeStepLimit();
314 
316  _material_timestep_limit[_qp] = std::numeric_limits<Real>::max();
317  else
319 }
320 
321 void
323  RankTwoTensor & stress)
324 {
325  // form the stress, with the check for changed elasticity constants
327  stress = _elasticity_tensor[_qp] * (_elastic_strain_old[_qp] + elastic_strain_increment);
328  else
329  {
330  if (_damage_model)
331  stress = _undamaged_stress_old + _elasticity_tensor[_qp] * elastic_strain_increment;
332  else
333  stress = _stress_old[_qp] + _elasticity_tensor[_qp] * elastic_strain_increment;
334  }
335 }
336 
337 void
339 {
340  auto elastic_strain_inc = _strain_increment[_qp] - _inelastic_strain_increment[1];
341 
342  RankTwoTensor stress;
343  computeStress(elastic_strain_inc, stress);
344  RankTwoTensor deviatoric_stress = stress.deviatoric();
345  Real effective_stress = std::sqrt(1.5 * deviatoric_stress.doubleContraction(deviatoric_stress));
346 
348  effective_stress, _stress[_qp], _consistent_tangent_operator[0]);
349 
350  elastic_strain_inc = _strain_increment[_qp] - _inelastic_strain_increment[0];
351 
352  computeStress(elastic_strain_inc, stress);
353  deviatoric_stress = stress.deviatoric();
354  effective_stress = std::sqrt(1.5 * deviatoric_stress.doubleContraction(deviatoric_stress));
355 
357  effective_stress, _stress[_qp], _consistent_tangent_operator[1]);
358 }
359 
360 void
362  Real effective_trial_stress, const RankTwoTensor & deviatoric_trial_stress)
363 {
364  if (!MooseUtils::absoluteFuzzyEqual(effective_trial_stress, 0.0))
365  {
368  deviatoric_trial_stress *
369  (1.5 * _effective_creep_strain_increment / effective_trial_stress);
370  else
371  _inelastic_strain_increment[0].zero();
372 
375  deviatoric_trial_stress *
376  (1.5 * _effective_plastic_strain_increment / effective_trial_stress);
377  else
378  _inelastic_strain_increment[1].zero();
379  }
380  else
381  {
382  _inelastic_strain_increment[0].zero();
383  _inelastic_strain_increment[1].zero();
384  }
385 }
386 
387 void
389 {
397 }
virtual GenericReal< is_ad > computeResidual(const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar) override
Compute the residual for a predicted value of the scalar.
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[...] computed by the inelastic models, compute _Jacobian_mult[_qp].
T getIsotropicShearModulus(const RankFourTensorTempl< T > &elasticity_tensor)
Get the shear modulus for an isotropic elasticity tensor param elasticity_tensor the tensor (must be ...
ComputeCreepPlasticityStress(const InputParameters &parameters)
This class uses the stress update material in a radial return isotropic creep model.
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
virtual void computeStressFinalize(const GenericRankTwoTensor< is_ad > &plastic_strain_increment) override
Perform any necessary steps to finalize state after return mapping iterations.
This class uses the Discrete material in a radial return isotropic plasticity model.
ComputeCreepPlasticityStress computes the stress, the consistent tangent operator (or an approximatio...
virtual void computeStressInitialize(const GenericReal< is_ad > &effective_trial_stress, const GenericRankFourTensor< is_ad > &elasticity_tensor) override
Perform any necessary initialization before return mapping iterations.
const MaterialProperty< RankFourTensor > & _elasticity_tensor
Elasticity tensor material property.
const MaterialProperty< RankTwoTensor > & _strain_increment
virtual GenericReal< is_ad > computeDerivative(const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar) override
Compute the derivative of the residual as a function of the scalar variable.
std::vector< StressUpdateBase * > _models
The user supplied list of inelastic models to use in the simulation.
virtual std::vector< MaterialName > getInelasticModelNames() override
void updateEffectiveInelasticStrain(const GenericReal< is_ad > &increment)
void addRequiredParam(const std::string &name, const std::string &doc_string)
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< RankFourTensor > _consistent_tangent_operator
the consistent tangent operators computed by each plastic model
RankTwoTensorTempl< Real > deviatoric() const
PowerLawCreepStressUpdate * _creep_model
void computeInelasticStrainIncrements(Real effective_trial_stress, const RankTwoTensor &deviatoric_trial_stress)
const GenericReal< is_ad > & effectiveInelasticStrainIncrement() const
Current value of scalar inelastic strain.
virtual void computeStressFinalize(const GenericRankTwoTensor< is_ad > &plastic_strain_increment) override
Perform any necessary steps to finalize state after return mapping iterations.
DamageBaseTempl< false > * _damage_model
Pointer to the damage model.
Real doubleContraction(const RankTwoTensorTempl< Real > &a) const
ComputeMultipleInelasticStressBase computes the stress, the consistent tangent operator (or an approx...
IsotropicPlasticityStressUpdate * _plasticity_model
virtual void resetIncrementalMaterialProperties() override
Reset material properties.
void computeTangentOperator(Real effective_trial_stress, const RankTwoTensor &stress_new, RankFourTensor &tangent_operator)
Calculate the tangent_operator.
std::array< RankTwoTensor, 2 > _inelastic_strain_increment
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void updateQpState(RankTwoTensor &elastic_strain_increment, RankTwoTensor &combined_inelastic_strain_increment) override
Given the _strain_increment[_qp], iterate over all of the user-specified recompute materials in order...
const MaterialProperty< RankTwoTensor > & _stress_old
Old state of the stress tensor material property.
virtual GenericReal< is_ad > computeResidual(const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar) override
Compute the residual for a predicted value of the scalar.
void setQp(unsigned int qp)
Sets the value of the global variable _qp for inheriting classes.
IntRange< T > make_range(T beg, T end)
void computeStress(const RankTwoTensor &elastic_strain_increment, RankTwoTensor &stress)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
const bool _perform_finite_strain_rotations
after updateQpState, rotate the stress, elastic_strain, inelastic_strain and Jacobian_mult using _rot...
MaterialProperty< RankTwoTensor > & _stress
Stress material property.
const bool & currentlyComputingJacobian() const
virtual GenericReal< is_ad > computeDerivative(const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar) override
Compute the derivative of the residual as a function of the scalar variable.
void updateEffectiveInelasticStrainIncrement(const GenericReal< is_ad > &eisi)
const MaterialProperty< RankTwoTensor > & _elastic_strain_old
Strain tensors.
auto index_range(const T &sizable)
const unsigned int _max_iterations
Input parameters associated with the recompute iteration to return the stress state to the yield surf...
registerMooseObject("SolidMechanicsApp", ComputeCreepPlasticityStress)