LCOV - code coverage report
Current view: top level - src/materials/nucleation_models - LDLNucleationMicroForce.C (source / functions) Hit Total Coverage
Test: coverage.info Lines: 50 56 89.3 %
Date: 2025-07-01 01:12:18 Functions: 3 3 100.0 %

          Line data    Source code
       1             : //* This file is part of the RACCOON application
       2             : //* being developed at Dolbow lab at Duke University
       3             : //* http://dolbow.pratt.duke.edu
       4             : 
       5             : #include "LDLNucleationMicroForce.h"
       6             : 
       7             : registerADMooseObject("raccoonApp", LDLNucleationMicroForce);
       8             : 
       9             : InputParameters
      10         152 : LDLNucleationMicroForce::validParams()
      11             : {
      12         152 :   InputParameters params = NucleationMicroForceBase::validParams();
      13             : 
      14         152 :   params.addClassDescription(
      15             :       "This class computes the external driving force for nucleation given "
      16             :       "a Drucker-Prager strength envelope developed by Larsen et al. (2024)");
      17         304 :   params.addRequiredParam<MaterialPropertyName>(
      18             :       "tensile_strength", "The tensile strength of the material beyond which the material fails.");
      19         304 :   params.addRequiredParam<MaterialPropertyName>(
      20             :       "hydrostatic_strength",
      21             :       "The hydrostatic strength of the material beyond which the material fails.");
      22         304 :   params.addParam<MaterialPropertyName>("delta", "delta", "Name of the unitless coefficient delta");
      23         304 :   params.addParam<bool>("h_correction", false, "Whether to use h correction formula for delta");
      24         152 :   return params;
      25           0 : }
      26             : 
      27          12 : LDLNucleationMicroForce::LDLNucleationMicroForce(const InputParameters & parameters)
      28             :   : NucleationMicroForceBase(parameters),
      29          36 :     _sigma_ts(getADMaterialProperty<Real>(prependBaseName("tensile_strength", true))),
      30          24 :     _sigma_hs(getADMaterialProperty<Real>(prependBaseName("hydrostatic_strength", true))),
      31          12 :     _delta(declareADProperty<Real>(prependBaseName("delta", true))),
      32          36 :     _h_correction(getParam<bool>("h_correction"))
      33             : {
      34          12 : }
      35             : 
      36             : void
      37     1035840 : LDLNucleationMicroForce::computeQpProperties()
      38             : {
      39             :   // The bulk modulus
      40     2071680 :   ADReal K = _lambda[_qp] + 2.0 * _mu[_qp] / 3.0;
      41             : 
      42             :   // The Young's modulus
      43     3107520 :   ADReal E = 9.0 * _mu[_qp] * K / (_mu[_qp] + 3.0 * K);
      44             : 
      45             :   // The mobility
      46     1035840 :   ADReal M = _Gc[_qp] / _L[_qp] / _c0[_qp];
      47             : 
      48     1035840 :   ADReal l_ch = E * _Gc[_qp] / _sigma_ts[_qp] / _sigma_ts[_qp] * 3.0 / 8.0;
      49     2071680 :   if (_L[_qp] > l_ch * 0.8)
      50       35761 :     flagSolutionWarning(
      51             :         "The reg length might be too large to construct a reasonable numerical strength surface.");
      52             : 
      53             :   // Invariants of the stress
      54     1035840 :   ADReal I1 = _stress[_qp].trace();
      55     1035840 :   ADRankTwoTensor stress_dev = _stress[_qp].deviatoric();
      56     2071680 :   ADReal J2 = 0.5 * stress_dev.doubleContraction(stress_dev);
      57             : 
      58             :   // Just to be extra careful... J2 is for sure non-negative but discretization and interpolation
      59             :   // might bring surprise
      60     1035840 :   if (J2 < 0)
      61           0 :     mooseException("Negative J2");
      62             : 
      63             :   // define zero J2's derivative
      64     1035840 :   if (MooseUtils::absoluteFuzzyEqual(J2, 0))
      65        4800 :     J2.value() = libMesh::TOLERANCE * libMesh::TOLERANCE;
      66             : 
      67             :   // Compute critical energy
      68     1035840 :   ADReal W_ts = _sigma_ts[_qp] * _sigma_ts[_qp] / 2.0 / E;
      69     1035840 :   ADReal W_hs = _sigma_hs[_qp] * _sigma_hs[_qp] / 2.0 / K;
      70             : 
      71             :   // Compute delta
      72     1035840 :   if (!_h_correction)
      73             :   {
      74             :     // Use formula without h correction
      75           0 :     _delta[_qp] = (_sigma_ts[_qp] + (1 + 2 * std::sqrt(3)) * _sigma_hs[_qp]) /
      76           0 :                       (8 + 3 * std::sqrt(3)) / _sigma_hs[_qp] * 3.0 / 16.0 *
      77           0 :                       (_Gc[_qp] / W_ts / _L[_qp]) +
      78           0 :                   3.0 / 8.0;
      79             :   }
      80             :   else
      81             :   {
      82             :     // Get mesh size of current element
      83     1035840 :     ADReal h = _current_elem->hmin();
      84             :     // if (_L[_qp]/h *_L[_qp]/l_ch > 0.16)
      85     4071840 :     if ((h > _L[_qp] * 0.5) && (_L[_qp] > l_ch * 0.7))
      86     1000083 :       flagSolutionWarning(
      87             :           "The mesh size might be too coarse for a valid h_correction in the complete "
      88             :           "model and lead to unexpected numerical strength surface. You may either refine "
      89             :           "the mesh, reduce the reg length, or turn h_correction=false.");
      90             : 
      91             :     // Use formula with h correction
      92     4143360 :     _delta[_qp] = std::pow(1 + 3.0 / 8.0 * h / _L[_qp], -2) *
      93     2071680 :                       (_sigma_ts[_qp] + (1 + 2 * std::sqrt(3.0)) * _sigma_hs[_qp]) /
      94     1035840 :                       (8 + 3 * std::sqrt(3.0)) / _sigma_hs[_qp] * 3 / 16 *
      95     1035840 :                       (_Gc[_qp] / W_ts / _L[_qp]) +
      96     4143360 :                   std::pow(1 + 3.0 / 8.0 * h / _L[_qp], -1) * 2 / 5;
      97             :   }
      98             : 
      99             :   // Parameters in the strength surface
     100             :   ADReal alpha_1 =
     101     2071680 :       -_delta[_qp] * _Gc[_qp] / 8.0 / _sigma_hs[_qp] / _L[_qp] + 2.0 / 3.0 * W_hs / _sigma_hs[_qp];
     102     2071680 :   ADReal alpha_2 = -(std::sqrt(3.0) / 8.0 * _delta[_qp] * (3.0 * _sigma_hs[_qp] - _sigma_ts[_qp]) /
     103     1035840 :                          (_sigma_hs[_qp] * _sigma_ts[_qp]) * _Gc[_qp] / _L[_qp] +
     104     1035840 :                      2.0 / std::sqrt(3.0) * W_hs / _sigma_hs[_qp] -
     105     2071680 :                      2.0 * std::sqrt(3.0) * W_ts / _sigma_ts[_qp]);
     106             : 
     107             :   // Compute the external driving force required to recover the desired strength envelope.
     108     1035840 :   _ex_driving[_qp] =
     109     1035840 :       alpha_2 * std::sqrt(J2) + alpha_1 * I1 +
     110     3107520 :       (1.0 - std::sqrt(I1 * I1) / I1) / std::pow(_g[_qp], 1.5) *
     111     5179200 :           (J2 / 2.0 / _mu[_qp] + I1 * I1 / 6.0 / (3.0 * _lambda[_qp] + 2.0 * _mu[_qp]));
     112             : 
     113     1035840 :   _stress_balance[_qp] =
     114     4143360 :       J2 / _mu[_qp] + std::pow(I1, 2) / 9.0 / K - _ex_driving[_qp] - M * _delta[_qp];
     115     1035840 : }

Generated by: LCOV version 1.16