23 "This class uses the generalized radial return for anisotropic elasto-plasticity model." 24 "This class can be used in conjunction with other creep and plasticity materials for " 25 "more complex simulations.");
28 "Hardening constant (H) for anisotropic plasticity");
30 "hardening_exponent", 1.0,
"Hardening exponent (n) for anisotropic plasticity");
32 "Yield stress (constant value) for anisotropic plasticity");
34 "local_cylindrical_csys",
36 "Compute inelastic strain increment in local cylindrical coordinate system");
40 "The axis of cylindrical component about which to rotate when " 41 "computing inelastic strain increment in local coordinate system");
52 _eigenvectors_hill(6, 6),
53 _anisotropic_elastic_tensor(6, 6),
54 _elasticity_tensor_name(this->_base_name +
"elasticity_tensor"),
56 this->template getGenericMaterialProperty<
RankFourTensor, is_ad>(_elasticity_tensor_name)),
57 _hardening_constant(this->template getParam<
Real>(
"hardening_constant")),
58 _hardening_exponent(this->template getParam<
Real>(
"hardening_exponent")),
59 _hardening_variable(this->template declareGenericProperty<
Real, is_ad>(this->_base_name +
60 "hardening_variable")),
61 _hardening_variable_old(
62 this->template getMaterialPropertyOld<
Real>(this->_base_name +
"hardening_variable")),
63 _elasticity_eigenvectors(this->template declareGenericProperty<DenseMatrix<
Real>, is_ad>(
64 this->_base_name +
"elasticity_eigenvectors")),
65 _elasticity_eigenvalues(this->template declareGenericProperty<DenseVector<
Real>, is_ad>(
66 this->_base_name +
"elasticity_eigenvalues")),
67 _b_eigenvectors(this->template declareGenericProperty<DenseMatrix<
Real>, is_ad>(
68 this->_base_name +
"b_eigenvectors")),
69 _b_eigenvalues(this->template declareGenericProperty<DenseVector<
Real>, is_ad>(
70 this->_base_name +
"b_eigenvalues")),
71 _alpha_matrix(this->template declareGenericProperty<DenseMatrix<
Real>, is_ad>(this->_base_name +
73 _sigma_tilde(this->template declareGenericProperty<DenseVector<
Real>, is_ad>(this->_base_name +
75 _sigma_tilde_rotated(this->template declareGenericProperty<DenseVector<
Real>, is_ad>(
76 this->_base_name +
"sigma_tilde_rotated")),
77 _hardening_derivative(0.0),
78 _yield_condition(1.0),
79 _yield_stress(this->template getParam<
Real>(
"yield_stress")),
80 _hill_tensor(this->template getMaterialPropertyByName<DenseMatrix<
Real>>(this->_base_name +
83 this->template declareProperty<
RankTwoTensor>(this->_base_name +
"rotation_matrix")),
84 _rotation_matrix_transpose(this->template declareProperty<
RankTwoTensor>(
85 this->_base_name +
"rotation_matrix_transpose")),
87 this->template getMaterialPropertyOld<
RankTwoTensor>(this->_base_name +
"rotation_matrix")),
88 _rotation_matrix_transpose_old(this->template getMaterialPropertyOld<
RankTwoTensor>(
89 this->_base_name +
"rotation_matrix_transpose")),
90 _local_cylindrical_csys(this->template getParam<bool>(
"local_cylindrical_csys")),
91 _axis(this->template getParam<
MooseEnum>(
"axis").template getEnum<
Axis>())
96 "local_cylindrical_csys",
97 "\nIf parameter local_cylindrical_csys is provided then parameter axis should be also " 104 "\nIf parameter axis is provided then the parameter local_cylindrical_csys " 105 "should be set to true");
109 template <
bool is_ad>
116 if (_local_cylindrical_csys)
118 if (_axis == Axis::X)
120 normal_vector(0) = 0.0;
121 normal_vector(1) = _q_point[_qp](1);
122 normal_vector(2) = _q_point[_qp](2);
123 axial_vector(0) = 1.0;
125 else if (_axis == Axis::Y)
127 normal_vector(0) = _q_point[_qp](0);
128 normal_vector(1) = 0.0;
129 normal_vector(2) = _q_point[_qp](2);
130 axial_vector(1) = 1.0;
134 normal_vector(0) = _q_point[_qp](0);
135 normal_vector(1) = _q_point[_qp](1);
136 normal_vector(2) = 0.0;
137 axial_vector(2) = 1.0;
140 mooseError(
"\nInvalid value for axis parameter provided in HillElastoPlasticityStressUpdate");
143 if (_local_cylindrical_csys)
145 Real nv_norm = normal_vector.
norm();
149 normal_vector /= nv_norm;
152 mooseError(
"The normal vector cannot be a zero vector in " 153 "HillElastoPlasticityStressUpdate");
157 axial_vector /= av_norm;
160 mooseError(
"The axial vector cannot be a zero vector in " 161 "HillElastoPlasticityStressUpdate");
165 normal_vector, axial_vector, _rotation_matrix[_qp],
false);
166 _rotation_matrix_transpose[_qp] = _rotation_matrix[_qp].transpose();
172 template <
bool is_ad>
176 _hardening_variable[_qp] = _hardening_variable_old[_qp];
177 _plasticity_strain[_qp] = _plasticity_strain_old[_qp];
179 if (_local_cylindrical_csys)
181 _rotation_matrix[_qp] = _rotation_matrix_old[_qp];
182 _rotation_matrix_transpose[_qp] = _rotation_matrix_transpose_old[_qp];
188 template <
bool is_ad>
195 _hardening_variable[_qp] = _hardening_variable_old[_qp];
196 _plasticity_strain[_qp] = _plasticity_strain_old[_qp];
197 _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp];
199 _elasticity_eigenvectors[_qp].resize(6, 6);
200 _elasticity_eigenvalues[_qp].resize(6);
202 _b_eigenvectors[_qp].resize(6, 6);
203 _b_eigenvalues[_qp].resize(6);
205 _alpha_matrix[_qp].resize(6, 6);
206 _sigma_tilde[_qp].resize(6);
207 _sigma_tilde_rotated[_qp].resize(6);
210 computeElasticityTensorEigenDecomposition();
212 _yield_condition = 1.0;
213 _yield_condition = -computeResidual(stress_dev, stress, 0.0);
216 template <
bool is_ad>
224 if (_local_cylindrical_csys)
229 ElasticityTensorTools::toVoigtNotation<is_ad>(_anisotropic_elastic_tensor,
elasticity_tensor);
231 const unsigned int dimension = _anisotropic_elastic_tensor.n();
234 for (
unsigned int index_i = 0; index_i < dimension; index_i++)
235 for (
unsigned int index_j = 0; index_j < dimension; index_j++)
238 Eigen::SelfAdjointEigenSolver<AnisotropyMatrixReal> es(
A);
240 auto lambda = es.eigenvalues();
241 auto v = es.eigenvectors();
243 for (
unsigned int index_i = 0; index_i < dimension; index_i++)
244 _elasticity_eigenvalues[_qp](index_i) = lambda(index_i);
246 for (
unsigned int index_i = 0; index_i < dimension; index_i++)
247 for (
unsigned int index_j = 0; index_j < dimension; index_j++)
248 _elasticity_eigenvectors[_qp](index_i, index_j) =
v(index_i, index_j);
252 for (
unsigned int i = 0; i < 6; i++)
254 sqrt_Delta(i, i) = std::sqrt(_elasticity_eigenvalues[_qp](i));
258 _elasticity_eigenvectors[_qp].get_transpose(eigenvectors_elasticity_transpose);
261 b_matrix = _hill_tensor[_qp];
264 b_matrix.right_multiply(_elasticity_eigenvectors[_qp]);
265 b_matrix.right_multiply(sqrt_Delta);
266 b_matrix.left_multiply(eigenvectors_elasticity_transpose);
267 b_matrix.left_multiply(sqrt_Delta);
270 for (
unsigned int index_i = 0; index_i < dimension; index_i++)
271 for (
unsigned int index_j = 0; index_j < dimension; index_j++)
274 if (isBlockDiagonal(B_eigen))
276 Eigen::SelfAdjointEigenSolver<AnisotropyMatrixRealBlock> es_b_left(B_eigen.block<3, 3>(0, 0));
277 Eigen::SelfAdjointEigenSolver<AnisotropyMatrixRealBlock> es_b_right(B_eigen.block<3, 3>(3, 3));
279 auto lambda_b_left = es_b_left.eigenvalues();
280 auto v_b_left = es_b_left.eigenvectors();
282 auto lambda_b_right = es_b_right.eigenvalues();
283 auto v_b_right = es_b_right.eigenvectors();
285 _b_eigenvalues[_qp](0) = lambda_b_left(0);
286 _b_eigenvalues[_qp](1) = lambda_b_left(1);
287 _b_eigenvalues[_qp](2) = lambda_b_left(2);
288 _b_eigenvalues[_qp](3) = lambda_b_right(0);
289 _b_eigenvalues[_qp](4) = lambda_b_right(1);
290 _b_eigenvalues[_qp](5) = lambda_b_right(2);
292 _b_eigenvectors[_qp](0, 0) = v_b_left(0, 0);
293 _b_eigenvectors[_qp](0, 1) = v_b_left(0, 1);
294 _b_eigenvectors[_qp](0, 2) = v_b_left(0, 2);
295 _b_eigenvectors[_qp](1, 0) = v_b_left(1, 0);
296 _b_eigenvectors[_qp](1, 1) = v_b_left(1, 1);
297 _b_eigenvectors[_qp](1, 2) = v_b_left(1, 2);
298 _b_eigenvectors[_qp](2, 0) = v_b_left(2, 0);
299 _b_eigenvectors[_qp](2, 1) = v_b_left(2, 1);
300 _b_eigenvectors[_qp](2, 2) = v_b_left(2, 2);
301 _b_eigenvectors[_qp](3, 3) = v_b_right(0, 0);
302 _b_eigenvectors[_qp](3, 4) = v_b_right(0, 1);
303 _b_eigenvectors[_qp](3, 5) = v_b_right(0, 2);
304 _b_eigenvectors[_qp](4, 3) = v_b_right(1, 0);
305 _b_eigenvectors[_qp](4, 4) = v_b_right(1, 1);
306 _b_eigenvectors[_qp](4, 5) = v_b_right(1, 2);
307 _b_eigenvectors[_qp](5, 3) = v_b_right(2, 0);
308 _b_eigenvectors[_qp](5, 4) = v_b_right(2, 1);
309 _b_eigenvectors[_qp](5, 5) = v_b_right(2, 2);
313 Eigen::SelfAdjointEigenSolver<AnisotropyMatrixReal> es_b(B_eigen);
315 auto lambda_b = es_b.eigenvalues();
316 auto v_b = es_b.eigenvectors();
317 for (
unsigned int index_i = 0; index_i < dimension; index_i++)
318 _b_eigenvalues[_qp](index_i) = lambda_b(index_i);
320 for (
unsigned int index_i = 0; index_i < dimension; index_i++)
321 for (
unsigned int index_j = 0; index_j < dimension; index_j++)
322 _b_eigenvectors[_qp](index_i, index_j) = v_b(index_i, index_j);
325 _alpha_matrix[_qp] = sqrt_Delta;
326 _alpha_matrix[_qp].right_multiply(_b_eigenvectors[_qp]);
327 _alpha_matrix[_qp].left_multiply(_elasticity_eigenvectors[_qp]);
330 template <
bool is_ad>
338 for (
unsigned int i = 0; i < 6; i++)
340 K(i) = _b_eigenvalues[_qp](i) / Utility::pow<2>(1 + delta_gamma * _b_eigenvalues[_qp](i));
342 if (_local_cylindrical_csys)
343 omega +=
K(i) * _sigma_tilde_rotated[_qp](i) * _sigma_tilde_rotated[_qp](i);
345 omega +=
K(i) * _sigma_tilde[_qp](i) * _sigma_tilde[_qp](i);
352 return std::sqrt(omega);
355 template <
bool is_ad>
367 template <
bool is_ad>
376 if (_yield_condition <= 0.0)
381 if (_local_cylindrical_csys)
385 RankTwoScalarTools::VoigtVectorToRankTwoTensor<is_ad>(stress_sigma, stress);
387 stress.rotate(_rotation_matrix_transpose[_qp]);
390 RankTwoScalarTools::RankTwoTensorToVoigtVector<is_ad>(stress, stress_sigma_rotated);
394 alpha_temp_rotated.lu_solve(stress_sigma_rotated, stress_tilde_rotated);
397 _sigma_tilde_rotated[_qp] = stress_tilde_rotated;
398 omega = computeOmega(delta_gamma, stress_tilde_rotated);
406 alpha_temp.lu_solve(stress_sigma, stress_tilde);
409 _sigma_tilde[_qp] = stress_tilde;
410 omega = computeOmega(delta_gamma, stress_tilde);
414 _hardening_variable[_qp] = computeHardeningValue(delta_gamma, omega);
421 _hardening_constant *
std::pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent) +
425 residual = s_y / omega - 1.0;
430 template <
bool is_ad>
438 if (_yield_condition <= 0.0)
442 _hardening_derivative = computeHardeningDerivative();
446 _hardening_constant *
std::pow(hardeningVariable + 1.0e-30, _hardening_exponent) +
453 computeDeltaDerivatives(delta_gamma, stress_sigma, sy_alpha, omega, omega_gamma, sy_gamma);
454 GenericReal<is_ad> residual_derivative = 1 / omega * (sy_gamma - 1 / omega * omega_gamma * sy);
456 return residual_derivative;
459 template <
bool is_ad>
474 if (_local_cylindrical_csys)
475 omega = computeOmega(delta_gamma, _sigma_tilde_rotated[_qp]);
477 omega = computeOmega(delta_gamma, _sigma_tilde[_qp]);
480 for (
unsigned int i = 0; i < 6; i++)
481 K(i) = _b_eigenvalues[_qp](i) / Utility::pow<2>(1 + delta_gamma * _b_eigenvalues[_qp](i));
483 for (
unsigned int i = 0; i < 6; i++)
485 -2.0 * _b_eigenvalues[_qp](i) *
K(i) / (1 + _b_eigenvalues[_qp](i) * delta_gamma);
487 for (
unsigned int i = 0; i < 6; i++)
489 if (_local_cylindrical_csys)
490 omega_gamma += K_deltaGamma(i) * _sigma_tilde_rotated[_qp](i) * _sigma_tilde_rotated[_qp](i);
492 omega_gamma += K_deltaGamma(i) * _sigma_tilde[_qp](i) * _sigma_tilde[_qp](i);
495 omega_gamma /= 4.0 * omega;
496 sy_gamma = 2.0 * sy_alpha * (omega + delta_gamma * omega_gamma);
499 template <
bool is_ad>
504 return _hardening_variable_old[_qp] + 2.0 * delta_gamma * omega;
507 template <
bool is_ad>
511 return _hardening_constant * _hardening_exponent *
513 std::pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent - 1));
516 template <
bool is_ad>
529 if (_local_cylindrical_csys)
532 stress_rotated.rotate(_rotation_matrix_transpose[_qp]);
534 RankTwoScalarTools::RankTwoTensorToVoigtVector<is_ad>(stress_rotated, stress_vector);
538 RankTwoScalarTools::RankTwoTensorToVoigtVector<is_ad>(stress, stress_vector);
541 _hill_tensor[_qp].vector_mult(hill_stress, stress_vector);
542 hill_stress.scale(delta_gamma);
543 inelasticStrainIncrement_vector = hill_stress;
545 inelasticStrainIncrement(0, 0) = inelasticStrainIncrement_vector(0);
546 inelasticStrainIncrement(1, 1) = inelasticStrainIncrement_vector(1);
547 inelasticStrainIncrement(2, 2) = inelasticStrainIncrement_vector(2);
548 inelasticStrainIncrement(0, 1) = inelasticStrainIncrement(1, 0) =
549 inelasticStrainIncrement_vector(3) / 2.0;
550 inelasticStrainIncrement(1, 2) = inelasticStrainIncrement(2, 1) =
551 inelasticStrainIncrement_vector(4) / 2.0;
552 inelasticStrainIncrement(0, 2) = inelasticStrainIncrement(2, 0) =
553 inelasticStrainIncrement_vector(5) / 2.0;
555 if (_local_cylindrical_csys)
556 inelasticStrainIncrement.rotate(_rotation_matrix[_qp]);
560 _hill_tensor[_qp].vector_mult(Mepsilon, inelasticStrainIncrement_vector);
561 GenericReal<is_ad> eq_plastic_strain_inc = Mepsilon.dot(inelasticStrainIncrement_vector);
563 if (eq_plastic_strain_inc > 0.0)
564 eq_plastic_strain_inc = std::sqrt(eq_plastic_strain_inc);
566 _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp] + eq_plastic_strain_inc;
569 inelasticStrainIncrement, stress, stress_dev, delta_gamma);
572 template <
bool is_ad>
586 if (_yield_condition <= 0.0)
591 for (
unsigned int i = 0; i < 6; i++)
592 inv_matrix(i, i) = 1 / (1 + delta_gamma * _b_eigenvalues[_qp](i));
594 _alpha_matrix[_qp].right_multiply(inv_matrix);
597 if (_local_cylindrical_csys)
598 _alpha_matrix[_qp].vector_mult(stress_output, _sigma_tilde_rotated[_qp]);
600 _alpha_matrix[_qp].vector_mult(stress_output, _sigma_tilde[_qp]);
602 RankTwoScalarTools::VoigtVectorToRankTwoTensor<is_ad>(stress_output, stress_new);
604 if (_local_cylindrical_csys)
605 stress_new.rotate(_rotation_matrix[_qp]);
608 template <
bool is_ad>
614 mooseError(
"computeStrainEnergyRateDensity not implemented for anisotropic plasticity.");
Moose::GenericType< Real, is_ad > GenericReal
auto norm() const -> decltype(std::norm(Real()))
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void computeElasticityTensorEigenDecomposition()
Compute eigendecomposition of element-wise elasticity tensor.
static InputParameters validParams()
virtual void propagateQpStatefulProperties() override
void mooseError(Args &&... args)
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.
Eigen::Matrix< Real, 6, 6 > AnisotropyMatrixReal
static const std::string K
This class uses the stress update material in an anisotropic return mapping.
const bool _local_cylindrical_csys
Moose::GenericType< DenseVector< Real >, is_ad > GenericDenseVector
Moose::GenericType< RankFourTensor, is_ad > GenericRankFourTensor
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)
virtual GenericReal< is_ad > computeResidual(const GenericDenseVector< is_ad > &effective_trial_stress, const GenericDenseVector< is_ad > &stress_new, const GenericReal< is_ad > &scalar) override
GenericReal< is_ad > computeHardeningValue(const GenericReal< is_ad > &scalar, const GenericReal< is_ad > &omega)
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
HillElastoPlasticityStressUpdateTempl(const InputParameters ¶meters)
typename GenericMaterialPropertyStruct< T, is_ad >::type GenericMaterialProperty
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 void initQpStatefulProperties() override
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.
registerMooseObject("SolidMechanicsApp", ADHillElastoPlasticityStressUpdate)
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.
Real computeHardeningDerivative()
static const std::string Z
virtual void computeStressInitialize(const GenericDenseVector< is_ad > &stress_dev, const GenericDenseVector< is_ad > &stress, const GenericRankFourTensor< is_ad > &elasticity_tensor) override
virtual void initQpStatefulProperties() override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
virtual void propagateQpStatefulProperties() override
This class provides baseline functionality for anisotropic (Hill-like) plasticity models based on the...
void paramError(const std::string ¶m, Args... args) const
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)
MooseUnits pow(const MooseUnits &, int)
Moose::GenericType< DenseMatrix< Real >, is_ad > GenericDenseMatrix
Moose::GenericType< RankTwoTensor, is_ad > GenericRankTwoTensor
virtual Real computeStrainEnergyRateDensity(const GenericMaterialProperty< RankTwoTensor, is_ad > &stress, const GenericMaterialProperty< RankTwoTensor, is_ad > &strain_rate) override
static InputParameters validParams()