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 : #pragma once 11 : 12 : #include "StressUpdateBase.h" 13 : #include "SingleVariableReturnMappingSolution.h" 14 : #include "ADSingleVariableReturnMappingSolution.h" 15 : 16 : /** 17 : * RadialReturnStressUpdate computes the radial return stress increment for 18 : * an isotropic elastic-viscoplasticity model after interating on the difference 19 : * between new and old trial stress increments. This radial return mapping class 20 : * acts as a base class for the radial return creep and plasticity classes / combinations. 21 : * The stress increment computed by RadialReturnStressUpdate is used by 22 : * ComputeMultipleInelasticStress which computes the elastic stress for finite 23 : * strains. This return mapping class is acceptable for finite strains but not 24 : * total strains. 25 : * This class is based on the Elasto-viscoplasticity algorithm in F. Dunne and N. 26 : * Petrinic's Introduction to Computational Plasticity (2004) Oxford University Press. 27 : */ 28 : 29 : template <bool is_ad> 30 : class RadialReturnStressUpdateTempl : public StressUpdateBaseTempl<is_ad>, 31 : public SingleVariableReturnMappingSolutionTempl<is_ad> 32 : { 33 : public: 34 : static InputParameters validParams(); 35 : 36 : RadialReturnStressUpdateTempl(const InputParameters & parameters); 37 : 38 : using Material::_current_elem; 39 : using Material::_dt; 40 : using Material::_q_point; 41 : using Material::_qp; 42 : 43 : enum class SubsteppingType 44 : { 45 : NONE, 46 : ERROR_BASED, 47 : INCREMENT_BASED 48 : }; 49 : 50 : /** 51 : * A radial return (J2) mapping method is performed with return mapping 52 : * iterations. 53 : * @param strain_increment Sum of elastic and inelastic strain increments 54 : * @param inelastic_strain_increment Inelastic strain increment calculated by this class 55 : * @param rotation increment Not used by this class 56 : * @param stress_new New trial stress from pure elastic calculation 57 : * @param stress_old Old state of stress 58 : * @param elasticity_tensor Rank 4 C_{ijkl}, must be isotropic 59 : * @param elastic_strain_old Old state of total elastic strain 60 : * @param compute_full_tangent_operator Flag currently unused by this class 61 : * @param tangent_operator Currently a copy of the elasticity tensor in this class 62 : */ 63 : 64 : virtual void updateState( 65 : GenericRankTwoTensor<is_ad> & strain_increment, 66 : GenericRankTwoTensor<is_ad> & inelastic_strain_increment, 67 : const GenericRankTwoTensor<is_ad> & rotation_increment, 68 : GenericRankTwoTensor<is_ad> & stress_new, 69 : const RankTwoTensor & stress_old, 70 : const GenericRankFourTensor<is_ad> & elasticity_tensor, 71 : const RankTwoTensor & elastic_strain_old, 72 : bool compute_full_tangent_operator = false, 73 : RankFourTensor & tangent_operator = StressUpdateBaseTempl<is_ad>::_identityTensor) override; 74 : 75 : virtual void updateStateSubstepInternal( 76 : GenericRankTwoTensor<is_ad> & /*strain_increment*/, 77 : GenericRankTwoTensor<is_ad> & /*inelastic_strain_increment*/, 78 : const GenericRankTwoTensor<is_ad> & /*rotation_increment*/, 79 : GenericRankTwoTensor<is_ad> & /*stress_new*/, 80 : const RankTwoTensor & /*stress_old*/, 81 : const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/, 82 : const RankTwoTensor & /*elastic_strain_old*/, 83 : unsigned int total_number_substeps, 84 : bool compute_full_tangent_operator = false, 85 : RankFourTensor & tangent_operator = StressUpdateBaseTempl<is_ad>::_identityTensor); 86 : 87 : /** 88 : * Similar to the updateState function, this method updates the strain and stress for one substep 89 : */ 90 : virtual void updateStateSubstep( 91 : GenericRankTwoTensor<is_ad> & /*strain_increment*/, 92 : GenericRankTwoTensor<is_ad> & /*inelastic_strain_increment*/, 93 : const GenericRankTwoTensor<is_ad> & /*rotation_increment*/, 94 : GenericRankTwoTensor<is_ad> & /*stress_new*/, 95 : const RankTwoTensor & /*stress_old*/, 96 : const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/, 97 : const RankTwoTensor & /*elastic_strain_old*/, 98 : bool compute_full_tangent_operator = false, 99 : RankFourTensor & tangent_operator = StressUpdateBaseTempl<is_ad>::_identityTensor) override; 100 : 101 : virtual Real 102 : computeReferenceResidual(const GenericReal<is_ad> & effective_trial_stress, 103 : const GenericReal<is_ad> & scalar_effective_inelastic_strain) override; 104 : 105 : virtual GenericReal<is_ad> 106 56364948 : minimumPermissibleValue(const GenericReal<is_ad> & /*effective_trial_stress*/) const override 107 : { 108 56364948 : return 0.0; 109 : } 110 : 111 : virtual GenericReal<is_ad> 112 : maximumPermissibleValue(const GenericReal<is_ad> & effective_trial_stress) const override; 113 : 114 : /** 115 : * Compute the limiting value of the time step for this material 116 : * @return Limiting time step 117 : */ 118 : virtual Real computeTimeStepLimit() override; 119 : 120 : /** 121 : * Does the model require the elasticity tensor to be isotropic? 122 : */ 123 2428 : bool requiresIsotropicTensor() override { return true; } 124 : 125 : /** 126 : * Radial return mapped models should be isotropic by default! 127 : */ 128 1528 : bool isIsotropic() override { return true; }; 129 : 130 : /** 131 : * If substepping is enabled, calculate the number of substeps as a function 132 : * of the elastic strain increment guess and the maximum inelastic strain increment 133 : * ratio based on a user-specified tolerance. 134 : * @param strain_increment When called, this is the elastic strain guess 135 : * @return The number of substeps required 136 : */ 137 : virtual int 138 : calculateNumberSubsteps(const GenericRankTwoTensor<is_ad> & strain_increment) override; 139 : 140 : /** 141 : * Has the user requested usage of (possibly) implemented substepping capability for inelastic 142 : * models. Parent classes set this to false, but RadialReturn inelastic models have the 143 : * ability to implement substepping. 144 : */ 145 1526 : virtual bool substeppingCapabilityRequested() override 146 : { 147 1526 : return _use_substepping != SubsteppingType::NONE; 148 : } 149 : 150 : /// Current value of scalar inelastic strain 151 0 : const GenericReal<is_ad> & effectiveInelasticStrainIncrement() const 152 : { 153 0 : return _effective_inelastic_strain_increment; 154 : } 155 : 156 0 : void updateEffectiveInelasticStrainIncrement(const GenericReal<is_ad> & eisi) 157 : { 158 238688 : _effective_inelastic_strain_increment = eisi; 159 0 : } 160 : 161 58535440 : void updateEffectiveInelasticStrain(const GenericReal<is_ad> & increment) 162 : { 163 85869512 : _effective_inelastic_strain[_qp] = _effective_inelastic_strain_old[_qp] + increment; 164 58535440 : } 165 : 166 : /** 167 : * Calculate the tangent_operator. 168 : */ 169 : void computeTangentOperator(Real effective_trial_stress, 170 : const RankTwoTensor & stress_new, 171 : RankFourTensor & tangent_operator); 172 : 173 : protected: 174 : virtual void initQpStatefulProperties() override; 175 : 176 : /** 177 : * Propagate the properties pertaining to this intermediate class. This 178 : * is intended to be called from propagateQpStatefulProperties() in 179 : * classes that inherit from this one. 180 : * This is intentionally named uniquely because almost all models that derive 181 : * from this class have their own stateful properties, and this forces them 182 : * to define their own implementations of propagateQpStatefulProperties(). 183 : */ 184 : void propagateQpStatefulPropertiesRadialReturn(); 185 : 186 : /** 187 : * Perform any necessary initialization before return mapping iterations 188 : * @param effective_trial_stress Effective trial stress 189 : * @param elasticityTensor Elasticity tensor 190 : */ 191 : virtual void computeStressInitialize(const GenericReal<is_ad> & effective_trial_stress, 192 : const GenericRankFourTensor<is_ad> & elasticity_tensor); 193 : 194 : /** 195 : * Calculate the derivative of the strain increment with respect to the updated stress. 196 : * @param effective_trial_stress Effective trial stress 197 : * @param scalar Inelastic strain increment magnitude being solved for 198 : */ 199 0 : virtual Real computeStressDerivative(const Real /*effective_trial_stress*/, const Real /*scalar*/) 200 : { 201 0 : return 0.0; 202 : } 203 : 204 : /** 205 : * Perform any necessary steps to finalize state after return mapping iterations 206 : * @param inelasticStrainIncrement Inelastic strain increment 207 : */ 208 : virtual void 209 0 : computeStressFinalize(const GenericRankTwoTensor<is_ad> & /*inelasticStrainIncrement*/) 210 : { 211 0 : } 212 : 213 : void outputIterationSummary(std::stringstream * iter_output, 214 : const unsigned int total_it) override; 215 : 216 : /// 3 * shear modulus 217 : GenericReal<is_ad> _three_shear_modulus; 218 : 219 : GenericMaterialProperty<Real, is_ad> & _effective_inelastic_strain; 220 : const MaterialProperty<Real> & _effective_inelastic_strain_old; 221 : 222 : /// Stores the scalar effective inelastic strain increment from Newton iteration 223 : GenericReal<is_ad> _effective_inelastic_strain_increment; 224 : 225 : /** 226 : * Maximum allowable scalar inelastic strain increment, used to control the 227 : * timestep size in conjunction with a user object 228 : */ 229 : Real _max_inelastic_increment; 230 : 231 : /** 232 : * Used to calculate the number of substeps taken in the radial return algorithm, 233 : * when substepping is enabled, based on the elastic strain increment ratio 234 : * to the maximum inelastic increment 235 : */ 236 : const Real _substep_tolerance; 237 : 238 : /** 239 : * Rank two identity tensor 240 : */ 241 : const RankTwoTensor _identity_two; 242 : 243 : /** 244 : * Rank four symmetric identity tensor 245 : */ 246 : const RankFourTensor _identity_symmetric_four; 247 : 248 : /** 249 : * Rank four deviatoric projection tensor 250 : */ 251 : const RankFourTensor _deviatoric_projection_four; 252 : 253 : /// Debugging option to enable specifying instead of calculating strain 254 : const bool _apply_strain; 255 : 256 : /// Whether user has requested the use of substepping technique to improve convergence [make const later] 257 : SubsteppingType _use_substepping; 258 : 259 : /// Use adaptive substepping, cutting substep sizes until convergence is achieved 260 : const bool _adaptive_substepping; 261 : 262 : /// Maximum number of substeps. If the calculation results in a larger number, cut overall time step. 263 : const unsigned int _maximum_number_substeps; 264 : 265 : /// original timestep (to be restored after substepping is completed) 266 : Real _dt_original; 267 : }; 268 : 269 : typedef RadialReturnStressUpdateTempl<false> RadialReturnStressUpdate; 270 : typedef RadialReturnStressUpdateTempl<true> ADRadialReturnStressUpdate; 271 : 272 : template <> 273 : void 274 : RadialReturnStressUpdateTempl<false>::computeTangentOperator(Real effective_trial_stress, 275 : const RankTwoTensor & stress_new, 276 : RankFourTensor & tangent_operator);