LCOV - code coverage report
Current view: top level - src/materials - ADViscoplasticityStressUpdate.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #31613 (c7d555) with base 7323e9 Lines: 126 137 92.0 %
Date: 2025-11-06 14:18:25 Functions: 11 12 91.7 %
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 "ADViscoplasticityStressUpdate.h"
      11             : 
      12             : #include "libmesh/utility.h"
      13             : 
      14             : registerMooseObject("SolidMechanicsApp", ADViscoplasticityStressUpdate);
      15             : 
      16             : InputParameters
      17        1104 : ADViscoplasticityStressUpdate::validParams()
      18             : {
      19        1104 :   InputParameters params = ADViscoplasticityStressUpdateBase::validParams();
      20        1104 :   params += ADSingleVariableReturnMappingSolution::validParams();
      21        1104 :   params.addClassDescription(
      22             :       "This material computes the non-linear homogenized gauge stress in order to compute the "
      23             :       "viscoplastic responce due to creep in porous materials. This material must be used in "
      24             :       "conjunction with ADComputeMultiplePorousInelasticStress");
      25        2208 :   MooseEnum viscoplasticity_model("LPS GTN", "LPS");
      26        2208 :   params.addParam<MooseEnum>(
      27             :       "viscoplasticity_model", viscoplasticity_model, "Which viscoplastic model to use");
      28        2208 :   MooseEnum pore_shape_model("spherical cylindrical", "spherical");
      29        2208 :   params.addParam<MooseEnum>("pore_shape_model", pore_shape_model, "Which pore shape model to use");
      30        2208 :   params.addRequiredParam<MaterialPropertyName>(
      31             :       "coefficient", "Material property name for the leading coefficient for Norton power law");
      32        2208 :   params.addRequiredRangeCheckedParam<Real>(
      33             :       "power", "power>=1.0", "Stress exponent for Norton power law");
      34        2208 :   params.addParam<Real>(
      35             :       "maximum_gauge_ratio",
      36        2208 :       1.0e6,
      37             :       "Maximum ratio between the gauge stress and the equivalent stress. This "
      38             :       "should be a high number. Note that this does not set an upper bound on the value, but "
      39             :       "rather will help with convergence of the inner Newton loop");
      40        2208 :   params.addParam<Real>(
      41             :       "minimum_equivalent_stress",
      42        2208 :       1.0e-3,
      43             :       "Minimum value of equivalent stress below which viscoplasticiy is not calculated.");
      44        2208 :   params.addParam<Real>("maximum_equivalent_stress",
      45        2208 :                         1.0e12,
      46             :                         "Maximum value of equivalent stress above which an exception is thrown "
      47             :                         "instead of calculating the properties in this material.");
      48             : 
      49        2208 :   params.addParamNamesToGroup("verbose maximum_gauge_ratio maximum_equivalent_stress", "Advanced");
      50        1104 :   return params;
      51        1104 : }
      52             : 
      53         828 : ADViscoplasticityStressUpdate::ADViscoplasticityStressUpdate(const InputParameters & parameters)
      54             :   : ADViscoplasticityStressUpdateBase(parameters),
      55             :     ADSingleVariableReturnMappingSolution(parameters),
      56         828 :     _model(parameters.get<MooseEnum>("viscoplasticity_model").getEnum<ViscoplasticityModel>()),
      57         828 :     _pore_shape(parameters.get<MooseEnum>("pore_shape_model").getEnum<PoreShapeModel>()),
      58         828 :     _pore_shape_factor(_pore_shape == PoreShapeModel::SPHERICAL ? 1.5 : std::sqrt(3.0)),
      59        1656 :     _power(getParam<Real>("power")),
      60         828 :     _power_factor(_model == ViscoplasticityModel::LPS ? (_power - 1.0) / (_power + 1.0) : 1.0),
      61        1656 :     _coefficient(getADMaterialProperty<Real>("coefficient")),
      62         828 :     _gauge_stress(declareADProperty<Real>(_base_name + "gauge_stress")),
      63        1656 :     _maximum_gauge_ratio(getParam<Real>("maximum_gauge_ratio")),
      64        1656 :     _minimum_equivalent_stress(getParam<Real>("minimum_equivalent_stress")),
      65        1656 :     _maximum_equivalent_stress(getParam<Real>("maximum_equivalent_stress")),
      66         828 :     _hydro_stress(0.0),
      67         828 :     _identity_two(RankTwoTensor::initIdentity),
      68         828 :     _dhydro_stress_dsigma(_identity_two / 3.0),
      69        1656 :     _derivative(0.0)
      70             : {
      71         828 :   _check_range = true;
      72         828 : }
      73             : 
      74             : void
      75      244226 : ADViscoplasticityStressUpdate::updateState(ADRankTwoTensor & elastic_strain_increment,
      76             :                                            ADRankTwoTensor & inelastic_strain_increment,
      77             :                                            const ADRankTwoTensor & /*rotation_increment*/,
      78             :                                            ADRankTwoTensor & stress,
      79             :                                            const RankTwoTensor & /*stress_old*/,
      80             :                                            const ADRankFourTensor & elasticity_tensor,
      81             :                                            const RankTwoTensor & elastic_strain_old,
      82             :                                            bool /*compute_full_tangent_operator = false*/,
      83             :                                            RankFourTensor & /*tangent_operator = _identityTensor*/)
      84             : {
      85             :   using std::sqrt;
      86             : 
      87             :   // Compute initial hydrostatic stress and porosity
      88      244226 :   if (_pore_shape == PoreShapeModel::CYLINDRICAL)
      89      168448 :     _hydro_stress = (stress(0, 0) + stress(1, 1)) / 2.0;
      90             :   else
      91      320004 :     _hydro_stress = stress.trace() / 3.0;
      92             : 
      93      244226 :   updateIntermediatePorosity(elastic_strain_increment);
      94             : 
      95             :   // Compute intermediate equivalent stress
      96      244224 :   const ADRankTwoTensor dev_stress = stress.deviatoric();
      97      244224 :   const ADReal dev_stress_squared = dev_stress.doubleContraction(dev_stress);
      98      484272 :   const ADReal equiv_stress = dev_stress_squared == 0.0 ? 0.0 : sqrt(1.5 * dev_stress_squared);
      99             : 
     100      244224 :   computeStressInitialize(equiv_stress, elasticity_tensor);
     101             : 
     102             :   // Prepare values
     103      244224 :   _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp];
     104      244224 :   _inelastic_strain[_qp] = _inelastic_strain_old[_qp];
     105      244224 :   inelastic_strain_increment.zero();
     106             : 
     107             :   // Protect against extremely high values of stresses calculated by other viscoplastic materials
     108      244224 :   if (equiv_stress > _maximum_equivalent_stress)
     109           0 :     mooseException("In ",
     110             :                    _name,
     111             :                    ": equivalent stress (",
     112             :                    equiv_stress,
     113             :                    ") is higher than maximum_equivalent_stress (",
     114             :                    _maximum_equivalent_stress,
     115             :                    ").\nCutting time step.");
     116             : 
     117             :   // If equivalent stress is present, calculate creep strain increment
     118      244224 :   if (equiv_stress > _minimum_equivalent_stress)
     119             :   {
     120             :     // Initalize stress potential
     121      240048 :     ADReal dpsi_dgauge(0);
     122             : 
     123      240048 :     computeInelasticStrainIncrement(_gauge_stress[_qp],
     124             :                                     dpsi_dgauge,
     125             :                                     inelastic_strain_increment,
     126             :                                     equiv_stress,
     127             :                                     dev_stress,
     128             :                                     stress);
     129             : 
     130             :     // Update elastic strain increment due to inelastic strain calculated here
     131      240048 :     elastic_strain_increment -= inelastic_strain_increment;
     132             :     // Update stress due to new strain
     133      240048 :     stress = elasticity_tensor * (elastic_strain_old + elastic_strain_increment);
     134             : 
     135             :     // Compute effective strain from the stress potential. Note that this is approximate and to be
     136             :     // used qualitatively
     137      480096 :     _effective_inelastic_strain[_qp] += dpsi_dgauge * _dt;
     138             :     // Update creep strain due to currently computed inelastic strain
     139      240048 :     _inelastic_strain[_qp] += inelastic_strain_increment;
     140             :   }
     141             : 
     142      244224 :   const ADRankTwoTensor new_dev_stress = stress.deviatoric();
     143      244224 :   const ADReal new_dev_stress_squared = new_dev_stress.doubleContraction(new_dev_stress);
     144             :   const ADReal new_equiv_stress =
     145      724320 :       new_dev_stress_squared == 0.0 ? 0.0 : sqrt(1.5 * new_dev_stress_squared);
     146             : 
     147      244224 :   if (MooseUtils::relativeFuzzyGreaterThan(new_equiv_stress, equiv_stress))
     148           0 :     mooseException("In ",
     149             :                    _name,
     150             :                    ": updated equivalent stress (",
     151             :                    MetaPhysicL::raw_value(new_equiv_stress),
     152             :                    ") is greater than initial equivalent stress (",
     153             :                    MetaPhysicL::raw_value(equiv_stress),
     154             :                    "). Try decreasing max_inelastic_increment to avoid this exception.");
     155             : 
     156      244224 :   computeStressFinalize(inelastic_strain_increment);
     157      244224 : }
     158             : 
     159             : ADReal
     160      238096 : ADViscoplasticityStressUpdate::initialGuess(const ADReal & effective_trial_stress)
     161             : {
     162      238096 :   return effective_trial_stress;
     163             : }
     164             : 
     165             : ADReal
     166      238096 : ADViscoplasticityStressUpdate::maximumPermissibleValue(const ADReal & effective_trial_stress) const
     167             : {
     168      238096 :   return effective_trial_stress * _maximum_gauge_ratio;
     169             : }
     170             : 
     171             : ADReal
     172      238096 : ADViscoplasticityStressUpdate::minimumPermissibleValue(const ADReal & effective_trial_stress) const
     173             : {
     174      238096 :   return effective_trial_stress;
     175             : }
     176             : 
     177             : ADReal
     178     1900886 : ADViscoplasticityStressUpdate::computeResidual(const ADReal & equiv_stress,
     179             :                                                const ADReal & trial_gauge)
     180             : {
     181             :   using std::abs, std::cosh, std::sinh;
     182             : 
     183     1900886 :   const ADReal M = abs(_hydro_stress) / trial_gauge;
     184     3801772 :   const ADReal dM_dtrial_gauge = -M / trial_gauge;
     185             : 
     186     1900886 :   const ADReal residual_left = Utility::pow<2>(equiv_stress / trial_gauge);
     187     1900886 :   const ADReal dresidual_left_dtrial_gauge = -2.0 * residual_left / trial_gauge;
     188             : 
     189     1900886 :   ADReal residual = residual_left;
     190     1900886 :   _derivative = dresidual_left_dtrial_gauge;
     191             : 
     192     1900886 :   if (_pore_shape == PoreShapeModel::SPHERICAL)
     193             :   {
     194     3203307 :     residual *= 1.0 + _intermediate_porosity / 1.5;
     195     3203307 :     _derivative *= 1.0 + _intermediate_porosity / 1.5;
     196             :   }
     197             : 
     198     1900886 :   if (_model == ViscoplasticityModel::GTN)
     199             :   {
     200     1234824 :     residual += 2.0 * _intermediate_porosity * cosh(_pore_shape_factor * M) - 1.0 -
     201     1234824 :                 Utility::pow<2>(_intermediate_porosity);
     202      617412 :     _derivative += 2.0 * _intermediate_porosity * sinh(_pore_shape_factor * M) *
     203      617412 :                    _pore_shape_factor * dM_dtrial_gauge;
     204             :   }
     205             :   else
     206             :   {
     207     1283474 :     const ADReal h = computeH(_power, M);
     208     1283474 :     const ADReal dh_dM = computeH(_power, M, true);
     209             : 
     210     1283474 :     residual += _intermediate_porosity * (h + _power_factor / h) - 1.0 -
     211     2566948 :                 _power_factor * Utility::pow<2>(_intermediate_porosity);
     212     2566948 :     const ADReal dresidual_dh = _intermediate_porosity * (1.0 - _power_factor / Utility::pow<2>(h));
     213     1283474 :     _derivative += dresidual_dh * dh_dM * dM_dtrial_gauge;
     214             :   }
     215             : 
     216     1900886 :   if (_verbose)
     217             :   {
     218             :     Moose::out << "in computeResidual:\n"
     219           0 :                << "  position: " << _q_point[_qp] << " hydro_stress: " << _hydro_stress
     220             :                << " equiv_stress: " << equiv_stress << " trial_grage: " << trial_gauge
     221             :                << " M: " << M << std::endl;
     222             :     Moose::out << "  residual: " << residual << "  derivative: " << _derivative << std::endl;
     223             :   }
     224             : 
     225     1900886 :   return residual;
     226             : }
     227             : 
     228             : ADReal
     229     3016212 : ADViscoplasticityStressUpdate::computeH(const Real n, const ADReal & M, const bool derivative)
     230             : {
     231             :   using std::pow;
     232             : 
     233     6032424 :   const ADReal mod = pow(M * _pore_shape_factor, (n + 1.0) / n);
     234             : 
     235             :   // Calculate derivative with respect to M
     236     3016212 :   if (derivative)
     237             :   {
     238     1492690 :     const ADReal dmod_dM = (n + 1.0) / n * mod / M;
     239     5970760 :     return dmod_dM * pow(1.0 + mod / n, n - 1.0);
     240             :   }
     241             : 
     242     3047044 :   return pow(1.0 + mod / n, n);
     243             : }
     244             : 
     245             : ADRankTwoTensor
     246      240048 : ADViscoplasticityStressUpdate::computeDGaugeDSigma(const ADReal & gauge_stress,
     247             :                                                    const ADReal & equiv_stress,
     248             :                                                    const ADRankTwoTensor & dev_stress,
     249             :                                                    const ADRankTwoTensor & stress)
     250             : {
     251             :   using std::abs, std::sinh;
     252             : 
     253             :   // Compute the derivative of the gauge stress with respect to the equivalent and hydrostatic
     254             :   // stress components
     255      240048 :   const ADReal M = abs(_hydro_stress) / gauge_stress;
     256      240048 :   const ADReal h = computeH(_power, M);
     257             : 
     258             :   // Compute the derviative of the residual with respect to the hydrostatic stress
     259      240048 :   ADReal dresidual_dhydro_stress = 0.0;
     260      240048 :   if (_hydro_stress != 0.0)
     261             :   {
     262             :     const ADReal dM_dhydro_stress = M / _hydro_stress;
     263      240048 :     if (_model == ViscoplasticityModel::GTN)
     264             :     {
     265       30832 :       dresidual_dhydro_stress = 2.0 * _intermediate_porosity * sinh(_pore_shape_factor * M) *
     266       61664 :                                 _pore_shape_factor * dM_dhydro_stress;
     267             :     }
     268             :     else
     269             :     {
     270             :       const ADReal dresidual_dh =
     271      627648 :           _intermediate_porosity * (1.0 - _power_factor / Utility::pow<2>(h));
     272      209216 :       const ADReal dh_dM = computeH(_power, M, true);
     273      209216 :       dresidual_dhydro_stress = dresidual_dh * dh_dM * dM_dhydro_stress;
     274             :     }
     275             :   }
     276             : 
     277             :   // Compute the derivative of the residual with respect to the equivalent stress
     278      240048 :   ADReal dresidual_dequiv_stress = 2.0 * equiv_stress / Utility::pow<2>(gauge_stress);
     279      240048 :   if (_pore_shape == PoreShapeModel::SPHERICAL)
     280      473352 :     dresidual_dequiv_stress *= 1.0 + _intermediate_porosity / 1.5;
     281             : 
     282             :   // Compute the derivative of the equilvalent stress to the deviatoric stress
     283      480096 :   const ADRankTwoTensor dequiv_stress_dsigma = 1.5 * dev_stress / equiv_stress;
     284             : 
     285             :   // Compute the derivative of the residual with the stress
     286      240048 :   const ADRankTwoTensor dresidual_dsigma = dresidual_dhydro_stress * _dhydro_stress_dsigma +
     287      240048 :                                            dresidual_dequiv_stress * dequiv_stress_dsigma;
     288             : 
     289             :   // Compute the deritative of the gauge stress with respect to the stress
     290             :   const ADRankTwoTensor dgauge_dsigma =
     291      480096 :       dresidual_dsigma * (gauge_stress / dresidual_dsigma.doubleContraction(stress));
     292             : 
     293      240048 :   return dgauge_dsigma;
     294             : }
     295             : 
     296             : void
     297      240048 : ADViscoplasticityStressUpdate::computeInelasticStrainIncrement(
     298             :     ADReal & gauge_stress,
     299             :     ADReal & dpsi_dgauge,
     300             :     ADRankTwoTensor & inelastic_strain_increment,
     301             :     const ADReal & equiv_stress,
     302             :     const ADRankTwoTensor & dev_stress,
     303             :     const ADRankTwoTensor & stress)
     304             : {
     305             :   using std::sqrt, std::pow;
     306             : 
     307             :   // If hydrostatic stress and porosity present, compute non-linear gauge stress
     308      240048 :   if (_intermediate_porosity == 0.0)
     309        1952 :     gauge_stress = equiv_stress;
     310      238096 :   else if (_hydro_stress == 0.0)
     311           0 :     gauge_stress = equiv_stress / sqrt(1.0 - (1.0 + _power_factor) * _intermediate_porosity +
     312           0 :                                        _power_factor * Utility::pow<2>(_intermediate_porosity));
     313             :   else
     314      238096 :     returnMappingSolve(equiv_stress, gauge_stress, _console);
     315             : 
     316             :   mooseAssert(gauge_stress >= equiv_stress,
     317             :               "Gauge stress calculated in inner Newton solve is less than the equivalent stress.");
     318             : 
     319             :   // Compute stress potential
     320      480096 :   dpsi_dgauge = _coefficient[_qp] * pow(gauge_stress, _power);
     321             : 
     322             :   // Compute strain increment from stress potential and the gauge stress derivative with respect
     323             :   // to the stress stress. The current form is explicit, and should eventually be changed
     324             :   inelastic_strain_increment =
     325      240048 :       _dt * dpsi_dgauge * computeDGaugeDSigma(gauge_stress, equiv_stress, dev_stress, stress);
     326      240048 : }
     327             : 
     328             : void
     329           0 : ADViscoplasticityStressUpdate::outputIterationSummary(std::stringstream * iter_output,
     330             :                                                       const unsigned int total_it)
     331             : {
     332           0 :   if (iter_output)
     333             :   {
     334           0 :     *iter_output << "At element " << _current_elem->id() << " _qp=" << _qp << " Coordinates "
     335           0 :                  << _q_point[_qp] << " block=" << _current_elem->subdomain_id() << '\n';
     336             :   }
     337           0 :   ADSingleVariableReturnMappingSolution::outputIterationSummary(iter_output, total_it);
     338           0 : }
     339             : 
     340             : Real
     341     1900886 : ADViscoplasticityStressUpdate::computeReferenceResidual(const ADReal & /*effective_trial_stress*/,
     342             :                                                         const ADReal & gauge_stress)
     343             : {
     344             :   // Use gauge stress for relative tolerance criteria, defined as:
     345             :   // abs(residual / gauge_stress) <= _relative_tolerance
     346     1900886 :   return MetaPhysicL::raw_value(gauge_stress);
     347             : }

Generated by: LCOV version 1.14