https://mooseframework.inl.gov
UpdatedLagrangianStressDivergence.C
Go to the documentation of this file.
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 
11 
13 
14 template <class G>
16  const InputParameters & parameters)
17  : LagrangianStressDivergenceBase(parameters),
18  _stress(getMaterialPropertyByName<RankTwoTensor>(_base_name + "cauchy_stress")),
19  _material_jacobian(getMaterialPropertyByName<RankFourTensor>(_base_name + "cauchy_jacobian")),
20 
21  // Assembly quantities in the reference frame for stabilization
22  _assembly_undisplaced(_fe_problem.assembly(_tid, this->_sys.number())),
23  _grad_phi_undisplaced(_assembly_undisplaced.gradPhi()),
24  _JxW_undisplaced(_assembly_undisplaced.JxW()),
25  _coord_undisplaced(_assembly_undisplaced.coordTransformation()),
26  _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
34  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.
42  mooseError("`F_bar_mode = incremental` is not yet supported with the UpdatedLagrangian "
43  "kernels; use TotalLagrangianStressDivergence (or `F_bar_mode = total`).");
44 }
45 
46 template <class G>
49 {
50  // F-bar doesn't modify the test function
51  return G::gradOp(component, _grad_test[_i][_qp], _test[_i][_qp], _q_point[_qp]);
52 }
53 
54 template <class G>
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  return gradTrialUnstabilized(component);
62 }
63 
64 template <class G>
67 {
68  // Without F-bar stabilization, simply return the gradient of the trial functions
69  return G::gradOp(component, _grad_phi[_j][_qp], _phi[_j][_qp], _q_point[_qp]);
70 }
71 
72 template <class G>
73 void
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  for (auto j : make_range(_phi.size()))
79  {
81  [this, component, j](unsigned int qp)
82  {
83  return G::gradOp(
84  component, _grad_phi_undisplaced[j][qp], _phi[j][qp], _q_point_undisplaced[qp]);
85  },
86  _JxW_undisplaced,
87  _coord_undisplaced);
88  if (_large_kinematics)
89  // Push forward to the current frame.
90  // The average deformation gradient is the same at all qps.
91  _avg_grad_trial[component][j] *= _F_avg[0].inverse();
92  }
93 }
94 
95 template <class G>
96 Real
98 {
99  return gradTest(_alpha).doubleContraction(_stress[_qp]);
100 }
101 
102 template <class G>
103 Real
105  unsigned int beta)
106 {
107  const auto grad_test = gradTest(alpha);
108  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  const RankTwoTensor delta_grad_u_local =
119  _large_kinematics ? grad_trial * _F_actual[_qp] : grad_trial;
120  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  RankTwoTensor delta_F_avg;
127  if (_stabilize_strain)
128  {
129  const RankTwoTensor delta_grad_u_avg =
130  _large_kinematics ? _avg_grad_trial[beta][_j] * _F_avg[_qp] : _avg_grad_trial[beta][_j];
131  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  const RankTwoTensor delta_F_stab =
137  _d_F_stab_d_F_ust[_qp] * delta_F_ust_local + _d_F_stab_d_F_avg[_qp] * delta_F_avg;
138 
139  const RankTwoTensor delta_dL = _d_deformation_gradient_increment_d_F[_qp] * delta_F_stab;
140 
141  // The material jacobian
142  Real J = grad_test.doubleContraction(_material_jacobian[_qp] * delta_dL);
143 
144  // The geometric jacobian (no F-bar stabilization in this term)
145  if (_large_kinematics)
146  {
147  J += _stress[_qp].doubleContraction(grad_test) * grad_trial.trace() -
148  _stress[_qp].doubleContraction(grad_test * grad_trial);
149  }
150 
151  return J;
152 }
153 
154 template <class G>
155 Real
157 {
158  // Multiple eigenstrains may depend on the same coupled var
159  RankTwoTensor total_deigen;
160  for (const auto deigen_darg : _deigenstrain_dargs[cvar])
161  total_deigen += (*deigen_darg)[_qp];
162 
163  RankFourTensor C = _material_jacobian[_qp];
164  RankFourTensor Csym = 0.5 * (C + C.transposeMajor().transposeIj().transposeMajor());
165 
166  return -(Csym * total_deigen).doubleContraction(gradTest(_alpha)) * _temperature->phi()[_j][_qp];
167 }
168 
virtual RankTwoTensor gradTrial(unsigned int component) override
virtual RankTwoTensor gradTest(unsigned int component) override
void mooseError(Args &&... args)
static const std::string component
Definition: NS.h:157
const bool _stabilize_strain
If true calculate the deformation gradient derivatives for F_bar.
virtual Real computeQpJacobianDisplacement(unsigned int alpha, unsigned int beta) override
const MooseVariable * _out_of_plane_strain
Out-of-plane strain, if provided.
virtual RankTwoTensor gradTrialUnstabilized(unsigned int component)
The unstabilized trial function gradient.
registerMooseObject("SolidMechanicsApp", UpdatedLagrangianStressDivergence)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string alpha
Definition: NS.h:138
const FBarMode _F_bar_mode
What F gets F-bar volumetric correction (Total vs.
IntRange< T > make_range(T beg, T end)
auto elementAverage(const Functor &f, const MooseArray< Real > &JxW, const MooseArray< Real > &coord)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual void precalculateJacobianDisplacement(unsigned int component) override
Prepare the average shape function gradients for stabilization.
UpdatedLagrangianStressDivergenceBase(const InputParameters &parameters)
virtual Real computeQpJacobianTemperature(unsigned int cvar) override
Base class of the "Lagrangian" kernel system.
static const std::string C
Definition: NS.h:172
Enforce equilibrium with an updated Lagrangian formulation.