LCOV - code coverage report
Current view: top level - src/materials - SteelCreepDamageOh.C (source / functions) Hit Total Coverage
Test: idaholab/blackbear: 276f95 Lines: 77 80 96.2 %
Date: 2025-10-28 03:10:25 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /****************************************************************/
       2             : /*               DO NOT MODIFY THIS HEADER                      */
       3             : /*                       BlackBear                              */
       4             : /*                                                              */
       5             : /*           (c) 2017 Battelle Energy Alliance, LLC             */
       6             : /*                   ALL RIGHTS RESERVED                        */
       7             : /*                                                              */
       8             : /*          Prepared by Battelle Energy Alliance, LLC           */
       9             : /*            Under Contract No. DE-AC07-05ID14517              */
      10             : /*            With the U. S. Department of Energy               */
      11             : /*                                                              */
      12             : /*            See COPYRIGHT for full restrictions               */
      13             : /****************************************************************/
      14             : 
      15             : #include "SteelCreepDamageOh.h"
      16             : 
      17             : #include "RankTwoTensor.h"
      18             : #include "RankFourTensor.h"
      19             : #include "ElasticityTensorTools.h"
      20             : #include "MooseUtils.h"
      21             : #include <cmath>
      22             : #include "RankTwoScalarTools.h"
      23             : 
      24             : #include "libmesh/utility.h"
      25             : 
      26             : registerMooseObject("BlackBearApp", SteelCreepDamageOh);
      27             : registerMooseObject("BlackBearApp", ADSteelCreepDamageOh);
      28             : 
      29             : template <bool is_ad>
      30             : InputParameters
      31         165 : SteelCreepDamageOhTempl<is_ad>::validParams()
      32             : {
      33         165 :   InputParameters params = ScalarDamageBaseTempl<is_ad>::validParams();
      34         165 :   params.addClassDescription(
      35             :       "Steel scalar damage model: Material 'suddenly' loses load-carrying "
      36             :       "capacity. This can model, e.g., 316H creep failure. See Oh et al (2011).");
      37         330 :   params.addRequiredParam<Real>("epsilon_f", "Uniaxial creep fracture strain (creep ductility).");
      38         330 :   params.setDocUnit("epsilon_f", "unitless");
      39         330 :   params.addRequiredParam<Real>("creep_law_exponent", "Exponent of the creep power law.");
      40         330 :   params.setDocUnit("creep_law_exponent", "unitless");
      41         330 :   params.addParam<Real>(
      42         330 :       "reduction_factor", 1000.0, "Reduction on the load-carrying capacity (stress).");
      43         330 :   params.setDocUnit("reduction_factor", "unitless");
      44         495 :   params.addRangeCheckedParam<Real>(
      45             :       "reduction_damage_threshold",
      46         330 :       0.9,
      47             :       "reduction_damage_threshold <= 1.0 & reduction_damage_threshold >= 0.0",
      48             :       "Starting value of damage that will trigger linear reduction of "
      49             :       "quadrature point's load-carrying capacity.");
      50         330 :   params.setDocUnit("reduction_damage_threshold", "unitless");
      51         330 :   params.addRequiredParam<std::vector<std::string>>(
      52             :       "creep_strain_names", "Names of the creep strains driving the damage.");
      53         165 :   return params;
      54           0 : }
      55             : 
      56             : template <bool is_ad>
      57         126 : SteelCreepDamageOhTempl<is_ad>::SteelCreepDamageOhTempl(const InputParameters & parameters)
      58             :   : ScalarDamageBaseTempl<is_ad>(parameters),
      59             :     GuaranteeConsumer(this),
      60         126 :     _creep_strain_names(this->template getParam<std::vector<std::string>>("creep_strain_names")),
      61         126 :     _creep_model(_creep_strain_names.size()),
      62         126 :     _combined_creep_strain(this->template declareGenericProperty<RankTwoTensor, is_ad>(
      63         126 :         _base_name + "combined_creep_strain")),
      64         126 :     _combined_creep_strain_old(
      65         126 :         this->template getMaterialPropertyOld<RankTwoTensor>(_base_name + "combined_creep_strain")),
      66         252 :     _epsilon_f(this->template getParam<Real>("epsilon_f")),
      67         252 :     _reduction_factor(this->template getParam<Real>("reduction_factor")),
      68         252 :     _reduction_damage_threshold(this->template getParam<Real>("reduction_damage_threshold")),
      69         252 :     _creep_law_exponent(this->template getParam<Real>("creep_law_exponent")),
      70         126 :     _stress(this->template getGenericMaterialProperty<RankTwoTensor, is_ad>(_base_name + "stress")),
      71         252 :     _omega(this->template declareGenericProperty<Real, is_ad>(_base_name + "omega")),
      72         378 :     _omega_old(this->template getMaterialPropertyOld<Real>(_base_name + "omega"))
      73             : {
      74         252 :   for (unsigned int i = 0; i < _creep_strain_names.size(); ++i)
      75             :   {
      76         126 :     _creep_model[i] = &this->template getGenericMaterialProperty<RankTwoTensor, is_ad>(
      77             :         _base_name + _creep_strain_names[i]);
      78             :   }
      79         126 :   if (MooseUtils::absoluteFuzzyEqual(_creep_law_exponent, -0.5, TOLERANCE))
      80           0 :     this->template paramError(
      81             :         "creep_law_exponent",
      82             :         "creep_law_exponent cannot be -0.5 due to singularities in the multiaxial update of "
      83             :         "the uniaxial ductility value.");
      84         126 : }
      85             : 
      86             : template <bool is_ad>
      87             : void
      88         840 : SteelCreepDamageOhTempl<is_ad>::initQpStatefulProperties()
      89             : {
      90         840 :   ScalarDamageBaseTempl<is_ad>::initQpStatefulProperties();
      91         840 :   _omega[_qp] = 0.0;
      92         840 :   _combined_creep_strain[_qp].zero();
      93         840 : }
      94             : 
      95             : template <bool is_ad>
      96             : void
      97      234696 : SteelCreepDamageOhTempl<is_ad>::updateQpDamageIndex()
      98             : {
      99             :   Real epsilon_f_star;
     100             : 
     101      234696 :   const auto & stress = MetaPhysicL::raw_value(_stress[_qp]);
     102      234696 :   const auto & vonMises = RankTwoScalarTools::vonMisesStress(stress);
     103             : 
     104      234696 :   if (vonMises > TOLERANCE)
     105             :   {
     106      233422 :     const auto & h = RankTwoScalarTools::triaxialityStress(stress);
     107             : 
     108             :     // Let's only modify axial ductility for significant values of stress triaxiality
     109      233422 :     if (h > TOLERANCE)
     110             :       // Update creep ductility due to triaxiliaty effects
     111      200256 :       epsilon_f_star =
     112      200256 :           _epsilon_f *
     113      200256 :           std::sinh(2.0 / 3.0 * (_creep_law_exponent - 0.5) / (_creep_law_exponent + 0.5)) /
     114      200256 :           std::sinh(2.0 * (_creep_law_exponent - 0.5) / (_creep_law_exponent + 0.5) * h);
     115             :     else
     116       33166 :       epsilon_f_star = _epsilon_f;
     117             :   }
     118             :   else
     119        1274 :     epsilon_f_star = _epsilon_f;
     120             : 
     121             :   // If the value obtained from multiaxiality equation isn't reasonable, do not update damage
     122             :   // This would also cause an FPE a few lines below
     123      234696 :   if (std::abs(epsilon_f_star) < TOLERANCE)
     124             :   {
     125       40467 :     _damage_index[_qp] = _damage_index_old[_qp];
     126       40467 :     _omega[_qp] = _omega_old[_qp];
     127       40467 :     return;
     128             :   }
     129             : 
     130      194229 :   _combined_creep_strain[_qp].zero();
     131      388458 :   for (unsigned int i = 0; i < _creep_strain_names.size(); ++i)
     132      194229 :     _combined_creep_strain[_qp] += (*_creep_model[i])[_qp];
     133             : 
     134      194229 :   GenericRankTwoTensor<is_ad> creep_increment =
     135      194229 :       _combined_creep_strain[_qp] - _combined_creep_strain_old[_qp];
     136             : 
     137             :   // Avoid derivative's divide by zero error
     138             :   Real epsilon_ad = 1.0e-14;
     139             : 
     140             :   // Get equivalent creep strain increment
     141      194229 :   GenericReal<is_ad> equivalent_creep_increment =
     142      129360 :       1 / std::sqrt(2) *
     143      129549 :       std::sqrt(Utility::pow<2>(creep_increment(0, 0) - creep_increment(1, 1)) +
     144      129549 :                 Utility::pow<2>(creep_increment(1, 1) - creep_increment(2, 2)) +
     145      129549 :                 Utility::pow<2>(creep_increment(2, 2) - creep_increment(0, 0)) +
     146      194229 :                 1.5 * creep_increment(0, 1) * creep_increment(0, 1) +
     147      194229 :                 1.5 * creep_increment(1, 2) * creep_increment(1, 2) +
     148      258909 :                 1.5 * creep_increment(2, 0) * creep_increment(2, 0) + epsilon_ad);
     149             : 
     150      258909 :   _omega[_qp] = _omega_old[_qp] + equivalent_creep_increment / epsilon_f_star;
     151             : 
     152      194229 :   if (_omega[_qp] > 1.0)
     153      141729 :     _omega[_qp] = 1.0;
     154             : 
     155             :   Real threshold = MetaPhysicL::raw_value(_omega[_qp]);
     156             : 
     157      194229 :   if (threshold < _reduction_damage_threshold)
     158             :   {
     159             :     // If threshold is not reached, there is no damage.
     160       52500 :     _damage_index[_qp] = 0.0;
     161             :     return;
     162             :   }
     163             : 
     164      141729 :   if (threshold > 1.0)
     165             :     threshold = 1;
     166             : 
     167             :   // Cast damage index from the omega model to the traditional damage index.
     168      141729 :   Real factor = (threshold - _reduction_damage_threshold) / (1 - _reduction_damage_threshold) *
     169      141729 :                 _reduction_factor;
     170      141729 :   _damage_index[_qp] = 1.0 - 1.0 / factor;
     171             : 
     172             :   // Account for a corner case where threshold == _reduction_damage_threshold
     173      141729 :   if (_damage_index[_qp] < 0.0)
     174           0 :     _damage_index[_qp] = 0.0;
     175             : }
     176             : 
     177             : template class SteelCreepDamageOhTempl<false>;
     178             : template class SteelCreepDamageOhTempl<true>;

Generated by: LCOV version 1.14