LCOV - code coverage report
Current view: top level - src/materials - HillElastoPlasticityStressUpdate.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #31613 (c7d555) with base 7323e9 Lines: 272 290 93.8 %
Date: 2025-11-06 14:18:25 Functions: 14 32 43.8 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      10             : #include "HillElastoPlasticityStressUpdate.h"
      11             : #include "RankTwoScalarTools.h"
      12             : #include "ElasticityTensorTools.h"
      13             : 
      14             : registerMooseObject("SolidMechanicsApp", ADHillElastoPlasticityStressUpdate);
      15             : registerMooseObject("SolidMechanicsApp", HillElastoPlasticityStressUpdate);
      16             : 
      17             : template <bool is_ad>
      18             : InputParameters
      19         112 : HillElastoPlasticityStressUpdateTempl<is_ad>::validParams()
      20             : {
      21         112 :   InputParameters params = AnisotropicReturnPlasticityStressUpdateBaseTempl<is_ad>::validParams();
      22         112 :   params.addClassDescription(
      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.");
      26             : 
      27         224 :   params.addRequiredParam<Real>("hardening_constant",
      28             :                                 "Hardening constant (H) for anisotropic plasticity");
      29         224 :   params.addParam<Real>(
      30         224 :       "hardening_exponent", 1.0, "Hardening exponent (n) for anisotropic plasticity");
      31         224 :   params.addRequiredParam<Real>("yield_stress",
      32             :                                 "Yield stress (constant value) for anisotropic plasticity");
      33         224 :   params.addParam<bool>(
      34             :       "local_cylindrical_csys",
      35         224 :       false,
      36             :       "Compute inelastic strain increment in local cylindrical coordinate system");
      37             : 
      38         224 :   params.addParam<MooseEnum>("axis",
      39         336 :                              MooseEnum("x y z", "y"),
      40             :                              "The axis of cylindrical component about which to rotate when "
      41             :                              "computing inelastic strain increment in local coordinate system");
      42             : 
      43         112 :   return params;
      44           0 : }
      45             : 
      46             : template <bool is_ad>
      47          84 : HillElastoPlasticityStressUpdateTempl<is_ad>::HillElastoPlasticityStressUpdateTempl(
      48             :     const InputParameters & parameters)
      49             :   : AnisotropicReturnPlasticityStressUpdateBaseTempl<is_ad>(parameters),
      50         168 :     _qsigma(0.0),
      51          84 :     _eigenvalues_hill(6),
      52          84 :     _eigenvectors_hill(6, 6),
      53          84 :     _anisotropic_elastic_tensor(6, 6),
      54          84 :     _elasticity_tensor_name(this->_base_name + "elasticity_tensor"),
      55          84 :     _elasticity_tensor(
      56          84 :         this->template getGenericMaterialProperty<RankFourTensor, is_ad>(_elasticity_tensor_name)),
      57         168 :     _hardening_constant(this->template getParam<Real>("hardening_constant")),
      58         168 :     _hardening_exponent(this->template getParam<Real>("hardening_exponent")),
      59         168 :     _hardening_variable(this->template declareGenericProperty<Real, is_ad>(this->_base_name +
      60             :                                                                            "hardening_variable")),
      61          84 :     _hardening_variable_old(
      62          84 :         this->template getMaterialPropertyOld<Real>(this->_base_name + "hardening_variable")),
      63         168 :     _elasticity_eigenvectors(this->template declareGenericProperty<DenseMatrix<Real>, is_ad>(
      64             :         this->_base_name + "elasticity_eigenvectors")),
      65         168 :     _elasticity_eigenvalues(this->template declareGenericProperty<DenseVector<Real>, is_ad>(
      66             :         this->_base_name + "elasticity_eigenvalues")),
      67         168 :     _b_eigenvectors(this->template declareGenericProperty<DenseMatrix<Real>, is_ad>(
      68             :         this->_base_name + "b_eigenvectors")),
      69         168 :     _b_eigenvalues(this->template declareGenericProperty<DenseVector<Real>, is_ad>(
      70             :         this->_base_name + "b_eigenvalues")),
      71         168 :     _alpha_matrix(this->template declareGenericProperty<DenseMatrix<Real>, is_ad>(this->_base_name +
      72             :                                                                                   "alpha_matrix")),
      73         168 :     _sigma_tilde(this->template declareGenericProperty<DenseVector<Real>, is_ad>(this->_base_name +
      74             :                                                                                  "sigma_tilde")),
      75         168 :     _sigma_tilde_rotated(this->template declareGenericProperty<DenseVector<Real>, is_ad>(
      76             :         this->_base_name + "sigma_tilde_rotated")),
      77          84 :     _hardening_derivative(0.0),
      78          84 :     _yield_condition(1.0),
      79         168 :     _yield_stress(this->template getParam<Real>("yield_stress")),
      80         168 :     _hill_tensor(this->template getMaterialPropertyByName<DenseMatrix<Real>>(this->_base_name +
      81             :                                                                              "hill_tensor")),
      82          84 :     _rotation_matrix(
      83          84 :         this->template declareProperty<RankTwoTensor>(this->_base_name + "rotation_matrix")),
      84          84 :     _rotation_matrix_transpose(this->template declareProperty<RankTwoTensor>(
      85             :         this->_base_name + "rotation_matrix_transpose")),
      86          84 :     _rotation_matrix_old(
      87          84 :         this->template getMaterialPropertyOld<RankTwoTensor>(this->_base_name + "rotation_matrix")),
      88         168 :     _rotation_matrix_transpose_old(this->template getMaterialPropertyOld<RankTwoTensor>(
      89             :         this->_base_name + "rotation_matrix_transpose")),
      90         168 :     _local_cylindrical_csys(this->template getParam<bool>("local_cylindrical_csys")),
      91         252 :     _axis(this->template getParam<MooseEnum>("axis").template getEnum<Axis>())
      92             : {
      93         210 :   if (_local_cylindrical_csys && !parameters.isParamSetByUser("axis"))
      94             :   {
      95           0 :     this->paramError(
      96             :         "local_cylindrical_csys",
      97             :         "\nIf parameter local_cylindrical_csys is provided then parameter axis should be also "
      98             :         "provided.");
      99             :   }
     100             : 
     101         105 :   if (!_local_cylindrical_csys && parameters.isParamSetByUser("axis"))
     102             :   {
     103           0 :     this->paramError("axis",
     104             :                      "\nIf parameter axis is provided then the parameter local_cylindrical_csys "
     105             :                      "should be set to true");
     106             :   }
     107          84 : }
     108             : 
     109             : template <bool is_ad>
     110             : void
     111        6800 : HillElastoPlasticityStressUpdateTempl<is_ad>::initQpStatefulProperties()
     112             : {
     113             :   RealVectorValue normal_vector(0, 0, 0);
     114             :   RealVectorValue axial_vector(0, 0, 0);
     115             : 
     116        6800 :   if (_local_cylindrical_csys)
     117             :   {
     118        3600 :     if (_axis == Axis::X)
     119             :     {
     120             :       normal_vector(0) = 0.0;
     121        1200 :       normal_vector(1) = _q_point[_qp](1);
     122        1200 :       normal_vector(2) = _q_point[_qp](2);
     123        1200 :       axial_vector(0) = 1.0;
     124             :     }
     125        2400 :     else if (_axis == Axis::Y)
     126             :     {
     127        1200 :       normal_vector(0) = _q_point[_qp](0);
     128             :       normal_vector(1) = 0.0;
     129        1200 :       normal_vector(2) = _q_point[_qp](2);
     130        1200 :       axial_vector(1) = 1.0;
     131             :     }
     132        1200 :     else if (_axis == Axis::Z)
     133             :     {
     134        1200 :       normal_vector(0) = _q_point[_qp](0);
     135        1200 :       normal_vector(1) = _q_point[_qp](1);
     136             :       normal_vector(2) = 0.0;
     137        1200 :       axial_vector(2) = 1.0;
     138             :     }
     139             :     else
     140           0 :       mooseError("\nInvalid value for axis parameter provided in HillElastoPlasticityStressUpdate");
     141             :   }
     142             : 
     143        6800 :   if (_local_cylindrical_csys)
     144             :   {
     145        3600 :     Real nv_norm = normal_vector.norm();
     146        3600 :     Real av_norm = axial_vector.norm();
     147             : 
     148        3600 :     if (!(MooseUtils::absoluteFuzzyEqual(nv_norm, 0.0)))
     149             :       normal_vector /= nv_norm;
     150             :     else
     151             :     {
     152           0 :       mooseError("The normal vector cannot be a zero vector in "
     153             :                  "HillElastoPlasticityStressUpdate");
     154             :     }
     155             : 
     156        3600 :     if (!(MooseUtils::absoluteFuzzyEqual(av_norm, 0.0)))
     157             :       axial_vector /= av_norm;
     158             :     else
     159             :     {
     160           0 :       mooseError("The axial vector cannot be a zero vector in "
     161             :                  "HillElastoPlasticityStressUpdate");
     162             :     }
     163             : 
     164        3600 :     RankTwoScalarTools::setRotationMatrix(
     165        3600 :         normal_vector, axial_vector, _rotation_matrix[_qp], false);
     166        3600 :     _rotation_matrix_transpose[_qp] = _rotation_matrix[_qp].transpose();
     167             :   }
     168             : 
     169        6800 :   AnisotropicReturnPlasticityStressUpdateBaseTempl<is_ad>::initQpStatefulProperties();
     170        6800 : }
     171             : 
     172             : template <bool is_ad>
     173             : void
     174           0 : HillElastoPlasticityStressUpdateTempl<is_ad>::propagateQpStatefulProperties()
     175             : {
     176           0 :   _hardening_variable[_qp] = _hardening_variable_old[_qp];
     177           0 :   _plasticity_strain[_qp] = _plasticity_strain_old[_qp];
     178             : 
     179           0 :   if (_local_cylindrical_csys)
     180             :   {
     181           0 :     _rotation_matrix[_qp] = _rotation_matrix_old[_qp];
     182           0 :     _rotation_matrix_transpose[_qp] = _rotation_matrix_transpose_old[_qp];
     183             :   }
     184             : 
     185           0 :   AnisotropicReturnPlasticityStressUpdateBaseTempl<is_ad>::propagateQpStatefulProperties();
     186           0 : }
     187             : 
     188             : template <bool is_ad>
     189             : void
     190      135560 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeStressInitialize(
     191             :     const GenericDenseVector<is_ad> & stress_dev,
     192             :     const GenericDenseVector<is_ad> & stress,
     193             :     const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/)
     194             : {
     195      135560 :   _hardening_variable[_qp] = _hardening_variable_old[_qp];
     196      135560 :   _plasticity_strain[_qp] = _plasticity_strain_old[_qp];
     197      135560 :   _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp];
     198             : 
     199      135560 :   _elasticity_eigenvectors[_qp].resize(6, 6);
     200      135560 :   _elasticity_eigenvalues[_qp].resize(6);
     201             : 
     202      135560 :   _b_eigenvectors[_qp].resize(6, 6);
     203      135560 :   _b_eigenvalues[_qp].resize(6);
     204             : 
     205      135560 :   _alpha_matrix[_qp].resize(6, 6);
     206      135560 :   _sigma_tilde[_qp].resize(6);
     207      135560 :   _sigma_tilde_rotated[_qp].resize(6);
     208             : 
     209             :   // Algebra needed for the generalized return mapping of anisotropic elastoplasticity
     210      135560 :   computeElasticityTensorEigenDecomposition();
     211             : 
     212      135560 :   _yield_condition = 1.0; // Some positive value
     213      135560 :   _yield_condition = -computeResidual(stress_dev, stress, 0.0);
     214      135560 : }
     215             : 
     216             : template <bool is_ad>
     217             : void
     218      135560 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeElasticityTensorEigenDecomposition()
     219             : {
     220             :   // Helper method to compute qp matrices required for the elasto-plasticity algorithm.
     221             :   using std::sqrt;
     222             : 
     223      135560 :   GenericRankFourTensor<is_ad> elasticity_tensor = _elasticity_tensor[_qp];
     224             : 
     225      135560 :   if (_local_cylindrical_csys)
     226             :   {
     227       59400 :     elasticity_tensor.rotate(_rotation_matrix_transpose[_qp]);
     228             :   }
     229             : 
     230      135560 :   ElasticityTensorTools::toVoigtNotation<is_ad>(_anisotropic_elastic_tensor, elasticity_tensor);
     231             : 
     232             :   const unsigned int dimension = _anisotropic_elastic_tensor.n();
     233             : 
     234             :   AnisotropyMatrixReal A = AnisotropyMatrixReal::Zero();
     235      948920 :   for (unsigned int index_i = 0; index_i < dimension; index_i++)
     236     5693520 :     for (unsigned int index_j = 0; index_j < dimension; index_j++)
     237     4880160 :       A(index_i, index_j) = MetaPhysicL::raw_value(_anisotropic_elastic_tensor(index_i, index_j));
     238             : 
     239             :   Eigen::SelfAdjointEigenSolver<AnisotropyMatrixReal> es(A);
     240             : 
     241             :   auto lambda = es.eigenvalues();
     242             :   auto v = es.eigenvectors();
     243             : 
     244      948920 :   for (unsigned int index_i = 0; index_i < dimension; index_i++)
     245      813360 :     _elasticity_eigenvalues[_qp](index_i) = lambda(index_i);
     246             : 
     247      948920 :   for (unsigned int index_i = 0; index_i < dimension; index_i++)
     248     5693520 :     for (unsigned int index_j = 0; index_j < dimension; index_j++)
     249     4880160 :       _elasticity_eigenvectors[_qp](index_i, index_j) = v(index_i, index_j);
     250             : 
     251             :   // Compute sqrt(Delta_c) * QcT * A * Qc * sqrt(Delta_c)
     252      135560 :   GenericDenseMatrix<is_ad> sqrt_Delta(6, 6);
     253      948920 :   for (unsigned int i = 0; i < 6; i++)
     254             :   {
     255      813360 :     sqrt_Delta(i, i) = sqrt(_elasticity_eigenvalues[_qp](i));
     256             :   }
     257             : 
     258      135560 :   GenericDenseMatrix<is_ad> eigenvectors_elasticity_transpose(6, 6);
     259      135560 :   _elasticity_eigenvectors[_qp].get_transpose(eigenvectors_elasticity_transpose);
     260             : 
     261      135560 :   GenericDenseMatrix<is_ad> b_matrix(6, 6);
     262      135560 :   b_matrix = _hill_tensor[_qp];
     263             : 
     264             :   // Right multiply by matrix of eigenvectors transpose
     265      135560 :   b_matrix.right_multiply(_elasticity_eigenvectors[_qp]);
     266      135560 :   b_matrix.right_multiply(sqrt_Delta);
     267      135560 :   b_matrix.left_multiply(eigenvectors_elasticity_transpose);
     268      135560 :   b_matrix.left_multiply(sqrt_Delta);
     269             : 
     270             :   AnisotropyMatrixReal B_eigen = AnisotropyMatrixReal::Zero();
     271      948920 :   for (unsigned int index_i = 0; index_i < dimension; index_i++)
     272     5693520 :     for (unsigned int index_j = 0; index_j < dimension; index_j++)
     273     4880160 :       B_eigen(index_i, index_j) = MetaPhysicL::raw_value(b_matrix(index_i, index_j));
     274             : 
     275      135560 :   if (isBlockDiagonal(B_eigen))
     276             :   {
     277        6400 :     Eigen::SelfAdjointEigenSolver<AnisotropyMatrixRealBlock> es_b_left(B_eigen.block<3, 3>(0, 0));
     278        6400 :     Eigen::SelfAdjointEigenSolver<AnisotropyMatrixRealBlock> es_b_right(B_eigen.block<3, 3>(3, 3));
     279             : 
     280             :     auto lambda_b_left = es_b_left.eigenvalues();
     281             :     auto v_b_left = es_b_left.eigenvectors();
     282             : 
     283             :     auto lambda_b_right = es_b_right.eigenvalues();
     284             :     auto v_b_right = es_b_right.eigenvectors();
     285             : 
     286        6400 :     _b_eigenvalues[_qp](0) = lambda_b_left(0);
     287        6400 :     _b_eigenvalues[_qp](1) = lambda_b_left(1);
     288        6400 :     _b_eigenvalues[_qp](2) = lambda_b_left(2);
     289        6400 :     _b_eigenvalues[_qp](3) = lambda_b_right(0);
     290        6400 :     _b_eigenvalues[_qp](4) = lambda_b_right(1);
     291        6400 :     _b_eigenvalues[_qp](5) = lambda_b_right(2);
     292             : 
     293        6400 :     _b_eigenvectors[_qp](0, 0) = v_b_left(0, 0);
     294        6400 :     _b_eigenvectors[_qp](0, 1) = v_b_left(0, 1);
     295        6400 :     _b_eigenvectors[_qp](0, 2) = v_b_left(0, 2);
     296        6400 :     _b_eigenvectors[_qp](1, 0) = v_b_left(1, 0);
     297        6400 :     _b_eigenvectors[_qp](1, 1) = v_b_left(1, 1);
     298        6400 :     _b_eigenvectors[_qp](1, 2) = v_b_left(1, 2);
     299        6400 :     _b_eigenvectors[_qp](2, 0) = v_b_left(2, 0);
     300        6400 :     _b_eigenvectors[_qp](2, 1) = v_b_left(2, 1);
     301        6400 :     _b_eigenvectors[_qp](2, 2) = v_b_left(2, 2);
     302        6400 :     _b_eigenvectors[_qp](3, 3) = v_b_right(0, 0);
     303        6400 :     _b_eigenvectors[_qp](3, 4) = v_b_right(0, 1);
     304        6400 :     _b_eigenvectors[_qp](3, 5) = v_b_right(0, 2);
     305        6400 :     _b_eigenvectors[_qp](4, 3) = v_b_right(1, 0);
     306        6400 :     _b_eigenvectors[_qp](4, 4) = v_b_right(1, 1);
     307        6400 :     _b_eigenvectors[_qp](4, 5) = v_b_right(1, 2);
     308        6400 :     _b_eigenvectors[_qp](5, 3) = v_b_right(2, 0);
     309        6400 :     _b_eigenvectors[_qp](5, 4) = v_b_right(2, 1);
     310        6400 :     _b_eigenvectors[_qp](5, 5) = v_b_right(2, 2);
     311             :   }
     312             :   else
     313             :   {
     314             :     Eigen::SelfAdjointEigenSolver<AnisotropyMatrixReal> es_b(B_eigen);
     315             : 
     316             :     auto lambda_b = es_b.eigenvalues();
     317             :     auto v_b = es_b.eigenvectors();
     318      904120 :     for (unsigned int index_i = 0; index_i < dimension; index_i++)
     319      774960 :       _b_eigenvalues[_qp](index_i) = lambda_b(index_i);
     320             : 
     321      904120 :     for (unsigned int index_i = 0; index_i < dimension; index_i++)
     322     5424720 :       for (unsigned int index_j = 0; index_j < dimension; index_j++)
     323     4649760 :         _b_eigenvectors[_qp](index_i, index_j) = v_b(index_i, index_j);
     324             :   }
     325             : 
     326      135560 :   _alpha_matrix[_qp] = sqrt_Delta;
     327      135560 :   _alpha_matrix[_qp].right_multiply(_b_eigenvectors[_qp]);
     328      135560 :   _alpha_matrix[_qp].left_multiply(_elasticity_eigenvectors[_qp]);
     329      135560 : }
     330             : 
     331             : template <bool is_ad>
     332             : GenericReal<is_ad>
     333      391548 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeOmega(
     334             :     const GenericReal<is_ad> & delta_gamma, const GenericDenseVector<is_ad> & /*stress_trial*/)
     335             : {
     336      391548 :   GenericDenseVector<is_ad> K(6);
     337      391548 :   GenericReal<is_ad> omega = 0.0;
     338             : 
     339     2740836 :   for (unsigned int i = 0; i < 6; i++)
     340             :   {
     341     9397152 :     K(i) = _b_eigenvalues[_qp](i) / Utility::pow<2>(1 + delta_gamma * _b_eigenvalues[_qp](i));
     342             : 
     343     2349288 :     if (_local_cylindrical_csys)
     344     3166560 :       omega += K(i) * _sigma_tilde_rotated[_qp](i) * _sigma_tilde_rotated[_qp](i);
     345             :     else
     346     1532016 :       omega += K(i) * _sigma_tilde[_qp](i) * _sigma_tilde[_qp](i);
     347             :   }
     348      391548 :   omega *= 0.5;
     349             : 
     350      391548 :   if (omega == 0.0)
     351       14680 :     omega = 1.0e-36;
     352             : 
     353             :   using std::sqrt;
     354      783096 :   return sqrt(omega);
     355             : }
     356             : 
     357             : template <bool is_ad>
     358             : Real
     359      187232 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeReferenceResidual(
     360             :     const GenericDenseVector<is_ad> & /*effective_trial_stress*/,
     361             :     const GenericDenseVector<is_ad> & /*stress_new*/,
     362             :     const GenericReal<is_ad> & /*residual*/,
     363             :     const GenericReal<is_ad> & /*scalar_effective_inelastic_strain*/)
     364             : {
     365             :   // Equation is already normalized.
     366      187232 :   return 1.0;
     367             : }
     368             : 
     369             : template <bool is_ad>
     370             : GenericReal<is_ad>
     371      322792 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeResidual(
     372             :     const GenericDenseVector<is_ad> & /*stress_dev*/,
     373             :     const GenericDenseVector<is_ad> & stress_sigma,
     374             :     const GenericReal<is_ad> & delta_gamma)
     375             : {
     376             :   using std::pow;
     377             : 
     378             :   // If in elastic regime, just return
     379      322792 :   if (_yield_condition <= 0.0)
     380       63948 :     return 0.0;
     381             : 
     382             :   GenericReal<is_ad> omega;
     383             : 
     384      258844 :   if (_local_cylindrical_csys)
     385             :   {
     386             :     // Get stress_tilde_rotated
     387      161640 :     GenericRankTwoTensor<is_ad> stress;
     388      161640 :     RankTwoScalarTools::VoigtVectorToRankTwoTensor<is_ad>(stress_sigma, stress);
     389             : 
     390      161640 :     stress.rotate(_rotation_matrix_transpose[_qp]);
     391             : 
     392      161640 :     GenericDenseVector<is_ad> stress_sigma_rotated(6);
     393      161640 :     RankTwoScalarTools::RankTwoTensorToVoigtVector<is_ad>(stress, stress_sigma_rotated);
     394             : 
     395      161640 :     GenericDenseVector<is_ad> stress_tilde_rotated(6);
     396      161640 :     GenericDenseMatrix<is_ad> alpha_temp_rotated(_alpha_matrix[_qp]);
     397      161640 :     alpha_temp_rotated.lu_solve(stress_sigma_rotated, stress_tilde_rotated);
     398             : 
     399             :     // Material property used in computeStressFinalize
     400      161640 :     _sigma_tilde_rotated[_qp] = stress_tilde_rotated;
     401      161640 :     omega = computeOmega(delta_gamma, stress_tilde_rotated);
     402      161640 :   }
     403             : 
     404             :   else
     405             :   {
     406             :     // Get stress_tilde
     407       97204 :     GenericDenseVector<is_ad> stress_tilde(6);
     408       97204 :     GenericDenseMatrix<is_ad> alpha_temp(_alpha_matrix[_qp]);
     409       97204 :     alpha_temp.lu_solve(stress_sigma, stress_tilde);
     410             : 
     411             :     // Material property used in computeStressFinalize
     412       97204 :     _sigma_tilde[_qp] = stress_tilde;
     413       97204 :     omega = computeOmega(delta_gamma, stress_tilde);
     414       97204 :   }
     415             : 
     416             :   // Hardening variable is \alpha isotropic hardening for now.
     417      258844 :   _hardening_variable[_qp] = computeHardeningValue(delta_gamma, omega);
     418             : 
     419             :   // A small value of 1.0e-30 is added to the hardening variable to avoid numerical issues
     420             :   // related to hardening variable becoming negative early in the iteration leading to non-
     421             :   // convergence. Note that pow(x,n) requires x to be positive if n is less than 1.
     422             : 
     423      258844 :   GenericReal<is_ad> s_y =
     424      258844 :       _hardening_constant * pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent) +
     425      258844 :       _yield_stress;
     426             : 
     427      258844 :   GenericReal<is_ad> residual = 0.0;
     428      258844 :   residual = s_y / omega - 1.0;
     429             : 
     430      258844 :   return residual;
     431             : }
     432             : 
     433             : template <bool is_ad>
     434             : GenericReal<is_ad>
     435       66352 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeDerivative(
     436             :     const GenericDenseVector<is_ad> & /*stress_dev*/,
     437             :     const GenericDenseVector<is_ad> & stress_sigma,
     438             :     const GenericReal<is_ad> & delta_gamma)
     439             : {
     440             :   using std::pow;
     441             : 
     442             :   // If in elastic regime, return unit derivative
     443       66352 :   if (_yield_condition <= 0.0)
     444           0 :     return 1.0;
     445             : 
     446       66352 :   GenericReal<is_ad> omega = computeOmega(delta_gamma, stress_sigma);
     447       66352 :   _hardening_derivative = computeHardeningDerivative();
     448             : 
     449       66352 :   GenericReal<is_ad> hardeningVariable = computeHardeningValue(delta_gamma, omega);
     450       66352 :   GenericReal<is_ad> sy =
     451      132704 :       _hardening_constant * pow(hardeningVariable + 1.0e-30, _hardening_exponent) + _yield_stress;
     452       66352 :   GenericReal<is_ad> sy_alpha = _hardening_derivative;
     453             : 
     454             :   GenericReal<is_ad> omega_gamma;
     455             :   GenericReal<is_ad> sy_gamma;
     456             : 
     457       66352 :   computeDeltaDerivatives(delta_gamma, stress_sigma, sy_alpha, omega, omega_gamma, sy_gamma);
     458      132704 :   GenericReal<is_ad> residual_derivative = 1 / omega * (sy_gamma - 1 / omega * omega_gamma * sy);
     459             : 
     460       66352 :   return residual_derivative;
     461             : }
     462             : 
     463             : template <bool is_ad>
     464             : void
     465       66352 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeDeltaDerivatives(
     466             :     const GenericReal<is_ad> & delta_gamma,
     467             :     const GenericDenseVector<is_ad> & /*stress_trial*/,
     468             :     const GenericReal<is_ad> & sy_alpha,
     469             :     GenericReal<is_ad> & omega,
     470             :     GenericReal<is_ad> & omega_gamma,
     471             :     GenericReal<is_ad> & sy_gamma)
     472             : {
     473       66352 :   omega_gamma = 0.0;
     474       66352 :   sy_gamma = 0.0;
     475             : 
     476       66352 :   GenericDenseVector<is_ad> K_deltaGamma(6);
     477             : 
     478       66352 :   if (_local_cylindrical_csys)
     479       51120 :     omega = computeOmega(delta_gamma, _sigma_tilde_rotated[_qp]);
     480             :   else
     481       15232 :     omega = computeOmega(delta_gamma, _sigma_tilde[_qp]);
     482             : 
     483       66352 :   GenericDenseVector<is_ad> K(6);
     484      464464 :   for (unsigned int i = 0; i < 6; i++)
     485     1592448 :     K(i) = _b_eigenvalues[_qp](i) / Utility::pow<2>(1 + delta_gamma * _b_eigenvalues[_qp](i));
     486             : 
     487      464464 :   for (unsigned int i = 0; i < 6; i++)
     488      398112 :     K_deltaGamma(i) =
     489     1592448 :         -2.0 * _b_eigenvalues[_qp](i) * K(i) / (1 + _b_eigenvalues[_qp](i) * delta_gamma);
     490             : 
     491      464464 :   for (unsigned int i = 0; i < 6; i++)
     492             :   {
     493      398112 :     if (_local_cylindrical_csys)
     494      613440 :       omega_gamma += K_deltaGamma(i) * _sigma_tilde_rotated[_qp](i) * _sigma_tilde_rotated[_qp](i);
     495             :     else
     496      182784 :       omega_gamma += K_deltaGamma(i) * _sigma_tilde[_qp](i) * _sigma_tilde[_qp](i);
     497             :   }
     498             : 
     499      132704 :   omega_gamma /= 4.0 * omega;
     500      132704 :   sy_gamma = 2.0 * sy_alpha * (omega + delta_gamma * omega_gamma);
     501       66352 : }
     502             : 
     503             : template <bool is_ad>
     504             : GenericReal<is_ad>
     505      325196 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeHardeningValue(
     506             :     const GenericReal<is_ad> & delta_gamma, const GenericReal<is_ad> & omega)
     507             : {
     508      650392 :   return _hardening_variable_old[_qp] + 2.0 * delta_gamma * omega;
     509             : }
     510             : 
     511             : template <bool is_ad>
     512             : Real
     513       66352 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeHardeningDerivative()
     514             : {
     515             :   using std::pow;
     516       66352 :   return _hardening_constant * _hardening_exponent *
     517       66352 :          MetaPhysicL::raw_value(pow(_hardening_variable[_qp] + 1.0e-30, _hardening_exponent - 1));
     518             : }
     519             : 
     520             : template <bool is_ad>
     521             : void
     522      120880 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeStrainFinalize(
     523             :     GenericRankTwoTensor<is_ad> & inelasticStrainIncrement,
     524             :     const GenericRankTwoTensor<is_ad> & stress,
     525             :     const GenericDenseVector<is_ad> & stress_dev,
     526             :     const GenericReal<is_ad> & delta_gamma)
     527             : {
     528             :   using std::sqrt;
     529             : 
     530             :   // e^P = delta_gamma * hill_tensor * stress
     531      120880 :   GenericDenseVector<is_ad> inelasticStrainIncrement_vector(6);
     532      120880 :   GenericDenseVector<is_ad> hill_stress(6);
     533      120880 :   GenericDenseVector<is_ad> stress_vector(6);
     534             : 
     535      120880 :   if (_local_cylindrical_csys)
     536             :   {
     537           0 :     GenericRankTwoTensor<is_ad> stress_rotated(stress);
     538       51120 :     stress_rotated.rotate(_rotation_matrix_transpose[_qp]);
     539             : 
     540       51120 :     RankTwoScalarTools::RankTwoTensorToVoigtVector<is_ad>(stress_rotated, stress_vector);
     541             :   }
     542             :   else
     543             :   {
     544       69760 :     RankTwoScalarTools::RankTwoTensorToVoigtVector<is_ad>(stress, stress_vector);
     545             :   }
     546             : 
     547      120880 :   _hill_tensor[_qp].vector_mult(hill_stress, stress_vector);
     548      120880 :   hill_stress.scale(delta_gamma);
     549             :   inelasticStrainIncrement_vector = hill_stress;
     550             : 
     551      120880 :   inelasticStrainIncrement(0, 0) = inelasticStrainIncrement_vector(0);
     552      120880 :   inelasticStrainIncrement(1, 1) = inelasticStrainIncrement_vector(1);
     553      120880 :   inelasticStrainIncrement(2, 2) = inelasticStrainIncrement_vector(2);
     554      120880 :   inelasticStrainIncrement(0, 1) = inelasticStrainIncrement(1, 0) =
     555      120880 :       inelasticStrainIncrement_vector(3) / 2.0;
     556      120880 :   inelasticStrainIncrement(1, 2) = inelasticStrainIncrement(2, 1) =
     557      120880 :       inelasticStrainIncrement_vector(4) / 2.0;
     558      120880 :   inelasticStrainIncrement(0, 2) = inelasticStrainIncrement(2, 0) =
     559      120880 :       inelasticStrainIncrement_vector(5) / 2.0;
     560             : 
     561      120880 :   if (_local_cylindrical_csys)
     562       51120 :     inelasticStrainIncrement.rotate(_rotation_matrix[_qp]);
     563             : 
     564             :   // Calculate equivalent plastic strain
     565      120880 :   GenericDenseVector<is_ad> Mepsilon(6);
     566      120880 :   _hill_tensor[_qp].vector_mult(Mepsilon, inelasticStrainIncrement_vector);
     567      120880 :   GenericReal<is_ad> eq_plastic_strain_inc = Mepsilon.dot(inelasticStrainIncrement_vector);
     568             : 
     569      120880 :   if (eq_plastic_strain_inc > 0.0)
     570       56932 :     eq_plastic_strain_inc = sqrt(eq_plastic_strain_inc);
     571             : 
     572      241760 :   _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp] + eq_plastic_strain_inc;
     573             : 
     574      120880 :   AnisotropicReturnPlasticityStressUpdateBaseTempl<is_ad>::computeStrainFinalize(
     575             :       inelasticStrainIncrement, stress, stress_dev, delta_gamma);
     576      120880 : }
     577             : 
     578             : template <bool is_ad>
     579             : void
     580      135560 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeStressFinalize(
     581             :     const GenericRankTwoTensor<is_ad> & /*plastic_strain_increment*/,
     582             :     const GenericReal<is_ad> & delta_gamma,
     583             :     GenericRankTwoTensor<is_ad> & stress_new,
     584             :     const GenericDenseVector<is_ad> & /*stress_dev*/,
     585             :     const GenericRankTwoTensor<is_ad> & /*stress_old*/,
     586             :     const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/)
     587             : {
     588             :   // Need to compute this iteration's stress tensor based on the scalar variable
     589             :   // For deviatoric
     590             :   // sigma(n+1) = {Alpha [I + delta_gamma*Delta_b]^(-1) A^-1}  sigma(trial)
     591             : 
     592      135560 :   if (_yield_condition <= 0.0)
     593       70348 :     return;
     594       65212 :   GenericDenseMatrix<is_ad> inv_matrix(6, 6);
     595       65212 :   inv_matrix.zero();
     596             : 
     597      456484 :   for (unsigned int i = 0; i < 6; i++)
     598     1565088 :     inv_matrix(i, i) = 1 / (1 + delta_gamma * _b_eigenvalues[_qp](i));
     599             : 
     600       65212 :   _alpha_matrix[_qp].right_multiply(inv_matrix);
     601             : 
     602       65212 :   GenericDenseVector<is_ad> stress_output(6);
     603       65212 :   if (_local_cylindrical_csys)
     604       59400 :     _alpha_matrix[_qp].vector_mult(stress_output, _sigma_tilde_rotated[_qp]);
     605             :   else
     606        5812 :     _alpha_matrix[_qp].vector_mult(stress_output, _sigma_tilde[_qp]);
     607             : 
     608       65212 :   RankTwoScalarTools::VoigtVectorToRankTwoTensor<is_ad>(stress_output, stress_new);
     609             : 
     610       65212 :   if (_local_cylindrical_csys)
     611       59400 :     stress_new.rotate(_rotation_matrix[_qp]);
     612       65212 : }
     613             : 
     614             : template <bool is_ad>
     615             : Real
     616           0 : HillElastoPlasticityStressUpdateTempl<is_ad>::computeStrainEnergyRateDensity(
     617             :     const GenericMaterialProperty<RankTwoTensor, is_ad> & /*stress*/,
     618             :     const GenericMaterialProperty<RankTwoTensor, is_ad> & /*strain_rate*/)
     619             : {
     620           0 :   mooseError("computeStrainEnergyRateDensity not implemented for anisotropic plasticity.");
     621             :   return 0.0;
     622             : }
     623             : 
     624             : template class HillElastoPlasticityStressUpdateTempl<false>;
     625             : template class HillElastoPlasticityStressUpdateTempl<true>;

Generated by: LCOV version 1.14