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 "TemperatureDependentHardeningStressUpdate.h" 11 : 12 : #include "PiecewiseLinear.h" 13 : #include "ElasticityTensorTools.h" 14 : 15 : registerMooseObject("SolidMechanicsApp", TemperatureDependentHardeningStressUpdate); 16 : registerMooseObject("SolidMechanicsApp", ADTemperatureDependentHardeningStressUpdate); 17 : 18 : template <bool is_ad> 19 : InputParameters 20 48 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::validParams() 21 : { 22 48 : InputParameters params = IsotropicPlasticityStressUpdateTempl<is_ad>::validParams(); 23 48 : 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 48 : params.set<Real>("yield_stress") = 1.0; 29 48 : params.set<Real>("hardening_constant") = 1.0; 30 : 31 48 : params.suppressParameter<Real>("yield_stress"); 32 48 : params.suppressParameter<FunctionName>("yield_stress_function"); 33 48 : params.suppressParameter<Real>("hardening_constant"); 34 48 : params.suppressParameter<FunctionName>("hardening_function"); 35 : 36 96 : params.addRequiredParam<std::vector<FunctionName>>( 37 : "hardening_functions", 38 : "List of functions of true stress as function of plastic strain at different temperatures"); 39 96 : params.addRequiredParam<std::vector<Real>>( 40 : "temperatures", 41 : "List of temperatures corresponding to the functions listed in 'hardening_functions'"); 42 : 43 48 : return params; 44 0 : } 45 : 46 : template <bool is_ad> 47 36 : TemperatureDependentHardeningStressUpdateTempl< 48 : is_ad>::TemperatureDependentHardeningStressUpdateTempl(const InputParameters & parameters) 49 : : IsotropicPlasticityStressUpdateTempl<is_ad>(parameters), 50 72 : _hardening_functions_names( 51 : this->template getParam<std::vector<FunctionName>>("hardening_functions")), 52 144 : _hf_temperatures(this->template getParam<std::vector<Real>>("temperatures")) 53 : { 54 36 : const unsigned int len = _hardening_functions_names.size(); 55 36 : if (len < 2) 56 0 : mooseError("At least two stress-strain curves must be provided in hardening_functions"); 57 36 : _hardening_functions.resize(len); 58 : 59 36 : const unsigned int len_temps = _hf_temperatures.size(); 60 36 : 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 72 : for (unsigned int i = 1; i < len_temps; ++i) 66 36 : 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 108 : for (unsigned int i = 0; i < len; ++i) 72 : { 73 72 : const PiecewiseLinear * const f = dynamic_cast<const PiecewiseLinear *>( 74 72 : &this->getFunctionByName(_hardening_functions_names[i])); 75 72 : if (!f) 76 0 : mooseError("Function ", _hardening_functions_names[i], " not found in ", this->name()); 77 : 78 72 : _hardening_functions[i] = f; 79 : 80 72 : yield_stress_vec.push_back(f->value(0.0, Point())); 81 : } 82 : 83 72 : _interp_yield_stress = std::make_unique<LinearInterpolation>(_hf_temperatures, yield_stress_vec); 84 36 : } 85 : 86 : template <bool is_ad> 87 : void 88 71680 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeStressInitialize( 89 : const GenericReal<is_ad> & effectiveTrialStress, 90 : const GenericRankFourTensor<is_ad> & elasticity_tensor) 91 : { 92 22752 : RadialReturnStressUpdateTempl<is_ad>::computeStressInitialize(effectiveTrialStress, 93 : elasticity_tensor); 94 71680 : initializeHardeningFunctions(); 95 71680 : computeYieldStress(elasticity_tensor); 96 : 97 71680 : this->_yield_condition = 98 71680 : effectiveTrialStress - this->_hardening_variable_old[_qp] - this->_yield_stress; 99 71680 : this->_hardening_variable[_qp] = this->_hardening_variable_old[_qp]; 100 71680 : this->_plastic_strain[_qp] = this->_plastic_strain_old[_qp]; 101 71680 : } 102 : 103 : template <bool is_ad> 104 : void 105 71680 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::initializeHardeningFunctions() 106 : { 107 71680 : const Real temp = MetaPhysicL::raw_value(this->_temperature[_qp]); 108 71680 : if (temp > _hf_temperatures[0] && temp < _hf_temperatures.back()) 109 : { 110 143360 : for (unsigned int i = 0; i < _hf_temperatures.size() - 1; ++i) 111 : { 112 71680 : if (temp >= _hf_temperatures[i] && temp < _hf_temperatures[i + 1]) 113 : { 114 71680 : _hf_index_lo = i; 115 71680 : _hf_index_hi = i + 1; 116 71680 : _hf_fraction = 117 71680 : (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 71680 : if (_hf_fraction < 0.0) 135 0 : mooseError("The hardening function fraction cannot be less than zero."); 136 71680 : } 137 : 138 : template <bool is_ad> 139 : GenericReal<is_ad> 140 140088 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeHardeningValue( 141 : const GenericReal<is_ad> & scalar) 142 : { 143 140088 : const Real strain = this->_effective_inelastic_strain_old[_qp] + MetaPhysicL::raw_value(scalar); 144 140088 : const GenericReal<is_ad> stress = 145 140088 : (1.0 - _hf_fraction) * _hardening_functions[_hf_index_lo]->value(strain, Point()) + 146 140088 : _hf_fraction * _hardening_functions[_hf_index_hi]->value(strain, Point()); 147 : 148 140088 : return stress - this->_yield_stress; 149 : } 150 : 151 : template <bool is_ad> 152 : GenericReal<is_ad> 153 93392 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeHardeningDerivative( 154 : const GenericReal<is_ad> & /*scalar*/) 155 : { 156 93392 : const Real strain_old = this->_effective_inelastic_strain_old[_qp]; 157 : 158 186784 : return (1.0 - _hf_fraction) * 159 93392 : _hardening_functions[_hf_index_lo]->timeDerivative(strain_old, Point()) + 160 93392 : _hf_fraction * _hardening_functions[_hf_index_hi]->timeDerivative(strain_old, Point()); 161 : } 162 : 163 : template <bool is_ad> 164 : void 165 71680 : TemperatureDependentHardeningStressUpdateTempl<is_ad>::computeYieldStress( 166 : const GenericRankFourTensor<is_ad> & /*elasticity_tensor*/) 167 : { 168 71680 : this->_yield_stress = 169 71680 : _interp_yield_stress->sample(MetaPhysicL::raw_value(this->_temperature[_qp])); 170 71680 : 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 71680 : } 174 : 175 : template class TemperatureDependentHardeningStressUpdateTempl<false>; 176 : template class TemperatureDependentHardeningStressUpdateTempl<true>;