https://mooseframework.inl.gov
Loading...
Searching...
No Matches
HillPlasticityStressUpdate.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
15
16template <bool is_ad>
19{
22 "This class uses the generalized radial return for anisotropic plasticity model."
23 "This class can be used in conjunction with other creep and plasticity materials for "
24 "more complex simulations.");
25
26 params.addRequiredParam<Real>("hardening_constant",
27 "Hardening constant (H) for anisotropic plasticity");
28 params.addParam<Real>(
29 "hardening_exponent", 1.0, "Hardening exponent (n) for anisotropic plasticity");
30 params.addRequiredParam<Real>("yield_stress",
31 "Yield stress (constant value) for anisotropic plasticity");
32
33 return params;
34}
35
36template <bool is_ad>
38 const InputParameters & parameters)
40 _qsigma(0.0),
41 _eigenvalues_hill(6),
42 _eigenvectors_hill(6, 6),
43 _hardening_constant(this->template getParam<Real>("hardening_constant")),
44 _hardening_exponent(this->template getParam<Real>("hardening_exponent")),
45 _hardening_variable(this->template declareGenericProperty<Real, is_ad>(this->_base_name +
46 "hardening_variable")),
47 _hardening_variable_old(
48 this->template getMaterialPropertyOld<Real>(this->_base_name + "hardening_variable")),
49 _hardening_derivative(0.0),
50 _yield_condition(1.0),
51 _yield_stress(this->template getParam<Real>("yield_stress")),
52 _hill_tensor(this->template getMaterialPropertyByName<DenseMatrix<Real>>(this->_base_name +
53 "hill_tensor")),
54 _stress_np1(6)
55{
56}
57
58template <bool is_ad>
59void
61{
62 _hardening_variable[_qp] = _hardening_variable_old[_qp];
63 _plasticity_strain[_qp] = _plasticity_strain_old[_qp];
65}
66
67template <bool is_ad>
68void
70 const GenericDenseVector<is_ad> & stress_dev,
71 const GenericDenseVector<is_ad> & /*stress*/,
72 const GenericRankFourTensor<is_ad> & elasticity_tensor)
73{
74 _hardening_variable[_qp] = _hardening_variable_old[_qp];
75 _plasticity_strain[_qp] = _plasticity_strain_old[_qp];
76 _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp];
77
79
80 // Hill constants: We use directly the transformation tensor, which won't be updated if not
81 // necessary in the Hill tensor material.
82 computeHillTensorEigenDecomposition(_hill_tensor[_qp]);
83
84 _yield_condition = 1.0; // Some positive value
85 _yield_condition = -computeResidual(stress_dev, stress_dev, 0.0);
86}
87
88template <bool is_ad>
91 const GenericDenseVector<is_ad> & stress_trial)
92{
94 GenericReal<is_ad> omega = 0.0;
95
96 for (unsigned int i = 0; i < 6; i++)
97 {
98 K(i) = _eigenvalues_hill(i) /
99 (Utility::pow<2>(1 + _two_shear_modulus * delta_gamma * _eigenvalues_hill(i)));
100 omega += K(i) * stress_trial(i) * stress_trial(i);
101 }
102 omega *= 0.5;
103
104 if (omega == 0.0)
105 omega = 1.0e-36;
106
107 using std::sqrt;
108 return sqrt(omega);
109}
110
111template <bool is_ad>
112void
114 const GenericReal<is_ad> & delta_gamma,
115 const GenericDenseVector<is_ad> & stress_trial,
116 const GenericReal<is_ad> & sy_alpha,
117 GenericReal<is_ad> & omega,
118 GenericReal<is_ad> & omega_gamma,
119 GenericReal<is_ad> & sy_gamma)
120{
121 omega_gamma = 0.0;
122 sy_gamma = 0.0;
123
124 GenericDenseVector<is_ad> K_deltaGamma(6);
125 omega = computeOmega(delta_gamma, stress_trial);
126
128 for (unsigned int i = 0; i < 6; i++)
129 K(i) = _eigenvalues_hill(i) /
130 (Utility::pow<2>(1 + _two_shear_modulus * delta_gamma * _eigenvalues_hill(i)));
131
132 for (unsigned int i = 0; i < 6; i++)
133 K_deltaGamma(i) = -2.0 * _two_shear_modulus * _eigenvalues_hill(i) * K(i) /
134 (1 + _two_shear_modulus * delta_gamma * _eigenvalues_hill(i));
135
136 for (unsigned int i = 0; i < 6; i++)
137 omega_gamma += K_deltaGamma(i) * stress_trial(i) * stress_trial(i);
138
139 omega_gamma /= 4.0 * omega;
140 sy_gamma = 2.0 * sy_alpha * (omega + delta_gamma * omega_gamma);
141}
142
143template <bool is_ad>
144Real
146 const GenericDenseVector<is_ad> & /*effective_trial_stress*/,
147 const GenericDenseVector<is_ad> & /*stress_new*/,
148 const GenericReal<is_ad> & /*residual*/,
149 const GenericReal<is_ad> & /*scalar_effective_inelastic_strain*/)
150{
151 // Equation is already normalized.
152 return 1.0;
153}
154
155template <bool is_ad>
158 const GenericDenseVector<is_ad> & stress_dev,
159 const GenericDenseVector<is_ad> & /*stress_sigma*/,
160 const GenericReal<is_ad> & delta_gamma)
161{
162 using std::pow;
163
164 // If in elastic regime, just return
165 if (_yield_condition <= 0.0)
166 return 0.0;
167
168 GenericDenseMatrix<is_ad> eigenvectors_hill_transpose(6, 6);
169
170 _eigenvectors_hill.get_transpose(eigenvectors_hill_transpose);
171 eigenvectors_hill_transpose.vector_mult(_stress_np1, stress_dev);
172
173 GenericReal<is_ad> omega = computeOmega(delta_gamma, _stress_np1);
174
175 // Hardening variable is \alpha isotropic hardening for now.
176 _hardening_variable[_qp] = computeHardeningValue(delta_gamma, omega);
178 _hardening_constant * pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent) +
179 _yield_stress;
180
181 GenericReal<is_ad> residual = 0.0;
182 residual = s_y / omega - 1.0;
183
184 return residual;
185}
186
187template <bool is_ad>
190 const GenericDenseVector<is_ad> & /*stress_dev*/,
191 const GenericDenseVector<is_ad> & /*stress_sigma*/,
192 const GenericReal<is_ad> & delta_gamma)
193{
194 // If in elastic regime, return unit derivative
195 if (_yield_condition <= 0.0)
196 return 1.0;
197
198 GenericReal<is_ad> omega = computeOmega(delta_gamma, _stress_np1);
199 _hardening_derivative = computeHardeningDerivative();
200
202 _hardening_derivative * computeHardeningValue(delta_gamma, omega) + _yield_stress;
203 GenericReal<is_ad> sy_alpha = _hardening_derivative;
204
205 GenericReal<is_ad> omega_gamma;
206 GenericReal<is_ad> sy_gamma;
207
208 computeDeltaDerivatives(delta_gamma, _stress_np1, sy_alpha, omega, omega_gamma, sy_gamma);
209 GenericReal<is_ad> residual_derivative = 1 / omega * (sy_gamma - 1 / omega * omega_gamma * sy);
210
211 return residual_derivative;
212}
213
214template <bool is_ad>
215void
217 const DenseMatrix<Real> & hill_tensor)
218{
219 const unsigned int dimension = hill_tensor.n();
220
222 for (unsigned int index_i = 0; index_i < dimension; index_i++)
223 for (unsigned int index_j = 0; index_j < dimension; index_j++)
224 A(index_i, index_j) = MetaPhysicL::raw_value(hill_tensor(index_i, index_j));
225
226 if (isBlockDiagonal(A))
227 {
228 Eigen::SelfAdjointEigenSolver<AnisotropyMatrixRealBlock> es(A.block<3, 3>(0, 0));
229
230 auto lambda = es.eigenvalues();
231 auto v = es.eigenvectors();
232
233 _eigenvalues_hill(0) = lambda(0);
234 _eigenvalues_hill(1) = lambda(1);
235 _eigenvalues_hill(2) = lambda(2);
236 _eigenvalues_hill(3) = A(3, 3);
237 _eigenvalues_hill(4) = A(4, 4);
238 _eigenvalues_hill(5) = A(5, 5);
239
240 _eigenvectors_hill(0, 0) = v(0, 0);
241 _eigenvectors_hill(0, 1) = v(0, 1);
242 _eigenvectors_hill(0, 2) = v(0, 2);
243 _eigenvectors_hill(1, 0) = v(1, 0);
244 _eigenvectors_hill(1, 1) = v(1, 1);
245 _eigenvectors_hill(1, 2) = v(1, 2);
246 _eigenvectors_hill(2, 0) = v(2, 0);
247 _eigenvectors_hill(2, 1) = v(2, 1);
248 _eigenvectors_hill(2, 2) = v(2, 2);
249 _eigenvectors_hill(3, 3) = 1.0;
250 _eigenvectors_hill(4, 4) = 1.0;
251 _eigenvectors_hill(5, 5) = 1.0;
252 }
253 else
254 {
255 Eigen::SelfAdjointEigenSolver<AnisotropyMatrixReal> es_b(A);
256
257 auto lambda_b = es_b.eigenvalues();
258 auto v_b = es_b.eigenvectors();
259 for (unsigned int index_i = 0; index_i < dimension; index_i++)
260 _eigenvalues_hill(index_i) = lambda_b(index_i);
261
262 for (unsigned int index_i = 0; index_i < dimension; index_i++)
263 for (unsigned int index_j = 0; index_j < dimension; index_j++)
264 _eigenvectors_hill(index_i, index_j) = v_b(index_i, index_j);
265 }
266}
267
268template <bool is_ad>
271 const GenericReal<is_ad> & delta_gamma, const GenericReal<is_ad> & omega)
272{
273 return _hardening_variable_old[_qp] + 2.0 * delta_gamma * omega;
274}
275
276template <bool is_ad>
277Real
279{
280 using std::pow;
281
282 return _hardening_constant * _hardening_exponent *
283 MetaPhysicL::raw_value(pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent - 1));
284}
285
286template <bool is_ad>
287void
289 GenericRankTwoTensor<is_ad> & inelasticStrainIncrement,
290 const GenericRankTwoTensor<is_ad> & stress,
291 const GenericDenseVector<is_ad> & stress_dev,
292 const GenericReal<is_ad> & delta_gamma)
293{
294 using std::sqrt;
295
296 // e^P = delta_gamma * hill_tensor * stress
297 GenericDenseVector<is_ad> inelasticStrainIncrement_vector(6);
298 GenericDenseVector<is_ad> hill_stress(6);
299 _hill_tensor[_qp].vector_mult(hill_stress, stress_dev);
300 hill_stress.scale(delta_gamma);
301 inelasticStrainIncrement_vector = hill_stress;
302
303 inelasticStrainIncrement(0, 0) = inelasticStrainIncrement_vector(0);
304 inelasticStrainIncrement(1, 1) = inelasticStrainIncrement_vector(1);
305 inelasticStrainIncrement(2, 2) = inelasticStrainIncrement_vector(2);
306 inelasticStrainIncrement(0, 1) = inelasticStrainIncrement(1, 0) =
307 inelasticStrainIncrement_vector(3) / 2.0;
308 inelasticStrainIncrement(1, 2) = inelasticStrainIncrement(2, 1) =
309 inelasticStrainIncrement_vector(4) / 2.0;
310 inelasticStrainIncrement(0, 2) = inelasticStrainIncrement(2, 0) =
311 inelasticStrainIncrement_vector(5) / 2.0;
312
313 // Calculate equivalent plastic strain
314 GenericDenseVector<is_ad> Mepsilon(6);
315 _hill_tensor[_qp].vector_mult(Mepsilon, inelasticStrainIncrement_vector);
316 GenericReal<is_ad> eq_plastic_strain_inc = Mepsilon.dot(inelasticStrainIncrement_vector);
317
318 if (eq_plastic_strain_inc > 0.0)
319 eq_plastic_strain_inc = sqrt(eq_plastic_strain_inc);
320
321 _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp] + eq_plastic_strain_inc;
322
324 inelasticStrainIncrement, stress, stress_dev, delta_gamma);
325}
326
327template <bool is_ad>
328void
330 const GenericRankTwoTensor<is_ad> & /*plastic_strain_increment*/,
331 const GenericReal<is_ad> & delta_gamma,
332 GenericRankTwoTensor<is_ad> & stress_new,
333 const GenericDenseVector<is_ad> & stress_dev,
334 const GenericRankTwoTensor<is_ad> & /*sstress_old*/,
335 const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/)
336{
337 // Need to compute this iteration's stress tensor based on the scalar variable for deviatoric
338 // s(n+1) = {Q [I + 2*nu*delta_gamma*Delta]^(-1) Q^T} s(trial)
339
340 if (_yield_condition <= 0.0)
341 return;
342
343 GenericDenseMatrix<is_ad> inv_matrix(6, 6);
344 for (unsigned int i = 0; i < 6; i++)
345 inv_matrix(i, i) = 1 / (1 + _two_shear_modulus * delta_gamma * _eigenvalues_hill(i));
346
347 GenericDenseMatrix<is_ad> eigenvectors_hill_transpose(6, 6);
348
349 _eigenvectors_hill.get_transpose(eigenvectors_hill_transpose);
350 GenericDenseMatrix<is_ad> eigenvectors_hill_copy(_eigenvectors_hill);
351
352 // Right multiply by matrix of eigenvectors transpose
353 inv_matrix.right_multiply(eigenvectors_hill_transpose);
354 // Right multiply eigenvector matrix by [I + 2*nu*delta_gamma*Delta]^(-1) Q^T
355 eigenvectors_hill_copy.right_multiply(inv_matrix);
356
357 GenericDenseVector<is_ad> stress_np1(6);
358 eigenvectors_hill_copy.vector_mult(stress_np1, stress_dev);
359
360 GenericRankTwoTensor<is_ad> stress_new_volumetric = stress_new - stress_new.deviatoric();
361
362 stress_new(0, 0) = stress_new_volumetric(0, 0) + stress_np1(0);
363 stress_new(1, 1) = stress_new_volumetric(1, 1) + stress_np1(1);
364 stress_new(2, 2) = stress_new_volumetric(2, 2) + stress_np1(2);
365 stress_new(0, 1) = stress_new(1, 0) = stress_np1(3);
366 stress_new(1, 2) = stress_new(2, 1) = stress_np1(4);
367 stress_new(0, 2) = stress_new(2, 0) = stress_np1(5);
368
369 GenericReal<is_ad> omega = computeOmega(delta_gamma, _stress_np1);
370 _hardening_variable[_qp] = computeHardeningValue(delta_gamma, omega);
371}
372
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const double v
Eigen::Matrix< Real, 6, 6 > AnisotropyMatrixReal
registerMooseObject("SolidMechanicsApp", ADHillPlasticityStressUpdate)
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 models based on the...
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 in an anisotropic return mapping.
HillPlasticityStressUpdateTempl(const InputParameters &parameters)
void computeHillTensorEigenDecomposition(const DenseMatrix< Real > &hill_tensor)
Compute eigendecomposition of Hill's tensor for anisotropic plasticity.
virtual void computeStressFinalize(const GenericRankTwoTensor< is_ad > &inelasticStrainIncrement, const GenericReal< is_ad > &delta_gamma, GenericRankTwoTensor< is_ad > &stress, const GenericDenseVector< is_ad > &, const GenericRankTwoTensor< is_ad > &, const GenericRankFourTensor< is_ad > &) override
Perform any necessary steps to finalize state after return mapping iterations.
GenericReal< is_ad > computeHardeningValue(const GenericReal< is_ad > &scalar, const GenericReal< is_ad > &omega)
void computeDeltaDerivatives(const GenericReal< is_ad > &delta_gamma, const GenericDenseVector< is_ad > &stress_trial, const GenericReal< is_ad > &sy_alpha, GenericReal< is_ad > &omega, GenericReal< is_ad > &omega_gamma, GenericReal< is_ad > &sy_gamma)
GenericReal< is_ad > computeOmega(const GenericReal< is_ad > &delta_gamma, const GenericDenseVector< is_ad > &stress_trial)
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.
virtual void computeStressInitialize(const GenericDenseVector< is_ad > &stress_dev, const GenericDenseVector< is_ad > &stress, const GenericRankFourTensor< is_ad > &elasticity_tensor) override
virtual void propagateQpStatefulProperties() override
virtual GenericReal< is_ad > computeDerivative(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 > computeResidual(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &scalar) override
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)
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)