Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://www.mooseframework.org 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 "TemperatureDependentHardeningStressUpdate.h" 11 : 12 : #include "PiecewiseLinear.h" 13 : #include "ElasticityTensorTools.h" 14 : 15 : registerMooseObject("TensorMechanicsApp", TemperatureDependentHardeningStressUpdate); 16 : registerMooseObject("TensorMechanicsApp", ADTemperatureDependentHardeningStressUpdate); 17 : 18 : template <bool is_ad> 19 : InputParameters 20 24 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::validParams() 21 : { 22 24 : InputParameters params = IsotropicPlasticityStressUpdateTempl<is_ad>::validParams(); 23 24 : params.addClassDescription("Computes the stress as a function of temperature " 24 : "and plastic strain from user-supplied hardening " 25 : "functions. This class can be used in conjunction " 26 : "with other creep and plasticity materials for " 27 : "more complex simulations"); 28 24 : params.set<Real>("yield_stress") = 1.0; 29 24 : params.set<Real>("hardening_constant") = 1.0; 30 : 31 24 : params.suppressParameter<Real>("yield_stress"); 32 24 : params.suppressParameter<FunctionName>("yield_stress_function"); 33 24 : params.suppressParameter<Real>("hardening_constant"); 34 24 : params.suppressParameter<FunctionName>("hardening_function"); 35 : 36 48 : params.addRequiredParam<std::vector<FunctionName>>( 37 : "hardening_functions", 38 : "List of functions of true stress as function of plastic strain at different temperatures"); 39 48 : params.addRequiredParam<std::vector<Real>>( 40 : "temperatures", 41 : "List of temperatures corresponding to the functions listed in 'hardening_functions'"); 42 : 43 24 : return params; 44 0 : } 45 : 46 : template <bool is_ad> 47 18 : TemperatureDependentHardeningStressUpdateTempl< 48 : is_ad>::TemperatureDependentHardeningStressUpdateTempl(const InputParameters & parameters) 49 : : IsotropicPlasticityStressUpdateTempl<is_ad>(parameters), 50 36 : _hardening_functions_names( 51 : this->template getParam<std::vector<FunctionName>>("hardening_functions")), 52 72 : _hf_temperatures(this->template getParam<std::vector<Real>>("temperatures")) 53 : { 54 18 : const unsigned int len = _hardening_functions_names.size(); 55 18 : if (len < 2) 56 0 : mooseError("At least two stress-strain curves must be provided in hardening_functions"); 57 18 : _hardening_functions.resize(len); 58 : 59 18 : const unsigned int len_temps = _hf_temperatures.size(); 60 18 : if (len != len_temps) 61 0 : mooseError("The vector of hardening function temperatures must have the same length as the " 62 : "vector of temperature dependent hardening functions."); 63 : 64 : // Check that the temperatures are strictly increasing 65 36 : for (unsigned int i = 1; i < len_temps; ++i) 66 18 : if (_hf_temperatures[i] <= _hf_temperatures[i - 1]) 67 0 : mooseError("The temperature dependent hardening functions and corresponding temperatures " 68 : "should be listed in order of increasing temperature."); 69 : 70 : std::vector<Real> yield_stress_vec; 71 54 : for (unsigned int i = 0; i < len; ++i) 72 : { 73 36 : const PiecewiseLinear * const f = dynamic_cast<const PiecewiseLinear *>( 74 36 : &this->getFunctionByName(_hardening_functions_names[i])); 75 36 : if (!f) 76 0 : mooseError("Function ", _hardening_functions_names[i], " not found in ", this->name()); 77 : 78 36 : _hardening_functions[i] = f; 79 : 80 36 : yield_stress_vec.push_back(f->value(0.0, Point())); 81 : } 82 : 83 36 : _interp_yield_stress = std::make_unique<LinearInterpolation>(_hf_temperatures, yield_stress_vec); 84 18 : } 85 : 86 : template <bool is_ad> 87 : void 88 37824 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeStressInitialize( 89 : const GenericReal<is_ad> & effectiveTrialStress, 90 : const GenericRankFourTensor<is_ad> & elasticity_tensor) 91 : { 92 12368 : RadialReturnStressUpdateTempl<is_ad>::computeStressInitialize(effectiveTrialStress, 93 : elasticity_tensor); 94 37824 : initializeHardeningFunctions(); 95 37824 : computeYieldStress(elasticity_tensor); 96 : 97 37824 : this->_yield_condition = 98 37824 : effectiveTrialStress - this->_hardening_variable_old[_qp] - this->_yield_stress; 99 37824 : this->_hardening_variable[_qp] = this->_hardening_variable_old[_qp]; 100 37824 : this->_plastic_strain[_qp] = this->_plastic_strain_old[_qp]; 101 37824 : } 102 : 103 : template <bool is_ad> 104 : void 105 37824 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::initializeHardeningFunctions() 106 : { 107 37824 : const Real temp = MetaPhysicL::raw_value(this->_temperature[_qp]); 108 37824 : if (temp > _hf_temperatures[0] && temp < _hf_temperatures.back()) 109 : { 110 75648 : for (unsigned int i = 0; i < _hf_temperatures.size() - 1; ++i) 111 : { 112 37824 : if (temp >= _hf_temperatures[i] && temp < _hf_temperatures[i + 1]) 113 : { 114 37824 : _hf_index_lo = i; 115 37824 : _hf_index_hi = i + 1; 116 37824 : _hf_fraction = 117 37824 : (temp - _hf_temperatures[i]) / (_hf_temperatures[i + 1] - _hf_temperatures[i]); 118 : } 119 : } 120 : } 121 0 : else if (temp <= _hf_temperatures[0]) 122 : { 123 0 : _hf_index_lo = 0; 124 0 : _hf_index_hi = _hf_index_lo; 125 0 : _hf_fraction = 0.0; 126 : } 127 0 : else if (temp >= _hf_temperatures.back()) 128 : { 129 0 : _hf_index_lo = _hf_temperatures.size() - 1; 130 0 : _hf_index_hi = _hf_index_lo; 131 0 : _hf_fraction = 1.0; 132 : } 133 : 134 37824 : if (_hf_fraction < 0.0) 135 0 : mooseError("The hardening function fraction cannot be less than zero."); 136 37824 : } 137 : 138 : template <bool is_ad> 139 : GenericReal<is_ad> 140 71556 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeHardeningValue( 141 : const GenericReal<is_ad> & scalar) 142 : { 143 71556 : const Real strain = this->_effective_inelastic_strain_old[_qp] + MetaPhysicL::raw_value(scalar); 144 71556 : const GenericReal<is_ad> stress = 145 71556 : (1.0 - _hf_fraction) * _hardening_functions[_hf_index_lo]->value(strain, Point()) + 146 71556 : _hf_fraction * _hardening_functions[_hf_index_hi]->value(strain, Point()); 147 : 148 71556 : return stress - this->_yield_stress; 149 : } 150 : 151 : template <bool is_ad> 152 : GenericReal<is_ad> 153 47612 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeHardeningDerivative( 154 : const GenericReal<is_ad> & /*scalar*/) 155 : { 156 47612 : const Real strain_old = this->_effective_inelastic_strain_old[_qp]; 157 : 158 95224 : return (1.0 - _hf_fraction) * 159 47612 : _hardening_functions[_hf_index_lo]->timeDerivative(strain_old, Point()) + 160 47612 : _hf_fraction * _hardening_functions[_hf_index_hi]->timeDerivative(strain_old, Point()); 161 : } 162 : 163 : template <bool is_ad> 164 : void 165 37824 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeYieldStress( 166 : const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/) 167 : { 168 37824 : this->_yield_stress = 169 37824 : _interp_yield_stress->sample(MetaPhysicL::raw_value(this->_temperature[_qp])); 170 37824 : if (this->_yield_stress <= 0.0) 171 0 : mooseError("The yield stress must be greater than zero, but during the simulation your yield " 172 : "stress became less than zero."); 173 37824 : } 174 : 175 : template class TemperatureDependentHardeningStressUpdateTempl<false>; 176 : template class TemperatureDependentHardeningStressUpdateTempl<true>;