LCOV - code coverage report
Current view: top level - src/materials - LinearViscoelasticityBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #32971 (54bef8) with base c6cf66 Lines: 124 147 84.4 %
Date: 2026-05-29 20:40:07 Functions: 7 8 87.5 %
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 "LinearViscoelasticityBase.h"
      11             : #include "Conversion.h"
      12             : 
      13             : InputParameters
      14         144 : LinearViscoelasticityBase::validParams()
      15             : {
      16         288 :   MooseEnum integration("backward-euler mid-point newmark zienkiewicz", "backward-euler");
      17             : 
      18         144 :   InputParameters params = ComputeElasticityTensorBase::validParams();
      19         288 :   params.addParam<MooseEnum>("integration_rule",
      20             :                              integration,
      21             :                              "describes how the viscoelastic behavior is integrated through time");
      22         288 :   params.addRangeCheckedParam<Real>("theta",
      23             :                                     1,
      24             :                                     "theta > 0 & theta <= 1",
      25             :                                     "coefficient for Newmark integration rule (between 0 and 1)");
      26         288 :   params.addParam<std::string>("driving_eigenstrain",
      27             :                                "name of the eigenstrain that increases the creep strains");
      28         288 :   params.addParam<std::string>(
      29             :       "elastic_strain_name", "elastic_strain", "name of the true elastic strain of the material");
      30         288 :   params.addParam<std::string>("creep_strain_name",
      31             :                                "creep_strain",
      32             :                                "name of the true creep strain of the material"
      33             :                                "(computed by LinearViscoelasticStressUpdate or"
      34             :                                "ComputeLinearViscoelasticStress)");
      35         288 :   params.addParam<bool>("force_recompute_properties",
      36         288 :                         false,
      37             :                         "forces the computation of the viscoelastic properties at each step of"
      38             :                         "the solver (default: false)");
      39         288 :   params.addParam<bool>(
      40             :       "need_viscoelastic_properties_inverse",
      41         288 :       false,
      42             :       "checks whether the model requires the computation of the inverse viscoelastic"
      43             :       "properties (default: false)");
      44         144 :   params.suppressParameter<FunctionName>("elasticity_tensor_prefactor");
      45         144 :   return params;
      46         144 : }
      47             : 
      48         108 : LinearViscoelasticityBase::LinearViscoelasticityBase(const InputParameters & parameters)
      49             :   : ComputeElasticityTensorBase(parameters),
      50         108 :     _integration_rule(getParam<MooseEnum>("integration_rule").getEnum<IntegrationRule>()),
      51         216 :     _theta(getParam<Real>("theta")),
      52         108 :     _apparent_elasticity_tensor(
      53         108 :         declareProperty<RankFourTensor>(_base_name + "apparent_elasticity_tensor")),
      54         108 :     _apparent_elasticity_tensor_inv(
      55         108 :         declareProperty<RankFourTensor>(_base_name + "apparent_elasticity_tensor_inv")),
      56         108 :     _elasticity_tensor_inv(declareProperty<RankFourTensor>(_elasticity_tensor_name + "_inv")),
      57         216 :     _need_viscoelastic_properties_inverse(getParam<bool>("need_viscoelastic_properties_inverse")),
      58         108 :     _has_longterm_dashpot(false),
      59         108 :     _components(0),
      60         108 :     _first_elasticity_tensor(
      61         108 :         declareProperty<RankFourTensor>(_base_name + "spring_elasticity_tensor_0")),
      62         108 :     _first_elasticity_tensor_inv(
      63         108 :         _need_viscoelastic_properties_inverse
      64         192 :             ? &declareProperty<RankFourTensor>(_base_name + "spring_elasticity_tensor_0_inv")
      65             :             : nullptr),
      66         108 :     _longterm_elasticity_tensor(nullptr),
      67         108 :     _longterm_elasticity_tensor_inv(nullptr),
      68         108 :     _apparent_creep_strain(declareProperty<RankTwoTensor>(_base_name + "apparent_creep_strain")),
      69         108 :     _apparent_creep_strain_old(
      70         108 :         getMaterialPropertyOld<RankTwoTensor>(_base_name + "apparent_creep_strain")),
      71         108 :     _elastic_strain_old(
      72         108 :         getMaterialPropertyOld<RankTwoTensor>(getParam<std::string>("elastic_strain_name"))),
      73         108 :     _creep_strain_old(
      74         108 :         getMaterialPropertyOld<RankTwoTensor>(getParam<std::string>("creep_strain_name"))),
      75         216 :     _has_driving_eigenstrain(isParamValid("driving_eigenstrain")),
      76         132 :     _driving_eigenstrain_name(
      77         108 :         _has_driving_eigenstrain ? getParam<std::string>("driving_eigenstrain") : ""),
      78         216 :     _driving_eigenstrain(_has_driving_eigenstrain
      79         108 :                              ? &getMaterialPropertyByName<RankTwoTensor>(_driving_eigenstrain_name)
      80             :                              : nullptr),
      81         216 :     _driving_eigenstrain_old(_has_driving_eigenstrain
      82         108 :                                  ? &getMaterialPropertyOld<RankTwoTensor>(_driving_eigenstrain_name)
      83             :                                  : nullptr),
      84         216 :     _force_recompute_properties(getParam<bool>("force_recompute_properties")),
      85         324 :     _step_zero(declareRestartableData<bool>("step_zero", true))
      86             : {
      87         108 :   if (_theta < 0.5)
      88           0 :     mooseWarning("theta parameter for LinearViscoelasticityBase is below 0.5; time integration may "
      89             :                  "not converge!");
      90             : 
      91             :   // force material properties to be considered stateful
      92         108 :   getMaterialPropertyOld<RankFourTensor>(_base_name + "apparent_elasticity_tensor");
      93         216 :   getMaterialPropertyOld<RankFourTensor>(_base_name + "apparent_elasticity_tensor_inv");
      94             :   getMaterialPropertyOld<RankFourTensor>(_elasticity_tensor_name);
      95         108 :   getMaterialPropertyOld<RankFourTensor>(_elasticity_tensor_name + "_inv");
      96         108 :   getMaterialPropertyOld<RankFourTensor>(_base_name + "spring_elasticity_tensor_0");
      97         108 :   if (_need_viscoelastic_properties_inverse)
      98         168 :     getMaterialPropertyOld<RankFourTensor>(_base_name + "spring_elasticity_tensor_0_inv");
      99         108 : }
     100             : 
     101             : void
     102         108 : LinearViscoelasticityBase::declareViscoelasticProperties()
     103             : {
     104         288 :   for (unsigned int i = 0; i < _components; ++i)
     105             :   {
     106         180 :     std::string ith = Moose::stringify(i + 1);
     107             : 
     108         180 :     if (!_has_longterm_dashpot || (_components > 0 && i < _components - 1))
     109             :     {
     110         144 :       _springs_elasticity_tensors.push_back(
     111         144 :           &declareProperty<RankFourTensor>(_base_name + "spring_elasticity_tensor_" + ith));
     112         288 :       getMaterialPropertyOld<RankFourTensor>(_base_name + "spring_elasticity_tensor_" + ith);
     113             :     }
     114             : 
     115         180 :     _dashpot_viscosities.push_back(&declareProperty<Real>(_base_name + "dashpot_viscosity_" + ith));
     116         180 :     _dashpot_viscosities_old.push_back(
     117         360 :         &getMaterialPropertyOld<Real>(_base_name + "dashpot_viscosity_" + ith));
     118             : 
     119         180 :     _viscous_strains.push_back(
     120         180 :         &declareProperty<RankTwoTensor>(_base_name + "viscous_strain_" + ith));
     121         180 :     _viscous_strains_old.push_back(
     122         360 :         &getMaterialPropertyOld<RankTwoTensor>(_base_name + "viscous_strain_" + ith));
     123             : 
     124         180 :     if (_need_viscoelastic_properties_inverse)
     125             :     {
     126         144 :       _springs_elasticity_tensors_inv.push_back(&declareProperty<RankFourTensor>(
     127         144 :           _base_name + "spring_elasticity_tensor_" + ith + "_inv"));
     128         144 :       _springs_elasticity_tensors_inv_old.push_back(&getMaterialPropertyOld<RankFourTensor>(
     129         288 :           _base_name + "spring_elasticity_tensor_" + ith + "_inv"));
     130             :     }
     131             :   }
     132             : 
     133         108 :   if (_has_longterm_dashpot)
     134             :   {
     135          36 :     _longterm_elasticity_tensor =
     136          36 :         &declareProperty<RankFourTensor>(_base_name + "longterm_elasticity_tensor");
     137          36 :     if (_need_viscoelastic_properties_inverse)
     138          36 :       _longterm_elasticity_tensor_inv =
     139          72 :           &declareProperty<RankFourTensor>(_base_name + "longterm_elasticity_tensor_inv");
     140             :   }
     141         108 : }
     142             : 
     143             : void
     144         432 : LinearViscoelasticityBase::initQpStatefulProperties()
     145             : {
     146         432 :   if (_components != _viscous_strains.size())
     147           0 :     mooseError(
     148             :         "inconsistent numbers of dashpots and viscous strains in LinearViscoelasticityBase;"
     149             :         " Make sure declareViscoelasticProperties has been called in the viscoelastic model");
     150             : 
     151         432 :   _apparent_creep_strain[_qp].zero();
     152         432 :   _apparent_elasticity_tensor[_qp].zero();
     153         432 :   _apparent_elasticity_tensor_inv[_qp].zero();
     154         432 :   _elasticity_tensor_inv[_qp].zero();
     155         432 :   _first_elasticity_tensor[_qp].zero();
     156         432 :   if (_longterm_elasticity_tensor)
     157         144 :     (*_longterm_elasticity_tensor)[_qp].zero();
     158         432 :   if (_first_elasticity_tensor_inv)
     159         336 :     (*_first_elasticity_tensor_inv)[_qp].zero();
     160         432 :   if (_longterm_elasticity_tensor_inv)
     161         144 :     (*_longterm_elasticity_tensor_inv)[_qp].zero();
     162             : 
     163        1152 :   for (unsigned int i = 0; i < _components; ++i)
     164             :   {
     165         720 :     if (!_has_longterm_dashpot || (_components > 0 && i < _components - 1))
     166             :     {
     167         576 :       (*_springs_elasticity_tensors[i])[_qp].zero();
     168         576 :       if (_need_viscoelastic_properties_inverse)
     169         432 :         (*_springs_elasticity_tensors_inv[i])[_qp].zero();
     170             :     }
     171             : 
     172         720 :     (*_dashpot_viscosities[i])[_qp] = 0.0;
     173         720 :     (*_viscous_strains[i])[_qp].zero();
     174             :   }
     175         432 : }
     176             : 
     177             : void
     178        6288 : LinearViscoelasticityBase::recomputeQpApparentProperties(unsigned int qp)
     179             : {
     180        6288 :   unsigned int qp_prev = _qp;
     181        6288 :   _qp = qp;
     182             : 
     183        6288 :   if (_t_step >= 1)
     184        6288 :     _step_zero = false;
     185             : 
     186             :   // 1. we get the viscoelastic properties and their inverse if needed
     187        6288 :   computeQpViscoelasticProperties();
     188             : 
     189        6288 :   if (_need_viscoelastic_properties_inverse)
     190        4784 :     computeQpViscoelasticPropertiesInv();
     191             : 
     192             :   // 2. we update the internal viscous strains from the previous time step
     193        6288 :   updateQpViscousStrains();
     194             : 
     195             :   // 3. we compute the apparent elasticity tensor
     196        6288 :   computeQpApparentElasticityTensors();
     197             : 
     198             :   // 4. we transform the internal viscous strains in an apparent creep strain
     199        6288 :   if (!_step_zero)
     200        6288 :     computeQpApparentCreepStrain();
     201             : 
     202        6288 :   _qp = qp_prev;
     203        6288 : }
     204             : 
     205             : void
     206       80416 : LinearViscoelasticityBase::computeQpElasticityTensor()
     207             : {
     208       80416 :   if (_force_recompute_properties)
     209           0 :     recomputeQpApparentProperties(_qp);
     210       80416 : }
     211             : 
     212             : void
     213           0 : LinearViscoelasticityBase::computeQpViscoelasticPropertiesInv()
     214             : {
     215             :   mooseAssert(_first_elasticity_tensor_inv, "_first_elasticity_tensor_inv is null");
     216           0 :   if (MooseUtils::absoluteFuzzyEqual(_first_elasticity_tensor[_qp].L2norm(), 0.0))
     217           0 :     (*_first_elasticity_tensor_inv)[_qp].zero();
     218             :   else
     219           0 :     (*_first_elasticity_tensor_inv)[_qp] = _first_elasticity_tensor[_qp].invSymm();
     220             : 
     221           0 :   for (unsigned int i = 0; i < _springs_elasticity_tensors.size(); ++i)
     222             :   {
     223             :     mooseAssert(_springs_elasticity_tensors_inv[i], "_springs_elasticity_tensors_inv[i] is null");
     224           0 :     if (MooseUtils::absoluteFuzzyEqual((*_springs_elasticity_tensors[i])[_qp].L2norm(), 0.0))
     225           0 :       (*_springs_elasticity_tensors_inv[i])[_qp].zero();
     226             :     else
     227           0 :       (*_springs_elasticity_tensors_inv[i])[_qp] = (*_springs_elasticity_tensors[i])[_qp].invSymm();
     228             :   }
     229             : 
     230           0 :   if (_longterm_elasticity_tensor)
     231             :   {
     232             :     mooseAssert(_longterm_elasticity_tensor_inv, "_longterm_elasticity_tensor_inv is null");
     233           0 :     if (MooseUtils::absoluteFuzzyEqual((*_longterm_elasticity_tensor)[_qp].L2norm(), 0.0))
     234           0 :       (*_longterm_elasticity_tensor_inv)[_qp].zero();
     235             :     else
     236           0 :       (*_longterm_elasticity_tensor_inv)[_qp] = (*_longterm_elasticity_tensor)[_qp].invSymm();
     237             :   }
     238           0 : }
     239             : 
     240             : Real
     241       26912 : LinearViscoelasticityBase::computeTheta(Real dt, Real viscosity) const
     242             : {
     243       26912 :   if (MooseUtils::absoluteFuzzyEqual(dt, 0.0))
     244           0 :     mooseError("linear viscoelasticity cannot be integrated over a dt of ", dt);
     245             : 
     246       26912 :   switch (_integration_rule)
     247             :   {
     248             :     case IntegrationRule::BackwardEuler:
     249             :       return 1.;
     250           0 :     case IntegrationRule::MidPoint:
     251           0 :       return 0.5;
     252           0 :     case IntegrationRule::Newmark:
     253           0 :       return _theta;
     254           0 :     case IntegrationRule::Zienkiewicz:
     255           0 :       return 1. / (1. - std::exp(-dt / viscosity)) - viscosity / dt;
     256             :     default:
     257             :       return 1.;
     258             :   }
     259             :   return 1.;
     260             : }

Generated by: LCOV version 1.14