LCOV - code coverage report
Current view: top level - src/materials - ConcreteExpansionMicrocrackingDamage.C (source / functions) Hit Total Coverage
Test: idaholab/blackbear: 75f23c Lines: 75 76 98.7 %
Date: 2025-07-17 04:05:57 Functions: 5 5 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 "ConcreteExpansionMicrocrackingDamage.h"
      16             : #include "ElasticityTensorTools.h"
      17             : 
      18             : registerMooseObject("BlackBearApp", ConcreteExpansionMicrocrackingDamage);
      19             : 
      20             : InputParameters
      21         571 : ConcreteExpansionMicrocrackingDamage::validParams()
      22             : {
      23         571 :   InputParameters params = ScalarDamageBase::validParams();
      24         571 :   params.addClassDescription("Scalar damage model based on extent of internal expansion");
      25             : 
      26        1142 :   params.addRequiredParam<MaterialPropertyName>(
      27             :       "microcracking_eigenstrain_name",
      28             :       "Name of the eigenstrain driving the microcracking damage process");
      29             : 
      30        1142 :   params.addParam<bool>("assume_isotropic_expansion",
      31        1142 :                         true,
      32             :                         "Indicates whether the model assumes an isotropic expansion (true) or "
      33             :                         "computes the linear expansion based on the first principal eigenstrain "
      34             :                         "(false)");
      35             : 
      36        1142 :   params.addParam<bool>("include_confinement_effects",
      37        1142 :                         true,
      38             :                         "Indicates whether the damage is affected by the current stress state");
      39             : 
      40        1142 :   params.addParam<Real>("eigenstrain_factor",
      41        1142 :                         1.0,
      42             :                         "Correction factor by which the eigenstrain is multiplied before "
      43             :                         "evaluating the damage");
      44             : 
      45        1142 :   params.addRequiredRangeCheckedParam<Real>(
      46             :       "microcracking_initiation_strain",
      47             :       "microcracking_initiation_strain > 0",
      48             :       "Linear strain at which the microcracking initiates (in [m/m])");
      49             : 
      50        1142 :   params.addRequiredRangeCheckedParam<Real>(
      51             :       "microcracking_strain_branch",
      52             :       "microcracking_strain_branch > 0",
      53             :       "Parameter controlling the rate at which the microcracking increases (in [m/m])");
      54             : 
      55        1142 :   params.addParam<Real>(
      56             :       "expansion_stress_limit",
      57             :       "Upper bound compressive stress beyond which damage is controlled by the external stress");
      58             : 
      59         571 :   return params;
      60           0 : }
      61             : 
      62         438 : ConcreteExpansionMicrocrackingDamage::ConcreteExpansionMicrocrackingDamage(
      63         438 :     const InputParameters & parameters)
      64             :   : ScalarDamageBase(parameters),
      65             :     GuaranteeConsumer(this),
      66         438 :     _eigenstrain_name(getParam<MaterialPropertyName>("microcracking_eigenstrain_name")),
      67         438 :     _eigenstrain(getMaterialProperty<RankTwoTensor>(_eigenstrain_name)),
      68         438 :     _eigenstrain_old(getMaterialPropertyOld<RankTwoTensor>(_eigenstrain_name)),
      69         876 :     _assume_isotropic_expansion(getParam<bool>("assume_isotropic_expansion")),
      70         876 :     _eigenstrain_factor(getParam<Real>("eigenstrain_factor")),
      71         876 :     _epsilon_init(getParam<Real>("microcracking_initiation_strain")),
      72         876 :     _epsilon_branch(getParam<Real>("microcracking_strain_branch")),
      73         876 :     _include_confinement_effects(getParam<bool>("include_confinement_effects")),
      74        1746 :     _sigma_u(isParamValid("expansion_stress_limit") ? getParam<Real>("expansion_stress_limit")
      75             :                                                     : 0.0),
      76         876 :     _stress(getMaterialPropertyOld<RankTwoTensor>("stress")),
      77         438 :     _elasticity_tensor_name(_base_name + "elasticity_tensor"),
      78         438 :     _elasticity_tensor(getMaterialPropertyByName<RankFourTensor>(_elasticity_tensor_name)),
      79         876 :     _eigenvalues(3, 0.0)
      80             : {
      81        1227 :   if (_include_confinement_effects && !parameters.isParamSetByUser("expansion_stress_limit"))
      82           3 :     paramError("expansion_stress_limit",
      83             :                "is a required parameter for include_confinement_effects = true");
      84             : 
      85         435 :   if (_include_confinement_effects && !(_sigma_u > 0))
      86           3 :     paramError("expansion_stress_limit",
      87             :                "needs to be strictly > 0 for include_confinement_effects = true");
      88         432 : }
      89             : 
      90             : void
      91         423 : ConcreteExpansionMicrocrackingDamage::initialSetup()
      92             : {
      93         846 :   if (!hasGuaranteedMaterialProperty(_elasticity_tensor_name, Guarantee::ISOTROPIC))
      94           3 :     mooseError("ConcreteExpansionMicrocrackingDamage "
      95             :                "requires that the elasticity tensor be guaranteed isotropic");
      96         420 : }
      97             : 
      98             : void
      99      150080 : ConcreteExpansionMicrocrackingDamage::updateQpDamageIndex()
     100             : {
     101      150080 :   const Real linear_expansion = computeLinearExpansion(_eigenstrain[_qp]);
     102             :   const Real inc_linear_expansion =
     103      150080 :       linear_expansion - computeLinearExpansion(_eigenstrain_old[_qp]);
     104             : 
     105      150080 :   _damage_index[_qp] = _damage_index_old[_qp];
     106             : 
     107             :   // no additional expansion implies no additional damage
     108      150080 :   if (inc_linear_expansion < TOLERANCE)
     109       22400 :     return;
     110             : 
     111             :   // unconfined damage
     112             :   Real inc_damage_unconfined = 0.0;
     113      142800 :   if (linear_expansion > _epsilon_init)
     114             :   {
     115             :     const Real linear_expansion_eq =
     116             :         inc_linear_expansion +
     117      201264 :         std::max(0.0,
     118      100632 :                  _epsilon_init + _epsilon_branch * (1.0 + 1.0 / (1.0 - _damage_index_old[_qp])));
     119      100632 :     const Real next_damage_unconfined =
     120      100632 :         1.0 - _epsilon_branch / (linear_expansion_eq - (_epsilon_branch + _epsilon_init));
     121      201264 :     inc_damage_unconfined = std::max(0.0, next_damage_unconfined - _damage_index_old[_qp]);
     122             :   }
     123             : 
     124             :   // no stress control implies damage from unconfined expansion only
     125      142800 :   if (!_include_confinement_effects)
     126             :   {
     127       15120 :     _damage_index[_qp] = std::min(1.0, _damage_index_old[_qp] + inc_damage_unconfined);
     128       15120 :     return;
     129             :   }
     130             : 
     131             :   // confined damage
     132             :   Real inc_damage_confined = 0.0;
     133             : 
     134             :   // sum of compressive stress (positive value)
     135      127680 :   _stress[_qp].symmetricEigenvalues(_eigenvalues);
     136      342496 :   const Real sigma_compressive = -std::min(0.0, _eigenvalues[0]) - std::min(0.0, _eigenvalues[1]) -
     137      127680 :                                  std::min(0.0, _eigenvalues[2]);
     138             : 
     139      127680 :   if (sigma_compressive > 0.0)
     140             :   {
     141      115332 :     const Real E = ElasticityTensorTools::getIsotropicYoungsModulus(_elasticity_tensor[_qp]);
     142      115332 :     const Real confinement_factor = E / std::max(_sigma_u, sigma_compressive);
     143             :     const Real linear_expansion_eq =
     144             :         inc_linear_expansion +
     145      115332 :         std::max(0.0,
     146      115332 :                  _damage_index_old[_qp] / (confinement_factor * (1.0 - _damage_index_old[_qp])));
     147             : 
     148      115332 :     const Real next_damage_confined = 1.0 - 1.0 / (1.0 + confinement_factor * linear_expansion_eq);
     149      230664 :     inc_damage_confined = std::max(0.0, next_damage_confined - _damage_index_old[_qp]);
     150             :   }
     151             : 
     152             :   // combined damage as combination of unconfined + confined
     153      195580 :   const Real coef = std::max(0.0, std::min(1.0, sigma_compressive / _sigma_u));
     154      127680 :   _damage_index[_qp] = std::min(
     155      255360 :       1.0,
     156      127680 :       _damage_index_old[_qp] +
     157      377804 :           std::max(0.0, coef * inc_damage_confined + (1.0 - coef) * inc_damage_unconfined));
     158             : }
     159             : 
     160             : Real
     161      300160 : ConcreteExpansionMicrocrackingDamage::computeLinearExpansion(const RankTwoTensor & strain)
     162             : {
     163             :   // the expansion is assumed isotropic
     164      300160 :   if (_assume_isotropic_expansion)
     165      511448 :     return std::max(0.0, strain(0, 0) * _eigenstrain_factor);
     166             : 
     167             :   // otherwise we use the principal expansion directions
     168             :   else
     169             :   {
     170       31024 :     strain.symmetricEigenvalues(_eigenvalues);
     171       31024 :     return std::max(std::max(0.0, _eigenvalues[0] * _eigenstrain_factor),
     172       31024 :                     std::max(std::max(0.0, _eigenvalues[1] * _eigenstrain_factor),
     173       62048 :                              std::max(0.0, _eigenvalues[2] * _eigenstrain_factor)));
     174             :   }
     175             : }

Generated by: LCOV version 1.14