LCOV - code coverage report
Current view: top level - src/materials - TemperatureDependentHardeningStressUpdate.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 66 81 81.5 %
Date: 2025-07-25 05:00:39 Functions: 14 14 100.0 %
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 "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>;

Generated by: LCOV version 1.14