LCOV - code coverage report
Current view: top level - src/materials - CappedDruckerPragerCosseratStressUpdate.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: f45d79 Lines: 55 63 87.3 %
Date: 2025-07-25 05:00:39 Functions: 5 5 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 "CappedDruckerPragerCosseratStressUpdate.h"
      11             : 
      12             : registerMooseObject("SolidMechanicsApp", CappedDruckerPragerCosseratStressUpdate);
      13             : 
      14             : InputParameters
      15         168 : CappedDruckerPragerCosseratStressUpdate::validParams()
      16             : {
      17         168 :   InputParameters params = CappedDruckerPragerStressUpdate::validParams();
      18         168 :   params.addClassDescription("Capped Drucker-Prager plasticity stress calculator for the Cosserat "
      19             :                              "situation where the host medium (ie, the limit where all Cosserat "
      20             :                              "effects are zero) is isotropic.  Note that the return-map flow rule "
      21             :                              "uses an isotropic elasticity tensor built with the 'host' properties "
      22             :                              "defined by the user.");
      23         336 :   params.addRequiredRangeCheckedParam<Real>("host_youngs_modulus",
      24             :                                             "host_youngs_modulus>0",
      25             :                                             "Young's modulus for the isotropic host medium");
      26         336 :   params.addRequiredRangeCheckedParam<Real>("host_poissons_ratio",
      27             :                                             "host_poissons_ratio>=0 & host_poissons_ratio<0.5",
      28             :                                             "Poisson's ratio for the isotropic host medium");
      29         168 :   return params;
      30           0 : }
      31             : 
      32         126 : CappedDruckerPragerCosseratStressUpdate::CappedDruckerPragerCosseratStressUpdate(
      33         126 :     const InputParameters & parameters)
      34             :   : CappedDruckerPragerStressUpdate(parameters),
      35         504 :     _shear(getParam<Real>("host_youngs_modulus") /
      36         378 :            (2.0 * (1.0 + getParam<Real>("host_poissons_ratio"))))
      37             : {
      38         252 :   const Real young = getParam<Real>("host_youngs_modulus");
      39         252 :   const Real poisson = getParam<Real>("host_poissons_ratio");
      40         126 :   const Real lambda = young * poisson / ((1.0 + poisson) * (1.0 - 2.0 * poisson));
      41         126 :   _Ehost.fillFromInputVector({lambda, _shear}, RankFourTensor::symmetric_isotropic);
      42         126 : }
      43             : 
      44             : void
      45        7200 : CappedDruckerPragerCosseratStressUpdate::setEppEqq(const RankFourTensor & /*Eijkl*/,
      46             :                                                    Real & Epp,
      47             :                                                    Real & Eqq) const
      48             : {
      49        7200 :   Epp = _Ehost.sum3x3();
      50        7200 :   Eqq = _shear;
      51        7200 : }
      52             : 
      53             : void
      54        7200 : CappedDruckerPragerCosseratStressUpdate::setStressAfterReturn(const RankTwoTensor & stress_trial,
      55             :                                                               Real p_ok,
      56             :                                                               Real q_ok,
      57             :                                                               Real /*gaE*/,
      58             :                                                               const std::vector<Real> & /*intnl*/,
      59             :                                                               const yieldAndFlow & /*smoothed_q*/,
      60             :                                                               const RankFourTensor & /*Eijkl*/,
      61             :                                                               RankTwoTensor & stress) const
      62             : {
      63             :   // symm_stress is the symmetric part of the stress tensor.
      64             :   // symm_stress = (s_ij+s_ji)/2 + de_ij tr(stress) / 3
      65             :   //             = q / q_trial * (s_ij^trial+s_ji^trial)/2 + de_ij p / 3
      66             :   //             = q / q_trial * (symm_stress_ij^trial - de_ij tr(stress^trial) / 3) + de_ij p / 3
      67        7200 :   const Real p_trial = stress_trial.trace();
      68       14400 :   RankTwoTensor symm_stress = RankTwoTensor(RankTwoTensor::initIdentity) / 3.0 *
      69        7200 :                               (p_ok - (_in_q_trial == 0.0 ? 0.0 : p_trial * q_ok / _in_q_trial));
      70        7200 :   if (_in_q_trial > 0)
      71        7200 :     symm_stress += q_ok / _in_q_trial * 0.5 * (stress_trial + stress_trial.transpose());
      72        7200 :   stress = symm_stress + 0.5 * (stress_trial - stress_trial.transpose());
      73        7200 : }
      74             : 
      75             : void
      76         160 : CappedDruckerPragerCosseratStressUpdate::consistentTangentOperator(
      77             :     const RankTwoTensor & /*stress_trial*/,
      78             :     Real /*p_trial*/,
      79             :     Real /*q_trial*/,
      80             :     const RankTwoTensor & stress,
      81             :     Real /*p*/,
      82             :     Real q,
      83             :     Real gaE,
      84             :     const yieldAndFlow & smoothed_q,
      85             :     const RankFourTensor & Eijkl,
      86             :     bool compute_full_tangent_operator,
      87             :     RankFourTensor & cto) const
      88             : {
      89         160 :   if (!compute_full_tangent_operator)
      90             :   {
      91           0 :     cto = Eijkl;
      92           0 :     return;
      93             :   }
      94             : 
      95         160 :   RankFourTensor EAijkl;
      96         640 :   for (unsigned i = 0; i < _tensor_dimensionality; ++i)
      97        1920 :     for (unsigned j = 0; j < _tensor_dimensionality; ++j)
      98        5760 :       for (unsigned k = 0; k < _tensor_dimensionality; ++k)
      99       17280 :         for (unsigned l = 0; l < _tensor_dimensionality; ++l)
     100             :         {
     101       12960 :           cto(i, j, k, l) = 0.5 * (Eijkl(i, j, k, l) + Eijkl(j, i, k, l));
     102       12960 :           EAijkl(i, j, k, l) = 0.5 * (Eijkl(i, j, k, l) - Eijkl(j, i, k, l));
     103             :         }
     104             : 
     105             :   const RankTwoTensor s_over_q =
     106         320 :       (q == 0.0 ? RankTwoTensor()
     107         640 :                 : (0.5 * (stress + stress.transpose()) -
     108         800 :                    stress.trace() * RankTwoTensor(RankTwoTensor::initIdentity) / 3.0) /
     109             :                       q);
     110         160 :   const RankTwoTensor E_s_over_q = Eijkl.innerProductTranspose(s_over_q); // not symmetric in kl
     111             :   const RankTwoTensor Ekl =
     112         160 :       RankTwoTensor(RankTwoTensor::initIdentity).initialContraction(Eijkl); // symmetric in kl
     113             : 
     114         640 :   for (unsigned i = 0; i < _tensor_dimensionality; ++i)
     115        1920 :     for (unsigned j = 0; j < _tensor_dimensionality; ++j)
     116        5760 :       for (unsigned k = 0; k < _tensor_dimensionality; ++k)
     117       17280 :         for (unsigned l = 0; l < _tensor_dimensionality; ++l)
     118             :         {
     119       21600 :           cto(i, j, k, l) -= (i == j) * (1.0 / 3.0) *
     120       12960 :                              (Ekl(k, l) * (1.0 - _dp_dpt) + 0.5 * E_s_over_q(k, l) * (-_dp_dqt));
     121       12960 :           cto(i, j, k, l) -=
     122       12960 :               s_over_q(i, j) * (Ekl(k, l) * (-_dq_dpt) + 0.5 * E_s_over_q(k, l) * (1.0 - _dq_dqt));
     123             :         }
     124             : 
     125         160 :   if (smoothed_q.dg[1] != 0.0)
     126             :   {
     127         192 :     const RankFourTensor Tijab = _Ehost * (gaE / _Epp) * smoothed_q.dg[1] * d2qdstress2(stress);
     128          96 :     RankFourTensor inv = RankFourTensor(RankFourTensor::initIdentitySymmetricFour) + Tijab;
     129             :     try
     130             :     {
     131          96 :       inv = inv.transposeMajor().invSymm();
     132             :     }
     133           0 :     catch (const MooseException & e)
     134             :     {
     135             :       // Cannot form the inverse, so probably at some degenerate place in stress space.
     136             :       // Just return with the "best estimate" of the cto.
     137           0 :       mooseWarning("CappedDruckerPragerCosseratStressUpdate: Cannot invert 1+T in consistent "
     138             :                    "tangent operator computation at quadpoint ",
     139           0 :                    _qp,
     140             :                    " of element ",
     141           0 :                    _current_elem->id());
     142             :       return;
     143           0 :     }
     144          96 :     cto = (cto.transposeMajor() * inv).transposeMajor();
     145             :   }
     146         160 :   cto += EAijkl;
     147             : }

Generated by: LCOV version 1.14