https://mooseframework.inl.gov
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 
11 #include "ElasticityTensorTools.h"
12 
15 
16 template <bool is_ad>
19 {
21  params.addClassDescription(
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 
36 template <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 
58 template <bool is_ad>
59 void
61 {
62  _hardening_variable[_qp] = _hardening_variable_old[_qp];
63  _plasticity_strain[_qp] = _plasticity_strain_old[_qp];
65 }
66 
67 template <bool is_ad>
68 void
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 
88 template <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  return std::sqrt(omega);
108 }
109 
110 template <bool is_ad>
111 void
113  const GenericReal<is_ad> & delta_gamma,
114  const GenericDenseVector<is_ad> & stress_trial,
115  const GenericReal<is_ad> & sy_alpha,
116  GenericReal<is_ad> & omega,
117  GenericReal<is_ad> & omega_gamma,
118  GenericReal<is_ad> & sy_gamma)
119 {
120  omega_gamma = 0.0;
121  sy_gamma = 0.0;
122 
123  GenericDenseVector<is_ad> K_deltaGamma(6);
124  omega = computeOmega(delta_gamma, stress_trial);
125 
127  for (unsigned int i = 0; i < 6; i++)
128  K(i) = _eigenvalues_hill(i) /
129  (Utility::pow<2>(1 + _two_shear_modulus * delta_gamma * _eigenvalues_hill(i)));
130 
131  for (unsigned int i = 0; i < 6; i++)
132  K_deltaGamma(i) = -2.0 * _two_shear_modulus * _eigenvalues_hill(i) * K(i) /
133  (1 + _two_shear_modulus * delta_gamma * _eigenvalues_hill(i));
134 
135  for (unsigned int i = 0; i < 6; i++)
136  omega_gamma += K_deltaGamma(i) * stress_trial(i) * stress_trial(i);
137 
138  omega_gamma /= 4.0 * omega;
139  sy_gamma = 2.0 * sy_alpha * (omega + delta_gamma * omega_gamma);
140 }
141 
142 template <bool is_ad>
143 Real
145  const GenericDenseVector<is_ad> & /*effective_trial_stress*/,
146  const GenericDenseVector<is_ad> & /*stress_new*/,
147  const GenericReal<is_ad> & /*residual*/,
148  const GenericReal<is_ad> & /*scalar_effective_inelastic_strain*/)
149 {
150  // Equation is already normalized.
151  return 1.0;
152 }
153 
154 template <bool is_ad>
157  const GenericDenseVector<is_ad> & stress_dev,
158  const GenericDenseVector<is_ad> & /*stress_sigma*/,
159  const GenericReal<is_ad> & delta_gamma)
160 {
161 
162  // If in elastic regime, just return
163  if (_yield_condition <= 0.0)
164  return 0.0;
165 
166  GenericDenseMatrix<is_ad> eigenvectors_hill_transpose(6, 6);
167 
168  _eigenvectors_hill.get_transpose(eigenvectors_hill_transpose);
169  eigenvectors_hill_transpose.vector_mult(_stress_np1, stress_dev);
170 
171  GenericReal<is_ad> omega = computeOmega(delta_gamma, _stress_np1);
172 
173  // Hardening variable is \alpha isotropic hardening for now.
174  _hardening_variable[_qp] = computeHardeningValue(delta_gamma, omega);
175  GenericReal<is_ad> s_y =
176  _hardening_constant * std::pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent) +
177  _yield_stress;
178 
179  GenericReal<is_ad> residual = 0.0;
180  residual = s_y / omega - 1.0;
181 
182  return residual;
183 }
184 
185 template <bool is_ad>
188  const GenericDenseVector<is_ad> & /*stress_dev*/,
189  const GenericDenseVector<is_ad> & /*stress_sigma*/,
190  const GenericReal<is_ad> & delta_gamma)
191 {
192  // If in elastic regime, return unit derivative
193  if (_yield_condition <= 0.0)
194  return 1.0;
195 
196  GenericReal<is_ad> omega = computeOmega(delta_gamma, _stress_np1);
197  _hardening_derivative = computeHardeningDerivative();
198 
199  GenericReal<is_ad> sy =
200  _hardening_derivative * computeHardeningValue(delta_gamma, omega) + _yield_stress;
201  GenericReal<is_ad> sy_alpha = _hardening_derivative;
202 
203  GenericReal<is_ad> omega_gamma;
204  GenericReal<is_ad> sy_gamma;
205 
206  computeDeltaDerivatives(delta_gamma, _stress_np1, sy_alpha, omega, omega_gamma, sy_gamma);
207  GenericReal<is_ad> residual_derivative = 1 / omega * (sy_gamma - 1 / omega * omega_gamma * sy);
208 
209  return residual_derivative;
210 }
211 
212 template <bool is_ad>
213 void
215  const DenseMatrix<Real> & hill_tensor)
216 {
217  const unsigned int dimension = hill_tensor.n();
218 
220  for (unsigned int index_i = 0; index_i < dimension; index_i++)
221  for (unsigned int index_j = 0; index_j < dimension; index_j++)
222  A(index_i, index_j) = MetaPhysicL::raw_value(hill_tensor(index_i, index_j));
223 
224  if (isBlockDiagonal(A))
225  {
226  Eigen::SelfAdjointEigenSolver<AnisotropyMatrixRealBlock> es(A.block<3, 3>(0, 0));
227 
228  auto lambda = es.eigenvalues();
229  auto v = es.eigenvectors();
230 
231  _eigenvalues_hill(0) = lambda(0);
232  _eigenvalues_hill(1) = lambda(1);
233  _eigenvalues_hill(2) = lambda(2);
234  _eigenvalues_hill(3) = A(3, 3);
235  _eigenvalues_hill(4) = A(4, 4);
236  _eigenvalues_hill(5) = A(5, 5);
237 
238  _eigenvectors_hill(0, 0) = v(0, 0);
239  _eigenvectors_hill(0, 1) = v(0, 1);
240  _eigenvectors_hill(0, 2) = v(0, 2);
241  _eigenvectors_hill(1, 0) = v(1, 0);
242  _eigenvectors_hill(1, 1) = v(1, 1);
243  _eigenvectors_hill(1, 2) = v(1, 2);
244  _eigenvectors_hill(2, 0) = v(2, 0);
245  _eigenvectors_hill(2, 1) = v(2, 1);
246  _eigenvectors_hill(2, 2) = v(2, 2);
247  _eigenvectors_hill(3, 3) = 1.0;
248  _eigenvectors_hill(4, 4) = 1.0;
249  _eigenvectors_hill(5, 5) = 1.0;
250  }
251  else
252  {
253  Eigen::SelfAdjointEigenSolver<AnisotropyMatrixReal> es_b(A);
254 
255  auto lambda_b = es_b.eigenvalues();
256  auto v_b = es_b.eigenvectors();
257  for (unsigned int index_i = 0; index_i < dimension; index_i++)
258  _eigenvalues_hill(index_i) = lambda_b(index_i);
259 
260  for (unsigned int index_i = 0; index_i < dimension; index_i++)
261  for (unsigned int index_j = 0; index_j < dimension; index_j++)
262  _eigenvectors_hill(index_i, index_j) = v_b(index_i, index_j);
263  }
264 }
265 
266 template <bool is_ad>
269  const GenericReal<is_ad> & delta_gamma, const GenericReal<is_ad> & omega)
270 {
271  return _hardening_variable_old[_qp] + 2.0 * delta_gamma * omega;
272 }
273 
274 template <bool is_ad>
275 Real
277 {
278  return _hardening_constant * _hardening_exponent *
280  std::pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent - 1));
281 }
282 
283 template <bool is_ad>
284 void
286  GenericRankTwoTensor<is_ad> & inelasticStrainIncrement,
287  const GenericRankTwoTensor<is_ad> & stress,
288  const GenericDenseVector<is_ad> & stress_dev,
289  const GenericReal<is_ad> & delta_gamma)
290 {
291  // e^P = delta_gamma * hill_tensor * stress
292  GenericDenseVector<is_ad> inelasticStrainIncrement_vector(6);
293  GenericDenseVector<is_ad> hill_stress(6);
294  _hill_tensor[_qp].vector_mult(hill_stress, stress_dev);
295  hill_stress.scale(delta_gamma);
296  inelasticStrainIncrement_vector = hill_stress;
297 
298  inelasticStrainIncrement(0, 0) = inelasticStrainIncrement_vector(0);
299  inelasticStrainIncrement(1, 1) = inelasticStrainIncrement_vector(1);
300  inelasticStrainIncrement(2, 2) = inelasticStrainIncrement_vector(2);
301  inelasticStrainIncrement(0, 1) = inelasticStrainIncrement(1, 0) =
302  inelasticStrainIncrement_vector(3) / 2.0;
303  inelasticStrainIncrement(1, 2) = inelasticStrainIncrement(2, 1) =
304  inelasticStrainIncrement_vector(4) / 2.0;
305  inelasticStrainIncrement(0, 2) = inelasticStrainIncrement(2, 0) =
306  inelasticStrainIncrement_vector(5) / 2.0;
307 
308  // Calculate equivalent plastic strain
309  GenericDenseVector<is_ad> Mepsilon(6);
310  _hill_tensor[_qp].vector_mult(Mepsilon, inelasticStrainIncrement_vector);
311  GenericReal<is_ad> eq_plastic_strain_inc = Mepsilon.dot(inelasticStrainIncrement_vector);
312 
313  if (eq_plastic_strain_inc > 0.0)
314  eq_plastic_strain_inc = std::sqrt(eq_plastic_strain_inc);
315 
316  _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp] + eq_plastic_strain_inc;
317 
319  inelasticStrainIncrement, stress, stress_dev, delta_gamma);
320 }
321 
322 template <bool is_ad>
323 void
325  const GenericRankTwoTensor<is_ad> & /*plastic_strain_increment*/,
326  const GenericReal<is_ad> & delta_gamma,
327  GenericRankTwoTensor<is_ad> & stress_new,
328  const GenericDenseVector<is_ad> & stress_dev,
329  const GenericRankTwoTensor<is_ad> & /*sstress_old*/,
330  const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/)
331 {
332  // Need to compute this iteration's stress tensor based on the scalar variable for deviatoric
333  // s(n+1) = {Q [I + 2*nu*delta_gamma*Delta]^(-1) Q^T} s(trial)
334 
335  if (_yield_condition <= 0.0)
336  return;
337 
338  GenericDenseMatrix<is_ad> inv_matrix(6, 6);
339  for (unsigned int i = 0; i < 6; i++)
340  inv_matrix(i, i) = 1 / (1 + _two_shear_modulus * delta_gamma * _eigenvalues_hill(i));
341 
342  GenericDenseMatrix<is_ad> eigenvectors_hill_transpose(6, 6);
343 
344  _eigenvectors_hill.get_transpose(eigenvectors_hill_transpose);
345  GenericDenseMatrix<is_ad> eigenvectors_hill_copy(_eigenvectors_hill);
346 
347  // Right multiply by matrix of eigenvectors transpose
348  inv_matrix.right_multiply(eigenvectors_hill_transpose);
349  // Right multiply eigenvector matrix by [I + 2*nu*delta_gamma*Delta]^(-1) Q^T
350  eigenvectors_hill_copy.right_multiply(inv_matrix);
351 
352  GenericDenseVector<is_ad> stress_np1(6);
353  eigenvectors_hill_copy.vector_mult(stress_np1, stress_dev);
354 
355  GenericRankTwoTensor<is_ad> stress_new_volumetric = stress_new - stress_new.deviatoric();
356 
357  stress_new(0, 0) = stress_new_volumetric(0, 0) + stress_np1(0);
358  stress_new(1, 1) = stress_new_volumetric(1, 1) + stress_np1(1);
359  stress_new(2, 2) = stress_new_volumetric(2, 2) + stress_np1(2);
360  stress_new(0, 1) = stress_new(1, 0) = stress_np1(3);
361  stress_new(1, 2) = stress_new(2, 1) = stress_np1(4);
362  stress_new(0, 2) = stress_new(2, 0) = stress_np1(5);
363 
364  GenericReal<is_ad> omega = computeOmega(delta_gamma, _stress_np1);
365  _hardening_variable[_qp] = computeHardeningValue(delta_gamma, omega);
366 }
367 
Moose::GenericType< Real, is_ad > GenericReal
virtual void computeStressInitialize(const GenericDenseVector< is_ad > &stress_dev, const GenericDenseVector< is_ad > &stress, const GenericRankFourTensor< is_ad > &elasticity_tensor) override
T getIsotropicShearModulus(const RankFourTensorTempl< T > &elasticity_tensor)
Get the shear modulus for an isotropic elasticity tensor param elasticity_tensor the tensor (must be ...
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
GenericReal< is_ad > computeHardeningValue(const GenericReal< is_ad > &scalar, const GenericReal< is_ad > &omega)
Eigen::Matrix< Real, 6, 6 > AnisotropyMatrixReal
static const std::string K
Definition: NS.h:170
registerMooseObject("SolidMechanicsApp", ADHillPlasticityStressUpdate)
virtual GenericReal< is_ad > computeDerivative(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &scalar) override
auto raw_value(const Eigen::Map< T > &in)
void computeHillTensorEigenDecomposition(const DenseMatrix< Real > &hill_tensor)
Compute eigendecomposition of Hill&#39;s tensor for anisotropic plasticity.
Moose::GenericType< DenseVector< Real >, is_ad > GenericDenseVector
This class uses the stress update material in an anisotropic return mapping.
Moose::GenericType< RankFourTensor, is_ad > GenericRankFourTensor
void addRequiredParam(const std::string &name, const std::string &doc_string)
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)
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)
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.
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 GenericReal< is_ad > computeResidual(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &scalar) override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
Definition: NS.h:84
HillPlasticityStressUpdateTempl(const InputParameters &parameters)
GenericReal< is_ad > computeOmega(const GenericReal< is_ad > &delta_gamma, const GenericDenseVector< is_ad > &stress_trial)
void addClassDescription(const std::string &doc_string)
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 provides baseline functionality for anisotropic (Hill-like) plasticity models based on the...
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
unsigned int n() const
MooseUnits pow(const MooseUnits &, int)
Moose::GenericType< DenseMatrix< Real >, is_ad > GenericDenseMatrix
Moose::GenericType< RankTwoTensor, is_ad > GenericRankTwoTensor
virtual void propagateQpStatefulProperties() override