https://mooseframework.inl.gov
Loading...
Searching...
No Matches
HillCreepStressUpdate.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
12#include "Function.h"
13
16
17template <bool is_ad>
20{
23 "This class uses the stress update material in a generalized radial return anisotropic power "
24 "law creep "
25 "model. This class can be used in conjunction with other creep and plasticity materials for "
26 "more complex simulations.");
27
28 // Linear strain hardening parameters
29 params.addCoupledVar("temperature", "Coupled temperature");
30 params.addRequiredParam<Real>("coefficient", "Leading coefficient in power-law equation");
31 params.addRequiredParam<Real>("n_exponent", "Exponent on effective stress in power-law equation");
32 params.addParam<Real>("m_exponent", 0.0, "Exponent on time in power-law equation");
33 params.addRequiredParam<Real>("activation_energy", "Activation energy");
34 params.addParam<Real>("gas_constant", 8.3143, "Universal gas constant");
35 params.addParam<Real>("start_time", 0.0, "Start time (if not zero)");
36 params.addParam<bool>("anisotropic_elasticity", false, "Enable using anisotropic elasticity");
37 params.addParam<FunctionName>(
38 "creep_prefactor", "Optional function to use as a scalar prefactor on the creep strain.");
39 return params;
40}
41
42template <bool is_ad>
45 _has_temp(this->isParamValid("temperature")),
46 _temperature(this->_has_temp ? this->coupledValue("temperature") : this->_zero),
47 _coefficient(this->template getParam<Real>("coefficient")),
48 _n_exponent(this->template getParam<Real>("n_exponent")),
49 _m_exponent(this->template getParam<Real>("m_exponent")),
50 _activation_energy(this->template getParam<Real>("activation_energy")),
51 _gas_constant(this->template getParam<Real>("gas_constant")),
52 _start_time(this->template getParam<Real>("start_time")),
53 _exponential(1.0),
54 _exp_time(1.0),
55 _hill_constants(this->template getMaterialPropertyByName<std::vector<Real>>(this->_base_name +
56 "hill_constants")),
57 _hill_tensor(this->_use_transformation
58 ? &this->template getMaterialPropertyByName<DenseMatrix<Real>>(
59 this->_base_name + "hill_tensor")
60 : nullptr),
61 _C(6, 6),
62 _elasticity_tensor_name(this->_base_name + "elasticity_tensor"),
63 _elasticity_tensor(
64 this->template getGenericMaterialProperty<RankFourTensor, is_ad>(_elasticity_tensor_name)),
65 _anisotropic_elasticity(this->template getParam<bool>("anisotropic_elasticity")),
66 _prefactor_function(
67 this->isParamValid("creep_prefactor") ? &this->getFunction("creep_prefactor") : nullptr)
68{
69 if (_start_time < this->_app.getStartTime() && (std::trunc(_m_exponent) != _m_exponent))
70 this->paramError("start_time",
71 "Start time must be equal to or greater than the Executioner start_time if a "
72 "non-integer m_exponent is used");
73}
74
75template <bool is_ad>
76void
78 const GenericDenseVector<is_ad> & /*stress_dev*/,
79 const GenericDenseVector<is_ad> & /*stress*/,
80 const GenericRankFourTensor<is_ad> & elasticity_tensor)
81{
82 if (_has_temp)
83 _exponential = std::exp(-_activation_energy / (_gas_constant * _temperature[_qp]));
84
86
87 _exp_time = std::pow(_t - _start_time, _m_exponent);
88}
89
90template <bool is_ad>
96
97template <bool is_ad>
100 const GenericDenseVector<is_ad> & /*effective_trial_stress*/,
101 const GenericDenseVector<is_ad> & stress_new,
102 const GenericReal<is_ad> & delta_gamma)
103{
104 using std::pow;
105
106 GenericReal<is_ad> qsigma_changed;
107 GenericRankTwoTensor<is_ad> stress_changed;
108
109 // Get the qsigma_changed and stress_changed (not used)
110 // delta_gamma (scalar plastic strain) will change the stress (and qsigma as well)
111 computeQsigmaChanged(qsigma_changed, stress_new, delta_gamma, stress_changed);
112
113 GenericReal<is_ad> creep_rate =
114 _coefficient * pow(qsigma_changed, _n_exponent) * _exponential * _exp_time;
115
116 if (_prefactor_function)
117 creep_rate *= _prefactor_function->value(_t, _q_point[_qp]);
118
119 this->_inelastic_strain_rate[_qp] = MetaPhysicL::raw_value(creep_rate);
120 // Return iteration difference between creep strain and inelastic strain multiplier
121 return creep_rate * _dt - delta_gamma;
122}
123
124template <bool is_ad>
125Real
127 const GenericDenseVector<is_ad> & /*effective_trial_stress*/,
128 const GenericDenseVector<is_ad> & /*stress_new*/,
129 const GenericReal<is_ad> & /*residual*/,
130 const GenericReal<is_ad> & /*scalar_effective_inelastic_strain*/)
131{
132 return 1.0;
133}
134
135template <bool is_ad>
138 const GenericDenseVector<is_ad> & /*effective_trial_stress*/,
139 const GenericDenseVector<is_ad> & stress_new,
140 const GenericReal<is_ad> & delta_gamma)
141{
142 using std::pow;
143
144 GenericReal<is_ad> qsigma_changed;
145 GenericRankTwoTensor<is_ad> stress_changed;
146
147 // Get the qsigma_changed and stress_changed
148 // delta_gamma (scalar plastic strain) will change the stress (and qsigma as well)
149 computeQsigmaChanged(qsigma_changed, stress_new, delta_gamma, stress_changed);
150
151 ElasticityTensorTools::toMooseVoigtNotation<is_ad>(_C, _elasticity_tensor[_qp]);
152 const unsigned int dimension = _C.n();
153 GenericDenseMatrix<is_ad> d_stress_d_inelasticStrainIncrement(dimension, dimension);
154
155 for (unsigned int index_i = 0; index_i < dimension; index_i++)
156 for (unsigned int index_j = 0; index_j < dimension; index_j++)
157 {
158 if (index_j < 3)
159 d_stress_d_inelasticStrainIncrement(index_i, index_j) =
160 -1.0 * MetaPhysicL::raw_value(_C(index_i, index_j));
161 else
162 d_stress_d_inelasticStrainIncrement(index_i, index_j) =
163 -2.0 * MetaPhysicL::raw_value(_C(index_i, index_j));
164 }
165
166 // Hill constants, some constraints apply
167 const Real & F = _hill_constants[_qp][0];
168 const Real & G = _hill_constants[_qp][1];
169 const Real & H = _hill_constants[_qp][2];
170 const Real & L = _hill_constants[_qp][3];
171 const Real & M = _hill_constants[_qp][4];
172 const Real & N = _hill_constants[_qp][5];
173
174 GenericDenseVector<is_ad> d_qsigma_d_inelasticStrainIncrement(6);
175 for (unsigned int index_k = 0; index_k < 6; index_k++)
176 {
177 d_qsigma_d_inelasticStrainIncrement(index_k) =
178 F * (stress_changed(1, 1) - stress_changed(2, 2)) *
179 (d_stress_d_inelasticStrainIncrement(1, index_k) -
180 d_stress_d_inelasticStrainIncrement(2, index_k)) +
181 G * (stress_changed(2, 2) - stress_changed(0, 0)) *
182 (d_stress_d_inelasticStrainIncrement(2, index_k) -
183 d_stress_d_inelasticStrainIncrement(0, index_k)) +
184 H * (stress_changed(0, 0) - stress_changed(1, 1)) *
185 (d_stress_d_inelasticStrainIncrement(0, index_k) -
186 d_stress_d_inelasticStrainIncrement(1, index_k)) +
187 2.0 * L * stress_changed(1, 2) * d_stress_d_inelasticStrainIncrement(4, index_k) +
188 2.0 * M * stress_changed(2, 0) * d_stress_d_inelasticStrainIncrement(5, index_k) +
189 2.0 * N * stress_changed(0, 1) * d_stress_d_inelasticStrainIncrement(3, index_k);
190 d_qsigma_d_inelasticStrainIncrement(index_k) /= qsigma_changed;
191 }
192
193 GenericDenseVector<is_ad> d_qsigma_d_sigma(6);
194
195 d_qsigma_d_sigma(0) = (H * (stress_changed(0, 0) - stress_changed(1, 1)) -
196 G * (stress_changed(2, 2) - stress_changed(0, 0))) /
197 qsigma_changed;
198 d_qsigma_d_sigma(1) = (F * (stress_changed(1, 1) - stress_changed(2, 2)) -
199 H * (stress_changed(0, 0) - stress_changed(1, 1))) /
200 qsigma_changed;
201 d_qsigma_d_sigma(2) = (G * (stress_changed(2, 2) - stress_changed(0, 0)) -
202 F * (stress_changed(1, 1) - stress_changed(2, 2))) /
203 qsigma_changed;
204 d_qsigma_d_sigma(3) = 2.0 * N * stress_changed(0, 1) / qsigma_changed;
205 d_qsigma_d_sigma(4) = 2.0 * L * stress_changed(1, 2) / qsigma_changed;
206 d_qsigma_d_sigma(5) = 2.0 * M * stress_changed(0, 2) / qsigma_changed;
207
208 GenericReal<is_ad> d_qsigma_d_deltaGamma =
209 d_qsigma_d_inelasticStrainIncrement.dot(d_qsigma_d_sigma);
210
211 GenericReal<is_ad> creep_rate_derivative = _coefficient * d_qsigma_d_deltaGamma * _n_exponent *
212 pow(qsigma_changed, _n_exponent - 1.0) * _exponential *
213 _exp_time;
214
215 if (_prefactor_function)
216 creep_rate_derivative *= _prefactor_function->value(_t, _q_point[_qp]);
217
218 return (creep_rate_derivative * _dt - 1.0);
219}
220
221template <bool is_ad>
222void
224 GenericRankTwoTensor<is_ad> & inelasticStrainIncrement,
225 const GenericRankTwoTensor<is_ad> & stress,
226 const GenericDenseVector<is_ad> & stress_dev,
227 const GenericReal<is_ad> & delta_gamma)
228{
229 using std::sqrt;
230
231 GenericReal<is_ad> qsigma_square;
232 if (!this->_use_transformation)
233 {
234 // Hill constants, some constraints apply
235 const Real & F = _hill_constants[_qp][0];
236 const Real & G = _hill_constants[_qp][1];
237 const Real & H = _hill_constants[_qp][2];
238 const Real & L = _hill_constants[_qp][3];
239 const Real & M = _hill_constants[_qp][4];
240 const Real & N = _hill_constants[_qp][5];
241
242 // Equivalent deviatoric stress function.
243 qsigma_square = F * (stress(1, 1) - stress(2, 2)) * (stress(1, 1) - stress(2, 2));
244 qsigma_square += G * (stress(2, 2) - stress(0, 0)) * (stress(2, 2) - stress(0, 0));
245 qsigma_square += H * (stress(0, 0) - stress(1, 1)) * (stress(0, 0) - stress(1, 1));
246 qsigma_square += 2 * L * stress(1, 2) * stress(1, 2);
247 qsigma_square += 2 * M * stress(0, 2) * stress(0, 2);
248 qsigma_square += 2 * N * stress(0, 1) * stress(0, 1);
249 }
250 else
251 {
253 (*_hill_tensor)[_qp].vector_mult(Ms, stress_dev);
254 qsigma_square = Ms.dot(stress_dev);
255 }
256
257 if (qsigma_square == 0)
258 {
259 inelasticStrainIncrement.zero();
260
262 inelasticStrainIncrement, stress, stress_dev, delta_gamma);
263
264 this->_effective_inelastic_strain[_qp] = this->_effective_inelastic_strain_old[_qp];
265
266 return;
267 }
268
269 // Use Hill-type flow rule to compute the time step inelastic increment.
270 GenericReal<is_ad> prefactor = delta_gamma / sqrt(qsigma_square);
271
272 if (!this->_use_transformation)
273 {
274 // Hill constants, some constraints apply
275 const Real & F = _hill_constants[_qp][0];
276 const Real & G = _hill_constants[_qp][1];
277 const Real & H = _hill_constants[_qp][2];
278 const Real & L = _hill_constants[_qp][3];
279 const Real & M = _hill_constants[_qp][4];
280 const Real & N = _hill_constants[_qp][5];
281
282 inelasticStrainIncrement(0, 0) =
283 prefactor * (H * (stress(0, 0) - stress(1, 1)) - G * (stress(2, 2) - stress(0, 0)));
284 inelasticStrainIncrement(1, 1) =
285 prefactor * (F * (stress(1, 1) - stress(2, 2)) - H * (stress(0, 0) - stress(1, 1)));
286 inelasticStrainIncrement(2, 2) =
287 prefactor * (G * (stress(2, 2) - stress(0, 0)) - F * (stress(1, 1) - stress(2, 2)));
288
289 inelasticStrainIncrement(0, 1) = inelasticStrainIncrement(1, 0) =
290 prefactor * 2.0 * N * stress(0, 1);
291 inelasticStrainIncrement(0, 2) = inelasticStrainIncrement(2, 0) =
292 prefactor * 2.0 * M * stress(0, 2);
293 inelasticStrainIncrement(1, 2) = inelasticStrainIncrement(2, 1) =
294 prefactor * 2.0 * L * stress(1, 2);
295 }
296 else
297 {
298 GenericDenseVector<is_ad> inelastic_strain_increment(6);
300 (*_hill_tensor)[_qp].vector_mult(Ms, stress_dev);
301
302 for (unsigned int i = 0; i < 6; i++)
303 inelastic_strain_increment(i) = Ms(i) * prefactor;
304
305 inelasticStrainIncrement(0, 0) = inelastic_strain_increment(0);
306 inelasticStrainIncrement(1, 1) = inelastic_strain_increment(1);
307 inelasticStrainIncrement(2, 2) = inelastic_strain_increment(2);
308
309 inelasticStrainIncrement(0, 1) = inelasticStrainIncrement(1, 0) = inelastic_strain_increment(3);
310 inelasticStrainIncrement(1, 2) = inelasticStrainIncrement(2, 1) = inelastic_strain_increment(4);
311 inelasticStrainIncrement(0, 2) = inelasticStrainIncrement(2, 0) = inelastic_strain_increment(5);
312 }
313
315 inelasticStrainIncrement, stress, stress_dev, delta_gamma);
316
317 this->_effective_inelastic_strain[_qp] = this->_effective_inelastic_strain_old[_qp] + delta_gamma;
318}
319
320template <bool is_ad>
321void
323 const GenericRankTwoTensor<is_ad> & creepStrainIncrement,
324 const GenericReal<is_ad> & /*delta_gamma*/,
325 GenericRankTwoTensor<is_ad> & stress_new,
326 const GenericDenseVector<is_ad> & /*stress_dev*/,
327 const GenericRankTwoTensor<is_ad> & stress_old,
328 const GenericRankFourTensor<is_ad> & elasticity_tensor)
329{
330 using std::abs;
331
332 // Class only valid for isotropic elasticity (for now)
333 stress_new -= elasticity_tensor * creepStrainIncrement;
334
335 // Compute the maximum time step allowed due to creep strain numerical integration error
336 Real stress_dif = MetaPhysicL::raw_value(stress_new - stress_old).L2norm();
337
338 // Get a representative value of the elasticity tensor
339 Real elasticity_value =
340 1.0 / 3.0 *
342 elasticity_tensor(2, 2, 2, 2)));
343
344 if (abs(stress_dif) > TOLERANCE * TOLERANCE)
345 this->_max_integration_error_time_step =
346 _dt / (stress_dif / elasticity_value / this->_max_integration_error);
347 else
348 this->_max_integration_error_time_step = std::numeric_limits<Real>::max();
349}
350
351template <bool is_ad>
352void
354 GenericReal<is_ad> & qsigma_changed,
355 const GenericDenseVector<is_ad> & stress_new,
356 const GenericReal<is_ad> & delta_gamma,
357 GenericRankTwoTensor<is_ad> & stress_changed)
358{
359 using std::sqrt;
360
361 GenericReal<is_ad> qsigma_square;
362
363 // Hill constants, some constraints apply
364 const Real & F = _hill_constants[_qp][0];
365 const Real & G = _hill_constants[_qp][1];
366 const Real & H = _hill_constants[_qp][2];
367 const Real & L = _hill_constants[_qp][3];
368 const Real & M = _hill_constants[_qp][4];
369 const Real & N = _hill_constants[_qp][5];
370
371 if (!this->_use_transformation)
372 {
373 qsigma_square = F * (stress_new(1) - stress_new(2)) * (stress_new(1) - stress_new(2));
374 qsigma_square += G * (stress_new(2) - stress_new(0)) * (stress_new(2) - stress_new(0));
375 qsigma_square += H * (stress_new(0) - stress_new(1)) * (stress_new(0) - stress_new(1));
376 qsigma_square += 2 * L * stress_new(4) * stress_new(4);
377 qsigma_square += 2 * M * stress_new(5) * stress_new(5);
378 qsigma_square += 2 * N * stress_new(3) * stress_new(3);
379 }
380 else
381 {
383 (*_hill_tensor)[_qp].vector_mult(Ms, stress_new);
384 qsigma_square = Ms.dot(stress_new);
385 }
386
387 GenericReal<is_ad> qsigma = sqrt(qsigma_square);
388
389 if (!_anisotropic_elasticity)
390 qsigma_changed = qsigma - 1.5 * _two_shear_modulus * delta_gamma;
391 else
392 {
394 stress(0, 0) = stress_new(0);
395 stress(1, 1) = stress_new(1);
396 stress(2, 2) = stress_new(2);
397 stress(0, 1) = stress(1, 0) = stress_new(3);
398 stress(1, 2) = stress(2, 1) = stress_new(4);
399 stress(0, 2) = stress(2, 0) = stress_new(5);
400
402 b(0) = H * (stress(0, 0) - stress(1, 1)) - G * (stress(2, 2) - stress(0, 0));
403 b(1) = F * (stress(1, 1) - stress(2, 2)) - H * (stress(0, 0) - stress(1, 1));
404 b(2) = G * (stress(2, 2) - stress(0, 0)) - F * (stress(1, 1) - stress(2, 2));
405 b(3) = 2.0 * N * stress(0, 1);
406 b(4) = 2.0 * L * stress(1, 2);
407 b(5) = 2.0 * M * stress(0, 2);
408
409 GenericRankTwoTensor<is_ad> inelasticStrainIncrement;
410 inelasticStrainIncrement(0, 0) = delta_gamma * b(0) / qsigma;
411 inelasticStrainIncrement(1, 1) = delta_gamma * b(1) / qsigma;
412 inelasticStrainIncrement(2, 2) = delta_gamma * b(2) / qsigma;
413 inelasticStrainIncrement(0, 1) = inelasticStrainIncrement(1, 0) = delta_gamma * b(3) / qsigma;
414 inelasticStrainIncrement(1, 2) = inelasticStrainIncrement(2, 1) = delta_gamma * b(4) / qsigma;
415 inelasticStrainIncrement(0, 2) = inelasticStrainIncrement(2, 0) = delta_gamma * b(5) / qsigma;
416
417 stress_changed = stress - _elasticity_tensor[_qp] * inelasticStrainIncrement;
418
419 GenericReal<is_ad> qsigma_square_changed;
420 qsigma_square_changed = F * (stress_changed(1, 1) - stress_changed(2, 2)) *
421 (stress_changed(1, 1) - stress_changed(2, 2));
422 qsigma_square_changed += G * (stress_changed(2, 2) - stress_changed(0, 0)) *
423 (stress_changed(2, 2) - stress_changed(0, 0));
424 qsigma_square_changed += H * (stress_changed(0, 0) - stress_changed(1, 1)) *
425 (stress_changed(0, 0) - stress_changed(1, 1));
426 qsigma_square_changed += 2 * L * stress_changed(1, 2) * stress_changed(1, 2);
427 qsigma_square_changed += 2 * M * stress_changed(0, 2) * stress_changed(0, 2);
428 qsigma_square_changed += 2 * N * stress_changed(0, 1) * stress_changed(0, 1);
429 qsigma_changed = sqrt(qsigma_square_changed);
430 }
431}
432
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const double M
registerMooseObject("SolidMechanicsApp", ADHillCreepStressUpdate)
Moose::GenericType< RankFourTensor, is_ad > GenericRankFourTensor
Moose::GenericType< DenseVector< Real >, is_ad > GenericDenseVector
Moose::GenericType< Real, is_ad > GenericReal
Moose::GenericType< RankTwoTensor, is_ad > GenericRankTwoTensor
Moose::GenericType< DenseMatrix< Real >, is_ad > GenericDenseMatrix
This class provides baseline functionality for anisotropic (Hill-like) plasticity and creep models ba...
virtual void computeStrainFinalize(GenericRankTwoTensor< is_ad > &, const GenericRankTwoTensor< is_ad > &, const GenericDenseVector< is_ad > &, const GenericReal< is_ad > &) override
Perform any necessary steps to finalize strain increment after return mapping iterations.
This class uses the stress update material for an anisotropic creep model.
virtual void computeStressInitialize(const GenericDenseVector< is_ad > &stress_dev, const GenericDenseVector< is_ad > &stress, const GenericRankFourTensor< is_ad > &elasticity_tensor) override
void computeQsigmaChanged(GenericReal< is_ad > &qsigma_changed, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &delta_gamma, GenericRankTwoTensor< is_ad > &stress_changed)
virtual GenericReal< is_ad > computeResidual(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &scalar) override
virtual Real computeReferenceResidual(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &residual, const GenericReal< is_ad > &scalar_effective_inelastic_strain) override
virtual GenericReal< is_ad > initialGuess(const GenericDenseVector< is_ad > &) override
virtual void computeStressFinalize(const GenericRankTwoTensor< is_ad > &inelasticStrainIncrement, const GenericReal< is_ad > &delta_gamma, GenericRankTwoTensor< is_ad > &stress, const GenericDenseVector< is_ad > &stress_dev, const GenericRankTwoTensor< is_ad > &stress_old, const GenericRankFourTensor< is_ad > &elasticity_tensor) override
Perform any necessary steps to finalize state after return mapping iterations.
const Real _m_exponent
Exponent on time.
virtual void computeStrainFinalize(GenericRankTwoTensor< is_ad > &inelasticStrainIncrement, const GenericRankTwoTensor< is_ad > &stress, const GenericDenseVector< is_ad > &stress_dev, const GenericReal< is_ad > &delta_gamma) override
Perform any necessary steps to finalize strain increment after return mapping iterations.
static InputParameters validParams()
virtual GenericReal< is_ad > computeDerivative(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &scalar) override
HillCreepStressUpdateTempl(const InputParameters &parameters)
void addRequiredParam(const std::string &name, const std::string &doc_string)
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)
void addCoupledVar(const std::string &name, const std::string &doc_string)
T getIsotropicShearModulus(const RankFourTensorTempl< T > &elasticity_tensor)
Get the shear modulus for an isotropic elasticity tensor param elasticity_tensor the tensor (must be ...
auto raw_value(const Eigen::Map< T > &in)
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)