www.mooseframework.org
ComputeMultipleInelasticStress.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 
18 
21 {
23  params.addRequiredParam<std::vector<MaterialName>>(
24  "inelastic_models",
25  "The material objects to use to calculate stress and inelastic strains. "
26  "Note: specify creep models first and plasticity models second.");
27  return params;
28 }
29 
32 {
33 }
34 
35 std::vector<MaterialName>
37 {
38  return getParam<std::vector<MaterialName>>("inelastic_models");
39 }
40 
41 void
43  RankTwoTensor & combined_inelastic_strain_increment)
44 {
46  {
47  _console << std::endl
48  << "iteration output for ComputeMultipleInelasticStress solve:"
49  << " time=" << _t << " int_pt=" << _qp << std::endl;
50  }
51  Real l2norm_delta_stress;
52  Real first_l2norm_delta_stress = 1.0;
53  unsigned int counter = 0;
54 
55  std::vector<RankTwoTensor> inelastic_strain_increment;
56  inelastic_strain_increment.resize(_num_models);
57 
58  for (const auto i_rmm : index_range(_models))
59  inelastic_strain_increment[i_rmm].zero();
60 
61  RankTwoTensor stress_max, stress_min;
62 
63  do
64  {
65  for (const auto i_rmm : index_range(_models))
66  {
67  _models[i_rmm]->setQp(_qp);
68 
69  // initially assume the strain is completely elastic
70  elastic_strain_increment = _strain_increment[_qp];
71  // and subtract off all inelastic strain increments calculated so far
72  // except the one that we're about to calculate
73  for (const auto j_rmm : make_range(_num_models))
74  if (i_rmm != j_rmm)
75  elastic_strain_increment -= inelastic_strain_increment[j_rmm];
76 
77  // form the trial stress, with the check for changed elasticity constants
79  _stress[_qp] =
80  _elasticity_tensor[_qp] * (_elastic_strain_old[_qp] + elastic_strain_increment);
81  else
82  {
83  if (_damage_model)
84  _stress[_qp] = _undamaged_stress_old + _elasticity_tensor[_qp] * elastic_strain_increment;
85  else
86  _stress[_qp] = _stress_old[_qp] + _elasticity_tensor[_qp] * elastic_strain_increment;
87  }
88 
89  // given a trial stress (_stress[_qp]) and a strain increment (elastic_strain_increment)
90  // let the i^th model produce an admissible stress (as _stress[_qp]), and decompose
91  // the strain increment into an elastic part (elastic_strain_increment) and an
92  // inelastic part (inelastic_strain_increment[i_rmm])
94  elastic_strain_increment,
95  inelastic_strain_increment[i_rmm],
97 
98  if (i_rmm == 0)
99  {
100  stress_max = _stress[_qp];
101  stress_min = _stress[_qp];
102  }
103  else
104  {
105  for (const auto i : make_range(Moose::dim))
106  for (const auto j : make_range(Moose::dim))
107  if (_stress[_qp](i, j) > stress_max(i, j))
108  stress_max(i, j) = _stress[_qp](i, j);
109  else if (stress_min(i, j) > _stress[_qp](i, j))
110  stress_min(i, j) = _stress[_qp](i, j);
111  }
112  }
113 
114  // now check convergence in the stress:
115  // once the change in stress is within tolerance after each recompute material
116  // consider the stress to be converged
117  l2norm_delta_stress = (stress_max - stress_min).L2norm();
118  if (counter == 0 && l2norm_delta_stress > 0.0)
119  first_l2norm_delta_stress = l2norm_delta_stress;
120 
122  {
123  _console << "stress iteration number = " << counter << "\n"
124  << " relative l2 norm delta stress = "
125  << (0 == first_l2norm_delta_stress ? 0
126  : l2norm_delta_stress / first_l2norm_delta_stress)
127  << "\n"
128  << " stress convergence relative tolerance = " << _relative_tolerance << "\n"
129  << " absolute l2 norm delta stress = " << l2norm_delta_stress << "\n"
130  << " stress convergence absolute tolerance = " << _absolute_tolerance << std::endl;
131  }
132  ++counter;
133  } while (counter < _max_iterations && l2norm_delta_stress > _absolute_tolerance &&
134  (l2norm_delta_stress / first_l2norm_delta_stress) > _relative_tolerance &&
135  _num_models != 1);
136 
137  if (counter == _max_iterations && l2norm_delta_stress > _absolute_tolerance &&
138  (l2norm_delta_stress / first_l2norm_delta_stress) > _relative_tolerance)
139  throw MooseException("Max stress iteration hit during ComputeMultipleInelasticStress solve!");
140 
141  combined_inelastic_strain_increment.zero();
142  for (const auto i_rmm : make_range(_num_models))
143  combined_inelastic_strain_increment +=
144  _inelastic_weights[i_rmm] * inelastic_strain_increment[i_rmm];
145 
148 
150  for (const auto i_rmm : make_range(_num_models))
151  _material_timestep_limit[_qp] += 1.0 / _models[i_rmm]->computeTimeStepLimit();
152 
154  _material_timestep_limit[_qp] = std::numeric_limits<Real>::max();
155  else
157 }
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].
ComputeMultipleInelasticStress computes the stress, the consistent tangent operator (or an approximat...
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...
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
registerMooseObject("SolidMechanicsApp", ComputeMultipleInelasticStress)
T L2norm(const RankTwoTensorTempl< T > &r2tensor)
const MaterialProperty< RankFourTensor > & _elasticity_tensor
Elasticity tensor material property.
const MaterialProperty< RankTwoTensor > & _strain_increment
static constexpr std::size_t dim
std::vector< StressUpdateBase * > _models
The user supplied list of inelastic models to use in the simulation.
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
virtual std::vector< MaterialName > getInelasticModelNames() override
DamageBaseTempl< false > * _damage_model
Pointer to the damage model.
ComputeMultipleInelasticStressBase computes the stress, the consistent tangent operator (or an approx...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< Real > _inelastic_weights
_inelastic_strain = sum_i (_inelastic_weights_i * inelastic_strain_from_model_i)
const MaterialProperty< RankTwoTensor > & _stress_old
Old state of the stress tensor material property.
IntRange< T > make_range(T beg, T end)
const bool _perform_finite_strain_rotations
after updateQpState, rotate the stress, elastic_strain, inelastic_strain and Jacobian_mult using _rot...
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
MaterialProperty< RankTwoTensor > & _stress
Stress material property.
const bool & currentlyComputingJacobian() const
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...
ComputeMultipleInelasticStress(const InputParameters &parameters)