LCOV - code coverage report
Current view: top level - src/kernels/lagrangian - UpdatedLagrangianStressDivergence.C (source / functions) Hit Total Coverage
Test: idaholab/moose solid_mechanics: #33390 (250e9c) with base 846a5c Lines: 52 56 92.9 %
Date: 2026-07-31 18:20:40 Functions: 8 9 88.9 %
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 "UpdatedLagrangianStressDivergence.h"
      11             : 
      12             : registerMooseObject("SolidMechanicsApp", UpdatedLagrangianStressDivergence);
      13             : 
      14             : template <class G>
      15         594 : UpdatedLagrangianStressDivergenceBase<G>::UpdatedLagrangianStressDivergenceBase(
      16             :     const InputParameters & parameters)
      17             :   : LagrangianStressDivergenceBase(parameters),
      18         594 :     _stress(getMaterialPropertyByName<RankTwoTensor>(_base_name + "cauchy_stress")),
      19        1188 :     _material_jacobian(getMaterialPropertyByName<RankFourTensor>(_base_name + "cauchy_jacobian")),
      20             : 
      21             :     // Assembly quantities in the reference frame for stabilization
      22         594 :     _assembly_undisplaced(_fe_problem.assembly(_tid, this->_sys.number())),
      23         594 :     _grad_phi_undisplaced(_assembly_undisplaced.gradPhi()),
      24         594 :     _JxW_undisplaced(_assembly_undisplaced.JxW()),
      25         594 :     _coord_undisplaced(_assembly_undisplaced.coordTransformation()),
      26         594 :     _q_point_undisplaced(_assembly_undisplaced.qPoints())
      27             : {
      28             :   // The use_displaced_mesh <-> large_kinematics consistency check lives in initialSetup(), since
      29             :   // large_kinematics is now derived from the strain calculator's guarantee (not available in the
      30             :   // constructor).
      31             : 
      32             :   // TODO: add weak plane stress support
      33         594 :   if (_out_of_plane_strain)
      34           0 :     mooseError("The UpdatedLagrangianStressDivergence kernels do not yet support the weak plane "
      35             :                "stress formulation. Please use the TotalLagrangianStressDivergecen kernels.");
      36             : 
      37             :   // The UL push-forward in `precalculateJacobianDisplacement` uses `_F_avg` (= avg(F_ust))
      38             :   // for the spatial-to-reference frame mapping; combining it with the incremental F-bar
      39             :   // chain (which expects `_avg_grad_trial` to represent deltaf_avg, not deltaF_avg) hasn't been
      40             :   // worked out yet. Use Total Lagrangian for incremental F-bar.
      41         594 :   if (_stabilize_strain && _F_bar_mode == FBarMode::Incremental)
      42           0 :     mooseError("`F_bar_mode = incremental` is not yet supported with the UpdatedLagrangian "
      43             :                "kernels; use TotalLagrangianStressDivergence (or `F_bar_mode = total`).");
      44         594 : }
      45             : 
      46             : template <class G>
      47             : RankTwoTensor
      48   464359424 : UpdatedLagrangianStressDivergenceBase<G>::gradTest(unsigned int component)
      49             : {
      50             :   // F-bar doesn't modify the test function
      51   464359424 :   return G::gradOp(component, _grad_test[_i][_qp], _test[_i][_qp], _q_point[_qp]);
      52             : }
      53             : 
      54             : template <class G>
      55             : RankTwoTensor
      56           0 : UpdatedLagrangianStressDivergenceBase<G>::gradTrial(unsigned int component)
      57             : {
      58             :   // F-bar stabilization is handled explicitly in computeQpJacobianDisplacement via the stored
      59             :   // partial derivatives _d_F_stab_d_F_ust and _d_F_stab_d_F_avg, so gradTrial always returns
      60             :   // the unstabilized spatial gradient.
      61           0 :   return gradTrialUnstabilized(component);
      62             : }
      63             : 
      64             : template <class G>
      65             : RankTwoTensor
      66   188517888 : UpdatedLagrangianStressDivergenceBase<G>::gradTrialUnstabilized(unsigned int component)
      67             : {
      68             :   // Without F-bar stabilization, simply return the gradient of the trial functions
      69   188517888 :   return G::gradOp(component, _grad_phi[_j][_qp], _phi[_j][_qp], _q_point[_qp]);
      70             : }
      71             : 
      72             : template <class G>
      73             : void
      74       61208 : UpdatedLagrangianStressDivergenceBase<G>::precalculateJacobianDisplacement(unsigned int component)
      75             : {
      76             :   // For updated Lagrangian, the averaging is taken on the reference frame. If large kinematics is
      77             :   // used, the averaged gradients should be pushed forward to the current frame.
      78      536760 :   for (auto j : make_range(_phi.size()))
      79             :   {
      80      475552 :     _avg_grad_trial[component][j] = StabilizationUtils::elementAverage(
      81      475552 :         [this, component, j](unsigned int qp)
      82             :         {
      83     3748928 :           return G::gradOp(
      84     3748928 :               component, _grad_phi_undisplaced[j][qp], _phi[j][qp], _q_point_undisplaced[qp]);
      85             :         },
      86             :         _JxW_undisplaced,
      87             :         _coord_undisplaced);
      88      475552 :     if (_large_kinematics)
      89             :       // Push forward to the current frame.
      90             :       // The average deformation gradient is the same at all qps.
      91      130000 :       _avg_grad_trial[component][j] *= _F_avg[0].inverse();
      92             :   }
      93       61208 : }
      94             : 
      95             : template <class G>
      96             : Real
      97   275595776 : UpdatedLagrangianStressDivergenceBase<G>::computeQpResidual()
      98             : {
      99   275595776 :   return gradTest(_alpha).doubleContraction(_stress[_qp]);
     100             : }
     101             : 
     102             : template <class G>
     103             : Real
     104   188517888 : UpdatedLagrangianStressDivergenceBase<G>::computeQpJacobianDisplacement(unsigned int alpha,
     105             :                                                                         unsigned int beta)
     106             : {
     107   188517888 :   const auto grad_test = gradTest(alpha);
     108   188517888 :   const auto grad_trial = gradTrialUnstabilized(beta);
     109             : 
     110             :   //           J^{alpha beta} = J^{alpha beta}_material + J^{alpha beta}_geometric
     111             :   //  J^{alpha beta}_material = phi^alpha : T : d(dL)/d(grad u) * grad_trial
     112             :   // J^{alpha beta}_geometric = sigma_{ij} (phi^alpha_{k, k} psi^beta_{i, j} -
     113             :   //                                        phi^alpha_{k, j} psi^beta_{i, k})
     114             : 
     115             :   // Local contribution to delta(F_ust): pull the spatial trial gradient back through the
     116             :   // literal n+1 deformation gradient (use_displaced_mesh = true uses F_actual, regardless
     117             :   // of alpha or F-bar), then chain to F_ust via _d_F_d_grad_u (= alpha * I^(4)).
     118   188517888 :   const RankTwoTensor delta_grad_u_local =
     119   188517888 :       _large_kinematics ? grad_trial * _F_actual[_qp] : grad_trial;
     120   188517888 :   const RankTwoTensor delta_F_ust_local = _d_F_d_grad_u[_qp] * delta_grad_u_local;
     121             : 
     122             :   // Non-local F-bar contribution to delta(F_avg): _avg_grad_trial is stored as
     123             :   // avg(gradTrial_reference) * F_avg^{-1} (see precalculateJacobianDisplacement). Multiply
     124             :   // by F_avg to recover the reference-frame averaged gradient, then chain to F_ust the
     125             :   // same way.
     126   188517888 :   RankTwoTensor delta_F_avg;
     127   188517888 :   if (_stabilize_strain)
     128             :   {
     129    29771392 :     const RankTwoTensor delta_grad_u_avg =
     130    29771392 :         _large_kinematics ? _avg_grad_trial[beta][_j] * _F_avg[_qp] : _avg_grad_trial[beta][_j];
     131    29771392 :     delta_F_avg = _d_F_d_grad_u[_qp] * delta_grad_u_avg;
     132             :   }
     133             : 
     134             :   // Stabilized delta(F_stab) through the F-bar tangent. With F-bar off, the partials are
     135             :   // _d_F_stab_d_F_ust = I^(4) and _d_F_stab_d_F_avg = 0, so this reduces to delta_F_ust_local.
     136   188517888 :   const RankTwoTensor delta_F_stab =
     137   188517888 :       _d_F_stab_d_F_ust[_qp] * delta_F_ust_local + _d_F_stab_d_F_avg[_qp] * delta_F_avg;
     138             : 
     139   188517888 :   const RankTwoTensor delta_dL = _d_deformation_gradient_increment_d_F[_qp] * delta_F_stab;
     140             : 
     141             :   // The material jacobian
     142   188517888 :   Real J = grad_test.doubleContraction(_material_jacobian[_qp] * delta_dL);
     143             : 
     144             :   // The geometric jacobian (no F-bar stabilization in this term)
     145   188517888 :   if (_large_kinematics)
     146             :   {
     147   239116032 :     J += _stress[_qp].doubleContraction(grad_test) * grad_trial.trace() -
     148   119558016 :          _stress[_qp].doubleContraction(grad_test * grad_trial);
     149             :   }
     150             : 
     151   188517888 :   return J;
     152             : }
     153             : 
     154             : template <class G>
     155             : Real
     156      245760 : UpdatedLagrangianStressDivergenceBase<G>::computeQpJacobianTemperature(unsigned int cvar)
     157             : {
     158             :   // Multiple eigenstrains may depend on the same coupled var
     159      245760 :   RankTwoTensor total_deigen;
     160      491520 :   for (const auto deigen_darg : _deigenstrain_dargs[cvar])
     161      245760 :     total_deigen += (*deigen_darg)[_qp];
     162             : 
     163      245760 :   RankFourTensor C = _material_jacobian[_qp];
     164      245760 :   RankFourTensor Csym = 0.5 * (C + C.transposeMajor().transposeIj().transposeMajor());
     165             : 
     166      245760 :   return -(Csym * total_deigen).doubleContraction(gradTest(_alpha)) * _temperature->phi()[_j][_qp];
     167             : }
     168             : 
     169             : template class UpdatedLagrangianStressDivergenceBase<GradientOperatorCartesian>;

Generated by: LCOV version 1.14