LCOV - code coverage report
Current view: top level - src/materials/lagrangian - ComputeLagrangianObjectiveStress.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #33390 (250e9c) with base 846a5c Lines: 74 74 100.0 %
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 "ComputeLagrangianObjectiveStress.h"
      11             : 
      12             : InputParameters
      13        5268 : ComputeLagrangianObjectiveStress::validParams()
      14             : {
      15        5268 :   InputParameters params = ComputeLagrangianStressCauchy::validParams();
      16             : 
      17        5268 :   params.addClassDescription("Stress update based on the small (engineering) stress");
      18             : 
      19       10536 :   MooseEnum objectiveRate("truesdell jaumann green_naghdi rashid", "truesdell");
      20       10536 :   params.addParam<MooseEnum>(
      21             :       "objective_rate", objectiveRate, "Which type of objective integration to use");
      22       10536 :   params.addParam<bool>(
      23             :       "rotate_old_stress",
      24       10536 :       false,
      25             :       "If true, the rate runs in passthrough mode: `cauchy_stress = small_stress` (no outer "
      26             :       "rotation applied). Use when wrapping a material with `perform_finite_strain_rotations = "
      27             :       "true` whose own internal rotation already produces the correct cumulative Cauchy stress "
      28             :       "(needs the strain calculator to publish a non-identity `rotation_increment` via "
      29             :       "`publish_rotation_increment = true`). `cauchy_jacobian` is still computed via the rate's "
      30             :       "chain rule. Default false preserves the standard objective-rate pipeline.");
      31             : 
      32        5268 :   return params;
      33        5268 : }
      34             : 
      35        3951 : ComputeLagrangianObjectiveStress::ComputeLagrangianObjectiveStress(
      36        3951 :     const InputParameters & parameters)
      37             :   : ComputeLagrangianStressCauchy(parameters),
      38        3951 :     _small_stress(declareProperty<RankTwoTensor>(_base_name + "small_stress")),
      39        7902 :     _small_stress_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "small_stress")),
      40        3951 :     _small_jacobian(declareProperty<RankFourTensor>(_base_name + "small_jacobian")),
      41        3951 :     _dcauchy_stress_d_eigenstrain(
      42        3951 :         declareProperty<RankFourTensor>(_base_name + "dcauchy_stress_d_eigenstrain")),
      43        7902 :     _cauchy_stress_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "cauchy_stress")),
      44        7902 :     _mechanical_strain(getMaterialPropertyByName<RankTwoTensor>(_base_name + "mechanical_strain")),
      45        7902 :     _strain_increment(getMaterialPropertyByName<RankTwoTensor>(_base_name + "strain_increment")),
      46        3951 :     _vorticity_increment(
      47        3951 :         getMaterialPropertyByName<RankTwoTensor>(_base_name + "vorticity_increment")),
      48        3951 :     _deformation_gradient_increment(getMaterialPropertyByName<RankTwoTensor>(
      49        3951 :         _base_name + "spatial_deformation_gradient_increment")),
      50        3951 :     _d_deformation_gradient_increment_d_F(getMaterialPropertyByName<RankFourTensor>(
      51        3951 :         _base_name + "d_spatial_deformation_gradient_increment_d_deformation_gradient")),
      52        3951 :     _d_vorticity_increment_d_F(getMaterialPropertyByName<RankFourTensor>(
      53        3951 :         _base_name + "d_vorticity_increment_d_deformation_gradient")),
      54        3951 :     _def_grad(getMaterialPropertyByName<RankTwoTensor>(_base_name + "deformation_gradient")),
      55        7902 :     _def_grad_old(getMaterialPropertyOldByName<RankTwoTensor>(_base_name + "deformation_gradient")),
      56        7902 :     _objective_rate(getParam<MooseEnum>("objective_rate")),
      57       15804 :     _rotate_old_stress(getParam<bool>("rotate_old_stress"))
      58             : {
      59             :   // Only the Green-Naghdi rate consumes the polar-decomposition rotation. Fetch these
      60             :   // (which marks `rotation` active and triggers the strain calc's polar decomposition) only
      61             :   // for that rate -- Truesdell/Jaumann/Rashid leave them null and skip the eigensolve.
      62        3951 :   if (_objective_rate == "green_naghdi")
      63             :   {
      64         192 :     _rotation = &getMaterialPropertyByName<RankTwoTensor>(_base_name + "rotation");
      65         192 :     _rotation_old = &getMaterialPropertyOldByName<RankTwoTensor>(_base_name + "rotation");
      66          96 :     _d_rotation_d_F = &getMaterialPropertyByName<RankFourTensor>(
      67         192 :         _base_name + "d_rotation_d_deformation_gradient");
      68             :   }
      69        3951 : }
      70             : 
      71             : void
      72      655730 : ComputeLagrangianObjectiveStress::initQpStatefulProperties()
      73             : {
      74      655730 :   ComputeLagrangianStressBase::initQpStatefulProperties();
      75             : 
      76      655730 :   _small_stress[_qp].zero();
      77      655730 :   _cauchy_stress[_qp].zero();
      78      655730 : }
      79             : 
      80             : void
      81    49631698 : ComputeLagrangianObjectiveStress::computeQpCauchyStress()
      82             : {
      83    49631698 :   computeQpSmallStress();
      84             : 
      85    49631698 :   const bool need_jacobian = _fe_problem.currentlyComputingJacobian() ||
      86    47999651 :                              _fe_problem.currentlyComputingResidualAndJacobian();
      87             : 
      88    49631698 :   if (!_large_kinematics)
      89             :   {
      90    16049094 :     _cauchy_stress[_qp] = _small_stress[_qp];
      91             :     // Small kinematics: no objective advection. dsigma/d_eigenstrain = -small_jacobian
      92             :     // (the negative because mechanical_strain = total_strain - eigenstrain).
      93             :     // Both Jacobian-side assignments are skipped on residual-only sweeps; the kernel
      94             :     // consumes neither during residual assembly.
      95    16049094 :     if (need_jacobian)
      96             :     {
      97      505199 :       _cauchy_jacobian[_qp] = _small_jacobian[_qp];
      98      505199 :       _dcauchy_stress_d_eigenstrain[_qp] = -_small_jacobian[_qp];
      99             :     }
     100             :   }
     101             :   else
     102             :   {
     103    33582604 :     const RankTwoTensor dS = _small_stress[_qp] - _small_stress_old[_qp];
     104             : 
     105             :     // Gather the per-qp quantities the rate needs, dispatch to the selected objective rate, and
     106             :     // scatter the outputs back into our properties.
     107    33582604 :     LagrangianObjectiveRates::Inputs in;
     108    33582604 :     in.dS = dS;
     109    33582604 :     in.cauchy_stress_old = _cauchy_stress_old[_qp];
     110    33582604 :     in.small_jacobian = _small_jacobian[_qp];
     111    33582604 :     in.dL = _deformation_gradient_increment[_qp];
     112    33582604 :     in.dW = _vorticity_increment[_qp];
     113    33582604 :     in.d_dL_d_F = _d_deformation_gradient_increment_d_F[_qp];
     114    33582604 :     in.d_dW_d_F = _d_vorticity_increment_d_F[_qp];
     115             :     // Green-Naghdi only: the rotation properties (and inv_df / F^{-1}) are fetched only for that
     116             :     // rate, so `_rotation` is non-null exactly when `greenNaghdi` will read them.
     117    33582604 :     if (_rotation)
     118             :     {
     119     3159348 :       in.rotation = (*_rotation)[_qp];
     120     3159348 :       in.rotation_old = (*_rotation_old)[_qp];
     121     3159348 :       in.d_rotation_d_F = (*_d_rotation_d_F)[_qp];
     122     3159348 :       in.inv_df = _inv_df[_qp];
     123     3159348 :       in.inv_def_grad = _inv_def_grad[_qp];
     124             :     }
     125             : 
     126    33582604 :     const auto out = LagrangianObjectiveRates::compute(_objective_rate, in, need_jacobian);
     127    33582604 :     _cauchy_stress[_qp] = out.cauchy_stress;
     128    33582604 :     if (need_jacobian)
     129             :     {
     130     1126848 :       _cauchy_jacobian[_qp] = out.cauchy_jacobian;
     131     1126848 :       _dcauchy_stress_d_eigenstrain[_qp] = out.dcauchy_stress_d_eigenstrain;
     132             :     }
     133             : 
     134    33582604 :     if (_rotate_old_stress)
     135             :     {
     136             :       // Passthrough mode: the wrapped stress material (e.g. `ComputeMultiPlasticityStress`
     137             :       // with `perform_finite_strain_rotations = true`, fed our published
     138             :       // `_rotation_increment`) has already produced the correctly-rotated cumulative Cauchy
     139             :       // stress. Use `_small_stress` directly and discard the rate's own outer rotation of
     140             :       // the stress. `_cauchy_jacobian` from the rate's chain rule is still correct because
     141             :       // it computes `d sigma_cauchy / d(dL)` from `_small_jacobian = dDeltasigma_const/deps` plus
     142             :       // the same rotation-derivative terms -- algebraically the same chain whether we view sigma as
     143             :       // produced by the rate's `R * (sigma_old + Deltasigma_const) * R^T` formula or by the wrapped
     144             :       // material's `R * (s_old + Deltasigma_const) * R^T = small_stress` storage.
     145      103168 :       _cauchy_stress[_qp] = _small_stress[_qp];
     146             :     }
     147             :   }
     148    49631698 : }

Generated by: LCOV version 1.14