LCOV - code coverage report
Current view: top level - src/materials/lagrangian - ComputeLagrangianStressPK1.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #33390 (250e9c) with base 846a5c Lines: 33 39 84.6 %
Date: 2026-07-31 18:20:40 Functions: 4 4 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 "ComputeLagrangianStressPK1.h"
      11             : 
      12             : InputParameters
      13         316 : ComputeLagrangianStressPK1::validParams()
      14             : {
      15         316 :   InputParameters params = ComputeLagrangianStressBase::validParams();
      16             : 
      17         316 :   params.addClassDescription("Stress update based on the first Piola-Kirchhoff stress");
      18             : 
      19         316 :   return params;
      20           0 : }
      21             : 
      22         237 : ComputeLagrangianStressPK1::ComputeLagrangianStressPK1(const InputParameters & parameters)
      23             :   : ComputeLagrangianStressBase(parameters),
      24         237 :     _inv_df(getMaterialPropertyByName<RankTwoTensor>(_base_name +
      25             :                                                      "inverse_incremental_deformation_gradient")),
      26         237 :     _inv_def_grad(
      27         237 :         getMaterialPropertyByName<RankTwoTensor>(_base_name + "inverse_deformation_gradient")),
      28         711 :     _F(getMaterialPropertyByName<RankTwoTensor>(_base_name + "deformation_gradient"))
      29             : {
      30         237 : }
      31             : 
      32             : void
      33     3700552 : ComputeLagrangianStressPK1::computeQpStressUpdate()
      34             : {
      35     3700552 :   computeQpPK1Stress();
      36     3700552 :   computeQpCauchyStress(); // This could be "switched"
      37     3700552 : }
      38             : 
      39             : void
      40      160600 : ComputeLagrangianStressPK1::computeQpCauchyStress()
      41             : {
      42             :   // Wrap PK1 -> sigma using the *unstabilized* F. F-bar enters only through the constitutive
      43             :   // PK1's strain dependence (via the F-bar'd `_f_inv`); the geometric wrap uses F_ust so
      44             :   // the residual matches OLD.
      45             :   //
      46             :   // All RankFourTensor algebra below builds Jacobian-only quantities
      47             :   // (`_cauchy_jacobian`, the post-multiplied `_pk1_jacobian`, and `_pk1_jacobian_bypass_fbar`).
      48             :   // Skip them on residual-only sweeps.
      49      160600 :   const bool need_jacobian = _fe_problem.currentlyComputingJacobian() ||
      50      130784 :                              _fe_problem.currentlyComputingResidualAndJacobian();
      51      160600 :   if (_large_kinematics)
      52             :   {
      53      160600 :     const RankTwoTensor F_ust_inv = _F_ust[_qp].inverse();
      54      160600 :     const RankTwoTensor F_ust_invT = F_ust_inv.transpose();
      55      160600 :     const Real J_ust = _F_ust[_qp].det();
      56      160600 :     _cauchy_stress[_qp] = _pk1_stress[_qp] * _F_ust[_qp].transpose() / J_ust;
      57             : 
      58      160600 :     if (!need_jacobian)
      59             :       return;
      60             : 
      61             :     usingTensorIndices(i_, j_, m_, n_);
      62             :     const auto I = RankTwoTensor::Identity();
      63             : 
      64             :     // dsigma/d(F_ust) via the constitutive PK1's F_stab chain plus the geometric F_ust pieces.
      65             :     //   sigma = (1/J(F_ust)) * PK1(F_stab) * F_ust^T
      66             :     //   dsigma/d(F_ust) = (1/J) * dPK1/d(F_stab) * d(F_stab)/d(F_ust) * F_ust^T
      67             :     //               + (1/J) * PK1 * d(F_ust^T)/d(F_ust)
      68             :     //               - sigma (x) F_ust^{-T}.
      69             :     // The middle factor `_d_F_stab_d_F_ust` is IdentityFour when F-bar is off, so the
      70             :     // first line collapses to the original PK1-jacobian chain.
      71             :     // Common geometric pieces (independent of F-bar):
      72       29816 :     const RankFourTensor dsigma_dF_geom = _pk1_stress[_qp].times<i_, n_, j_, m_>(I) / J_ust -
      73       59632 :                                           _cauchy_stress[_qp].times<i_, j_, n_, m_>(F_ust_inv);
      74             :     // dsigma_dF with the constitutive PK1 jacobian chained via F-bar (default path).
      75             :     RankFourTensor dsigma_dF =
      76       29816 :         (_pk1_jacobian[_qp] * _d_F_stab_d_F_ust[_qp]).singleProductJ(_F_ust[_qp]) / J_ust;
      77       29816 :     dsigma_dF += dsigma_dF_geom;
      78       29816 :     _cauchy_jacobian[_qp] = dsigma_dF * _d_deformation_gradient_increment_d_F[_qp].inverse();
      79             : 
      80             :     // Bypass-F-bar variant: sigma chain without the `_d_F_stab_d_F_ust` factor. Same
      81             :     // geometric pieces; constitutive PK1 jacobian used directly.
      82       29816 :     RankFourTensor dsigma_dF_no_fbar = _pk1_jacobian[_qp].singleProductJ(_F_ust[_qp]) / J_ust;
      83       29816 :     dsigma_dF_no_fbar += dsigma_dF_geom;
      84             : 
      85             :     // Update _pk1_jacobian and publish the bypass variant.
      86       29816 :     const RankFourTensor pk1_jac_no_fbar = _pk1_jacobian[_qp];
      87       29816 :     _pk1_jacobian[_qp] = _pk1_jacobian[_qp] * _d_F_stab_d_F_ust[_qp];
      88       29816 :     _pk1_jacobian_bypass_fbar[_qp] = pk1_jac_no_fbar;
      89             :   }
      90             :   // Small deformations: sigma = PK1 (no wrap). For TL, the kernel chain wants
      91             :   // dPK1/d(F_ust) -- pk1_jacobian (constitutive's dPK1/d(F_stab)) must be chained to
      92             :   // F_ust via `_d_F_stab_d_F_ust`. For UL, cauchy_jacobian = dsigma/d(dL) = pk1_jacobian
      93             :   // (since the constitutive's dPK1/d(F_stab) is essentially dsigma/d(dL) at small kin).
      94             :   else
      95             :   {
      96           0 :     _cauchy_stress[_qp] = _pk1_stress[_qp];
      97           0 :     if (!need_jacobian)
      98             :       return;
      99           0 :     _cauchy_jacobian[_qp] = _pk1_jacobian[_qp];
     100           0 :     _pk1_jacobian_bypass_fbar[_qp] = _pk1_jacobian[_qp];
     101           0 :     _pk1_jacobian[_qp] = _pk1_jacobian[_qp] * _d_F_stab_d_F_ust[_qp];
     102             :   }
     103             : }

Generated by: LCOV version 1.14