LCOV - code coverage report
Current view: top level - src/userobjects - SolidMechanicsPlasticDruckerPragerHyperbolic.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #31405 (292dce) with base fef103 Lines: 97 116 83.6 %
Date: 2025-09-04 07:57:23 Functions: 6 10 60.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 "SolidMechanicsPlasticDruckerPragerHyperbolic.h"
      11             : #include "RankFourTensor.h"
      12             : #include "libmesh/utility.h"
      13             : 
      14             : registerMooseObject("SolidMechanicsApp", SolidMechanicsPlasticDruckerPragerHyperbolic);
      15             : registerMooseObjectRenamed("SolidMechanicsApp",
      16             :                            TensorMechanicsPlasticDruckerPragerHyperbolic,
      17             :                            "01/01/2025 00:00",
      18             :                            SolidMechanicsPlasticDruckerPragerHyperbolic);
      19             : 
      20             : InputParameters
      21         298 : SolidMechanicsPlasticDruckerPragerHyperbolic::validParams()
      22             : {
      23         298 :   InputParameters params = SolidMechanicsPlasticDruckerPrager::validParams();
      24         596 :   params.addParam<bool>("use_custom_returnMap",
      25         596 :                         true,
      26             :                         "Whether to use the custom returnMap "
      27             :                         "algorithm.  Set to true if you are using "
      28             :                         "isotropic elasticity.");
      29         596 :   params.addParam<bool>("use_custom_cto",
      30         596 :                         true,
      31             :                         "Whether to use the custom consistent tangent "
      32             :                         "operator computations.  Set to true if you are "
      33             :                         "using isotropic elasticity.");
      34         298 :   params.addClassDescription("J2 plasticity, associative, with hardening");
      35         894 :   params.addRangeCheckedParam<Real>("smoother",
      36         596 :                                     0.0,
      37             :                                     "smoother>=0",
      38             :                                     "The cone vertex at J2=0 is smoothed.  The maximum mean "
      39             :                                     "stress possible, which is Cohesion*Cot(friction_angle) for "
      40             :                                     "smoother=0, becomes (Cohesion - "
      41             :                                     "smoother/3)*Cot(friction_angle).  This is a non-hardening "
      42             :                                     "parameter");
      43         894 :   params.addRangeCheckedParam<unsigned>(
      44             :       "max_iterations",
      45         596 :       40,
      46             :       "max_iterations>0",
      47             :       "Maximum iterations to use in the custom return map function");
      48         298 :   params.addClassDescription(
      49             :       "Non-associative Drucker Prager plasticity with hyperbolic smoothing of the cone tip.");
      50         298 :   return params;
      51           0 : }
      52             : 
      53         149 : SolidMechanicsPlasticDruckerPragerHyperbolic::SolidMechanicsPlasticDruckerPragerHyperbolic(
      54         149 :     const InputParameters & parameters)
      55             :   : SolidMechanicsPlasticDruckerPrager(parameters),
      56         149 :     _smoother2(Utility::pow<2>(getParam<Real>("smoother"))),
      57         298 :     _use_custom_returnMap(getParam<bool>("use_custom_returnMap")),
      58         298 :     _use_custom_cto(getParam<bool>("use_custom_cto")),
      59         447 :     _max_iters(getParam<unsigned>("max_iterations"))
      60             : {
      61         149 : }
      62             : 
      63             : Real
      64       77088 : SolidMechanicsPlasticDruckerPragerHyperbolic::yieldFunction(const RankTwoTensor & stress,
      65             :                                                             Real intnl) const
      66             : {
      67             :   Real aaa;
      68             :   Real bbb;
      69       77088 :   bothAB(intnl, aaa, bbb);
      70       77088 :   return std::sqrt(stress.secondInvariant() + _smoother2) + stress.trace() * bbb - aaa;
      71             : }
      72             : 
      73             : RankTwoTensor
      74           0 : SolidMechanicsPlasticDruckerPragerHyperbolic::df_dsig(const RankTwoTensor & stress, Real bbb) const
      75             : {
      76           0 :   return 0.5 * stress.dsecondInvariant() / std::sqrt(stress.secondInvariant() + _smoother2) +
      77           0 :          stress.dtrace() * bbb;
      78             : }
      79             : 
      80             : RankFourTensor
      81           0 : SolidMechanicsPlasticDruckerPragerHyperbolic::dflowPotential_dstress(const RankTwoTensor & stress,
      82             :                                                                      Real /*intnl*/) const
      83             : {
      84           0 :   RankFourTensor dr_dstress;
      85           0 :   dr_dstress = 0.5 * stress.d2secondInvariant() / std::sqrt(stress.secondInvariant() + _smoother2);
      86           0 :   dr_dstress += -0.5 * 0.5 * stress.dsecondInvariant().outerProduct(stress.dsecondInvariant()) /
      87           0 :                 std::pow(stress.secondInvariant() + _smoother2, 1.5);
      88           0 :   return dr_dstress;
      89             : }
      90             : 
      91             : std::string
      92           0 : SolidMechanicsPlasticDruckerPragerHyperbolic::modelName() const
      93             : {
      94           0 :   return "DruckerPragerHyperbolic";
      95             : }
      96             : 
      97             : bool
      98       77088 : SolidMechanicsPlasticDruckerPragerHyperbolic::returnMap(const RankTwoTensor & trial_stress,
      99             :                                                         Real intnl_old,
     100             :                                                         const RankFourTensor & E_ijkl,
     101             :                                                         Real ep_plastic_tolerance,
     102             :                                                         RankTwoTensor & returned_stress,
     103             :                                                         Real & returned_intnl,
     104             :                                                         std::vector<Real> & dpm,
     105             :                                                         RankTwoTensor & delta_dp,
     106             :                                                         std::vector<Real> & yf,
     107             :                                                         bool & trial_stress_inadmissible) const
     108             : {
     109       77088 :   if (!(_use_custom_returnMap))
     110           0 :     return SolidMechanicsPlasticModel::returnMap(trial_stress,
     111             :                                                  intnl_old,
     112             :                                                  E_ijkl,
     113             :                                                  ep_plastic_tolerance,
     114             :                                                  returned_stress,
     115             :                                                  returned_intnl,
     116             :                                                  dpm,
     117             :                                                  delta_dp,
     118             :                                                  yf,
     119             :                                                  trial_stress_inadmissible);
     120             : 
     121       77088 :   yf.resize(1);
     122             : 
     123       77088 :   yf[0] = yieldFunction(trial_stress, intnl_old);
     124             : 
     125       77088 :   if (yf[0] < _f_tol)
     126             :   {
     127             :     // the trial_stress is admissible
     128         480 :     trial_stress_inadmissible = false;
     129         480 :     return true;
     130             :   }
     131             : 
     132       76608 :   trial_stress_inadmissible = true;
     133       76608 :   const Real mu = E_ijkl(0, 1, 0, 1);
     134       76608 :   const Real lambda = E_ijkl(0, 0, 0, 0) - 2.0 * mu;
     135       76608 :   const Real bulky = 3.0 * lambda + 2.0 * mu;
     136       76608 :   const Real Tr_trial = trial_stress.trace();
     137       76608 :   const Real J2trial = trial_stress.secondInvariant();
     138             : 
     139             :   // Perform a Newton-Raphson to find dpm when
     140             :   // residual = (1 + dpm*mu/ll)sqrt(ll^2 - s^2) - sqrt(J2trial) = 0, with s=smoother
     141             :   // with ll = sqrt(J2 + s^2) = aaa - bbb*Tr(stress) = aaa - bbb(Tr_trial - p*3*bulky*bbb_flow)
     142             :   Real aaa;
     143             :   Real daaa;
     144             :   Real bbb;
     145             :   Real dbbb;
     146             :   Real bbb_flow;
     147             :   Real dbbb_flow;
     148             :   Real ll;
     149             :   Real dll;
     150             :   Real residual;
     151             :   Real jac;
     152       76608 :   dpm[0] = 0;
     153             :   unsigned int iter = 0;
     154             :   do
     155             :   {
     156      529400 :     bothAB(intnl_old + dpm[0], aaa, bbb);
     157      529400 :     dbothAB(intnl_old + dpm[0], daaa, dbbb);
     158      529400 :     onlyB(intnl_old + dpm[0], dilation, bbb_flow);
     159      529400 :     donlyB(intnl_old + dpm[0], dilation, dbbb_flow);
     160      529400 :     ll = aaa - bbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow);
     161      529400 :     dll = daaa - dbbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow) +
     162      529400 :           bbb * bulky * 3 * (bbb_flow + dpm[0] * dbbb_flow);
     163      529400 :     residual = bbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow) - aaa +
     164      529400 :                std::sqrt(J2trial / Utility::pow<2>(1 + dpm[0] * mu / ll) + _smoother2);
     165      529400 :     jac = dbbb * (Tr_trial - dpm[0] * bulky * 3 * bbb_flow) -
     166      529400 :           bbb * bulky * 3 * (bbb_flow + dpm[0] * dbbb_flow) - daaa +
     167      529400 :           0.5 * J2trial * (-2.0) * (mu / ll - dpm[0] * mu * dll / ll / ll) /
     168      529400 :               Utility::pow<3>(1 + dpm[0] * mu / ll) /
     169      529400 :               std::sqrt(J2trial / Utility::pow<2>(1.0 + dpm[0] * mu / ll) + _smoother2);
     170      529400 :     dpm[0] += -residual / jac;
     171      529400 :     if (iter > _max_iters) // not converging
     172             :       return false;
     173      529400 :     iter++;
     174      529400 :   } while (residual * residual > _f_tol * _f_tol);
     175             : 
     176             :   // set the returned values
     177       76608 :   yf[0] = 0;
     178       76608 :   returned_intnl = intnl_old + dpm[0];
     179             : 
     180       76608 :   bothAB(returned_intnl, aaa, bbb);
     181       76608 :   onlyB(returned_intnl, dilation, bbb_flow);
     182       76608 :   ll = aaa - bbb * (Tr_trial - dpm[0] * bulky * 3.0 * bbb_flow);
     183       76608 :   returned_stress =
     184       76608 :       trial_stress.deviatoric() / (1.0 + dpm[0] * mu / ll); // this is the deviatoric part only
     185             : 
     186       76608 :   RankTwoTensor rij = 0.5 * returned_stress.deviatoric() /
     187             :                       ll; // this is the derivatoric part the flow potential only
     188             : 
     189             :   // form the returned stress and the full flow potential
     190       76608 :   const Real returned_trace_over_3 = (aaa - ll) / bbb / 3.0;
     191      306432 :   for (unsigned i = 0; i < 3; ++i)
     192             :   {
     193      229824 :     returned_stress(i, i) += returned_trace_over_3;
     194      229824 :     rij(i, i) += bbb_flow;
     195             :   }
     196             : 
     197       76608 :   delta_dp = rij * dpm[0];
     198             : 
     199             :   return true;
     200             : }
     201             : 
     202             : RankFourTensor
     203       76608 : SolidMechanicsPlasticDruckerPragerHyperbolic::consistentTangentOperator(
     204             :     const RankTwoTensor & trial_stress,
     205             :     Real intnl_old,
     206             :     const RankTwoTensor & stress,
     207             :     Real intnl,
     208             :     const RankFourTensor & E_ijkl,
     209             :     const std::vector<Real> & cumulative_pm) const
     210             : {
     211       76608 :   if (!_use_custom_cto)
     212           0 :     return SolidMechanicsPlasticModel::consistentTangentOperator(
     213             :         trial_stress, intnl_old, stress, intnl, E_ijkl, cumulative_pm);
     214             : 
     215       76608 :   const Real mu = E_ijkl(0, 1, 0, 1);
     216       76608 :   const Real la = E_ijkl(0, 0, 0, 0) - 2.0 * mu;
     217       76608 :   const Real bulky = 3.0 * la + 2.0 * mu;
     218             :   Real bbb;
     219       76608 :   onlyB(intnl, friction, bbb);
     220             :   Real bbb_flow;
     221       76608 :   onlyB(intnl, dilation, bbb_flow);
     222             :   Real dbbb_flow;
     223       76608 :   donlyB(intnl, dilation, dbbb_flow);
     224       76608 :   const Real bbb_flow_mod = bbb_flow + cumulative_pm[0] * dbbb_flow;
     225       76608 :   const Real J2 = stress.secondInvariant();
     226       76608 :   const RankTwoTensor sij = stress.deviatoric();
     227       76608 :   const Real sq = std::sqrt(J2 + _smoother2);
     228             : 
     229             :   const Real one_over_h =
     230       76608 :       1.0 / (-dyieldFunction_dintnl(stress, intnl) + mu * J2 / Utility::pow<2>(sq) +
     231       76608 :              3.0 * bbb * bbb_flow_mod * bulky); // correct up to hard
     232             : 
     233             :   const RankTwoTensor df_dsig_timesE =
     234       76608 :       mu * sij / sq + bulky * bbb * RankTwoTensor(RankTwoTensor::initIdentity); // correct
     235             :   const RankTwoTensor rmod_timesE =
     236       76608 :       mu * sij / sq +
     237       76608 :       bulky * bbb_flow_mod * RankTwoTensor(RankTwoTensor::initIdentity); // correct up to hard
     238             : 
     239             :   const RankFourTensor coeff_ep =
     240       76608 :       E_ijkl - one_over_h * rmod_timesE.outerProduct(df_dsig_timesE); // correct
     241             : 
     242       76608 :   const RankFourTensor dr_dsig_timesE = -0.5 * mu * sij.outerProduct(sij) / Utility::pow<3>(sq) +
     243      153216 :                                         mu * stress.d2secondInvariant() / sq; // correct
     244             :   const RankTwoTensor df_dsig_E_dr_dsig =
     245       76608 :       0.5 * mu * _smoother2 * sij / Utility::pow<4>(sq); // correct
     246             : 
     247             :   const RankFourTensor coeff_si =
     248       76608 :       RankFourTensor(RankFourTensor::initIdentitySymmetricFour) +
     249       76608 :       cumulative_pm[0] *
     250      153216 :           (dr_dsig_timesE - one_over_h * rmod_timesE.outerProduct(df_dsig_E_dr_dsig));
     251             : 
     252       76608 :   RankFourTensor s_inv;
     253             :   try
     254             :   {
     255       76608 :     s_inv = coeff_si.invSymm();
     256             :   }
     257           0 :   catch (MooseException & e)
     258             :   {
     259           0 :     return coeff_ep; // when coeff_si is singular return the "linear" tangent operator
     260           0 :   }
     261             : 
     262       76608 :   return s_inv * coeff_ep;
     263             : }
     264             : 
     265             : bool
     266           0 : SolidMechanicsPlasticDruckerPragerHyperbolic::useCustomReturnMap() const
     267             : {
     268           0 :   return _use_custom_returnMap;
     269             : }
     270             : 
     271             : bool
     272       76608 : SolidMechanicsPlasticDruckerPragerHyperbolic::useCustomCTO() const
     273             : {
     274       76608 :   return _use_custom_cto;
     275             : }

Generated by: LCOV version 1.14