LCOV - code coverage report
Current view: top level - src/materials/large_deformation_models - LargeDeformationJ2PlasticityBeBar.C (source / functions) Hit Total Coverage
Test: coverage.info Lines: 126 128 98.4 %
Date: 2026-04-22 20:21:53 Functions: 10 10 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 "EigenADReal.h"
       6             : #include "LargeDeformationJ2PlasticityBeBar.h"
       7             : #include "CNHIsotropicElasticity.h"
       8             : #include "RaccoonUtils.h"
       9             : 
      10             : registerMooseObject("raccoonApp", LargeDeformationJ2PlasticityBeBar);
      11             : 
      12             : InputParameters
      13         144 : LargeDeformationJ2PlasticityBeBar::validParams()
      14             : {
      15         144 :   InputParameters params = LargeDeformationPlasticityModel::validParams();
      16         144 :   params.addClassDescription("Large deformation $J_2$ plasticity using the bebar (modified "
      17             :                              "left Cauchy-Green) update. Elastic parameters are sourced from "
      18             :                              "the associated CNHIsotropicElasticity model.");
      19         288 :   params.addRequiredCoupledVar("phase_field", "Name of the phase-field (damage) variable");
      20         288 :   params.addParam<MaterialPropertyName>(
      21             :       "strain_energy_density_corr",
      22             :       "psie_corr",
      23             :       "Name of the strain energy density computed by this material model");
      24         288 :   params.addParam<bool>("apply_strain_energy_split",
      25         288 :                         true,
      26             :                         "Whether to apply volumetric/deviatoric split to the active strain "
      27             :                         "energy (psie_active). If true (default), only the positive part of the "
      28             :                         "energy is assigned to psie_active. If false, the full unsplit energy U + "
      29             :                         "W is used for psie_active.");
      30         144 :   return params;
      31           0 : }
      32             : 
      33           6 : LargeDeformationJ2PlasticityBeBar::LargeDeformationJ2PlasticityBeBar(
      34           6 :     const InputParameters & parameters)
      35             :   : LargeDeformationPlasticityModel(parameters),
      36             :     DerivativeMaterialPropertyNameInterface(),
      37           6 :     _bebar(declareADProperty<RankTwoTensor>(prependBaseName("be_bar"))),
      38          18 :     _bebar_old(getMaterialPropertyOldByName<RankTwoTensor>(prependBaseName("be_bar"))),
      39           6 :     _bebar_det(declareADProperty<Real>(prependBaseName("be_bar_det"))),
      40          18 :     _F_old(getMaterialPropertyOldByName<RankTwoTensor>(prependBaseName("deformation_gradient"))),
      41          12 :     _F(getADMaterialPropertyByName<RankTwoTensor>(prependBaseName("deformation_gradient"))),
      42          12 :     _d_name(getVar("phase_field", 0)->name()),
      43           6 :     _psie_name(prependBaseName("strain_energy_density_corr", true)),
      44           6 :     _psie_corr(declareADProperty<Real>(_psie_name)),
      45           6 :     _psie_active_corr(declareADProperty<Real>(_psie_name + "_active")),
      46          12 :     _dpsie_dd_corr(declareADProperty<Real>(derivativePropertyName(_psie_name, {_d_name}))),
      47           6 :     _psie_unsplit(declareADProperty<Real>(_psie_name + "_unsplit")),
      48          24 :     _apply_strain_energy_split(getParam<bool>("apply_strain_energy_split"))
      49             : {
      50           6 :   _check_range = true;
      51          12 : }
      52             : 
      53             : void
      54           6 : LargeDeformationJ2PlasticityBeBar::setElasticityModel(
      55             :     LargeDeformationElasticityModel * elasticity_model)
      56             : {
      57           6 :   auto * cnh = dynamic_cast<CNHIsotropicElasticity *>(elasticity_model);
      58           6 :   if (!cnh)
      59           0 :     mooseError(type(), ": requires a CNHIsotropicElasticity model; got ", elasticity_model->type());
      60           6 :   _K = &cnh->getK();
      61           6 :   _G = &cnh->getG();
      62           6 :   _ge = &cnh->getDegradation();
      63           6 :   _dge_dd = &cnh->getDegradationDerivative();
      64           6 :   _psie_cnh = &cnh->getPsie();
      65           6 :   _psie_active_cnh = &cnh->getPsieActive();
      66           6 :   _dpsie_dd_cnh = &cnh->getDpsieDD();
      67           6 :   LargeDeformationPlasticityModel::setElasticityModel(elasticity_model);
      68           6 : }
      69             : 
      70             : void
      71          32 : LargeDeformationJ2PlasticityBeBar::initQpStatefulProperties()
      72             : {
      73          32 :   _Fp[_qp].setToIdentity();
      74          32 :   _ep[_qp] = 0;
      75          32 :   _bebar[_qp].setToIdentity();
      76          32 : }
      77             : 
      78             : void
      79        1176 : LargeDeformationJ2PlasticityBeBar::updateState(ADRankTwoTensor & stress, ADRankTwoTensor & /*Fe*/)
      80             : {
      81             :   using std::cbrt;
      82             :   using std::sqrt;
      83             : 
      84        1176 :   ADRankTwoTensor I2;
      85        1176 :   I2.setToIdentity();
      86             : 
      87        1176 :   ADReal delta_ep = 0;
      88             : 
      89             :   // Compute incremental fbar
      90        1176 :   ADRankTwoTensor f = _F[_qp] * _F_old[_qp].inverse();
      91        1176 :   ADRankTwoTensor fbar = f / cbrt(f.det());
      92             : 
      93             :   // Compute bebar_trial
      94        1176 :   _bebar[_qp] = fbar * _bebar_old[_qp] * fbar.transpose();
      95             : 
      96             :   // Compute trial deviatoric stress and its norm
      97        2352 :   ADRankTwoTensor s_trial = (*_G)[_qp] * (*_ge)[_qp] * _bebar[_qp].deviatoric();
      98        1176 :   ADReal s_trial_norm = s_trial.doubleContraction(s_trial);
      99        1176 :   if (MooseUtils::absoluteFuzzyEqual(s_trial_norm, 0))
     100           8 :     s_trial_norm.value() = libMesh::TOLERANCE * libMesh::TOLERANCE;
     101        1176 :   s_trial_norm = sqrt(s_trial_norm);
     102             : 
     103        2352 :   _Np[_qp] = sqrt(1.5) * s_trial / s_trial_norm;
     104             : 
     105             :   // Return mapping
     106        1176 :   ADReal phi = computeResidual(s_trial_norm, delta_ep);
     107        1176 :   if (phi > 0)
     108             :   {
     109        1064 :     returnMappingSolve(s_trial_norm, delta_ep, _console);
     110             : 
     111        2128 :     _ep[_qp] = _ep_old[_qp] + delta_ep;
     112        1064 :     ADRankTwoTensor s = s_trial - (2.0 / 3.0) * (*_ge)[_qp] * (*_G)[_qp] * delta_ep *
     113        2128 :                                       _bebar[_qp].trace() * _Np[_qp];
     114             : 
     115        1064 :     ADReal J = _F[_qp].det();
     116        2128 :     ADReal p = 0.5 * (*_K)[_qp] * (J * J - 1);
     117        4256 :     ADRankTwoTensor tau = J >= 1.0 ? (*_ge)[_qp] * p * I2 + s : p * I2 + s;
     118        1064 :     stress = tau / J;
     119             : 
     120        1064 :     computeCorrectionTerm(s / (*_ge)[_qp] / (*_G)[_qp]);
     121             :   }
     122             :   else
     123             :   {
     124         112 :     _ep[_qp] = _ep_old[_qp];
     125             : 
     126         112 :     ADReal J = _F[_qp].det();
     127         224 :     ADReal p = 0.5 * (*_K)[_qp] * (J * J - 1);
     128         448 :     ADRankTwoTensor tau = J >= 1.0 ? (*_ge)[_qp] * p * I2 + s_trial : p * I2 + s_trial;
     129         224 :     stress = tau / J;
     130             :   }
     131             : 
     132        1176 :   computeStrainEnergyDensity();
     133        1176 :   _hardening_model->plasticEnergy(_ep[_qp]);
     134        1176 :   _hardening_model->plasticDissipation(delta_ep, _ep[_qp], 0);
     135             : 
     136        1176 :   if (_t_step > 0)
     137             :   {
     138        2336 :     _heat[_qp] = _hardening_model->plasticDissipation(delta_ep, _ep[_qp], 1) * delta_ep / _dt;
     139        2336 :     _heat[_qp] += _hardening_model->thermalConjugate(_ep[_qp]) * delta_ep / _dt;
     140             :   }
     141             :   else
     142           8 :     _heat[_qp] = 0;
     143             : 
     144        1176 :   _bebar_det[_qp] = _bebar[_qp].det();
     145        1176 : }
     146             : 
     147             : Real
     148        2808 : LargeDeformationJ2PlasticityBeBar::computeReferenceResidual(const ADReal & effective_trial_stress,
     149             :                                                             const ADReal & delta_ep)
     150             : {
     151        2808 :   return MetaPhysicL::raw_value(effective_trial_stress - std::sqrt(2.0 / 3.0) * (*_ge)[_qp] *
     152        2808 :                                                              (*_G)[_qp] * delta_ep *
     153        5616 :                                                              _bebar[_qp].trace());
     154             : }
     155             : 
     156             : ADReal
     157        3984 : LargeDeformationJ2PlasticityBeBar::computeResidual(const ADReal & effective_trial_stress,
     158             :                                                    const ADReal & delta_ep)
     159             : {
     160        3984 :   ADReal ep = _ep_old[_qp] + delta_ep;
     161        3984 :   return effective_trial_stress -
     162        7968 :          std::sqrt(2.0 / 3.0) * (_hardening_model->plasticEnergy(ep, 1) +
     163        3984 :                                  _hardening_model->plasticDissipation(delta_ep, ep, 1)) -
     164        7968 :          std::sqrt(2.0 / 3.0) * (*_ge)[_qp] * (*_G)[_qp] * delta_ep * _bebar[_qp].trace();
     165             : }
     166             : 
     167             : ADReal
     168        2808 : LargeDeformationJ2PlasticityBeBar::computeDerivative(const ADReal & /*effective_trial_stress*/,
     169             :                                                      const ADReal & delta_ep)
     170             : {
     171        2808 :   ADReal ep = _ep_old[_qp] + delta_ep;
     172        5616 :   return -std::sqrt(2.0 / 3.0) * (_hardening_model->plasticEnergy(ep, 2) +
     173        2808 :                                   _hardening_model->plasticDissipation(delta_ep, ep, 2)) -
     174        5616 :          std::sqrt(2.0 / 3.0) * (*_ge)[_qp] * (*_G)[_qp] * _bebar[_qp].trace();
     175             : }
     176             : 
     177             : void
     178        1064 : LargeDeformationJ2PlasticityBeBar::computeCorrectionTerm(const ADRankTwoTensor & devbebar)
     179             : {
     180             :   using std::cbrt;
     181             :   using std::sqrt;
     182             : 
     183        1064 :   ADRankTwoTensor I2(RankTwoTensorTempl<ADReal>::initIdentity);
     184             : 
     185        1064 :   ADReal a = devbebar(0, 0);
     186        1064 :   ADReal b = devbebar(1, 1);
     187        1064 :   ADReal c = devbebar(2, 2);
     188        1064 :   ADReal d = devbebar(1, 2);
     189        1064 :   ADReal e = devbebar(0, 2);
     190        1064 :   ADReal h = devbebar(0, 1);
     191             : 
     192        1064 :   ADReal A = a + b + c;
     193        1064 :   ADReal B = a * b + a * c + b * c - d * d - e * e - h * h;
     194        1064 :   ADReal C = a * b * c + 2.0 * d * e * h - a * d * d - b * e * e - c * h * h - 1.0;
     195             : 
     196             :   ADReal D = cbrt(
     197        1064 :       -2 * A * A * A +
     198        1064 :       3 * sqrt(3) *
     199        5320 :           sqrt(4 * A * A * A * C - A * A * B * B - 18 * A * B * C + 4 * B * B * B + 27 * C * C) +
     200        3192 :       9 * A * B - 27 * C);
     201             : 
     202        6384 :   ADReal Ie_bar = D / 3 / cbrt(2) - cbrt(2) * (3 * B - A * A) / 3 / D - A / 3;
     203        1064 :   _bebar[_qp] = devbebar + Ie_bar * I2;
     204        1064 : }
     205             : 
     206             : void
     207        1176 : LargeDeformationJ2PlasticityBeBar::computeStrainEnergyDensity()
     208             : {
     209             :   using std::log;
     210        1176 :   ADReal J = _F[_qp].det();
     211        3528 :   ADReal U = 0.5 * (*_K)[_qp] * (0.5 * (J * J - 1) - log(J));
     212        3528 :   ADReal W = 0.5 * (*_G)[_qp] * (_bebar[_qp].trace() - 3.0);
     213             : 
     214        1176 :   _psie_unsplit[_qp] = U + W;
     215             : 
     216        1176 :   ADReal E_el_pos = J >= 1.0 ? U + W : W;
     217        1176 :   ADReal E_el_neg = J >= 1.0 ? 0.0 : U;
     218             : 
     219        1176 :   _psie_active_corr[_qp] = _apply_strain_energy_split ? E_el_pos : _psie_unsplit[_qp];
     220        2352 :   _psie_corr[_qp] = (*_ge)[_qp] * E_el_pos + E_el_neg;
     221        2352 :   _dpsie_dd_corr[_qp] = (*_dge_dd)[_qp] * _psie_active_corr[_qp];
     222             : 
     223             :   // Overwrite CNH's energy properties so that psie_active is correct for fracture driving.
     224             :   // CNH computes these from Fe, which BeBar does not update; the bebar-based values are correct.
     225        1176 :   (*_psie_cnh)[_qp] = _psie_corr[_qp];
     226        1176 :   (*_psie_active_cnh)[_qp] = _psie_active_corr[_qp];
     227        1176 :   (*_dpsie_dd_cnh)[_qp] = _dpsie_dd_corr[_qp];
     228        1176 : }

Generated by: LCOV version 1.16