https://mooseframework.inl.gov
HomogenizedTotalLagrangianStressDivergence.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 
12 // MOOSE includes
13 #include "Function.h"
14 #include "MooseVariableScalar.h"
15 
17 
20 {
22  params.addClassDescription("Total Lagrangian stress equilibrium kernel with "
23  "homogenization constraint Jacobian terms");
24  params.renameCoupledVar(
25  "scalar_variable", "macro_var", "Optional scalar field with the macro gradient");
26 
27  params.addParam<bool>(
28  "off_diagonal_jacobian", true, "Include the off diagonal parts of the constraint Jacobian");
29 
30  return params;
31 }
32 
34  const InputParameters & parameters)
36  _use_off_diagonal(getParam<bool>("off_diagonal_jacobian"))
37 {
38 }
39 
40 std::set<std::string>
42 {
43  // Add the scalar variable to the list of variables that this kernel contributes to
44  std::set<std::string> vars = TotalLagrangianStressDivergence::additionalROVariables();
45  vars.insert(_kappa_var_ptr->name());
46  return vars;
47 }
48 
49 void
51 {
52  if (_alpha != 0)
53  return;
54 
55  std::vector<Real> scalar_residuals(_k_order);
56 
57  // only assemble scalar residual once; i.e. when handling the first displacement component
58  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
59  {
60  initScalarQpResidual();
61  const auto dV = _JxW[_qp] * _coord[_qp];
62 
63  // index for residual vector
64  unsigned int h = 0;
65 
66  for (const auto & [indices, constraint] : cmap())
67  {
68  const auto [i, j] = indices;
69  const auto [ctype, ctarget] = constraint;
70  const auto cval = ctarget->value(_t, _q_point[_qp]);
71 
72  // value to be constrained
73  Real val;
75  {
77  val = _pk1[_qp](i, j);
79  val = _F[_qp](i, j) - (Real(i == j));
80  else
81  mooseError("Unknown constraint type in the integral!");
82  }
83  else
84  {
86  val = _pk1[_qp](i, j);
88  val = 0.5 * (_F[_qp](i, j) + _F[_qp](j, i)) - (Real(i == j));
89  else
90  mooseError("Unknown constraint type in the integral!");
91  }
92 
93  scalar_residuals[h++] += (val - cval) * dV;
94  }
95  }
96 
97  addResiduals(
98  _assembly, scalar_residuals, _kappa_var_ptr->dofIndices(), _kappa_var_ptr->scalingFactor());
99 }
100 
101 void
103 {
104  if (_alpha != 0)
105  return;
106 
107  _local_ke.resize(_k_order, _k_order);
108 
109  // only assemble scalar residual once; i.e. when handling the first displacement component
110  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
111  {
112  initScalarQpJacobian(_kappa_var);
113  const auto dV = _JxW[_qp] * _coord[_qp];
114 
115  // index for Jacobian row
116  unsigned int h = 0;
117 
118  for (const auto & [indices1, constraint1] : cmap())
119  {
120  const auto [i, j] = indices1;
121  const auto ctype = constraint1.first;
122 
123  // index for Jacobian col
124  unsigned int m = 0;
125 
126  for (const auto & [indices2, constraint2] : cmap())
127  {
128  const auto [k, l] = indices2;
130  // Macro_grad <-> macro_grad: scalar perturbation bypasses F-bar (the
131  // homogenization material adds to `_F` AFTER F-bar runs), so use the
132  // bypass variant of pk1_jacobian.
133  _local_ke(h, m++) += dV * (_dpk1_bypass_fbar[_qp](i, j, k, l));
134  else if (ctype == Homogenization::ConstraintType::Strain)
135  {
136  if (_large_kinematics)
137  _local_ke(h, m++) += dV * (Real(i == k && j == l));
138  else
139  _local_ke(h, m++) += dV * (0.5 * Real(i == k && j == l) + 0.5 * Real(i == l && j == k));
140  }
141  else
142  mooseError("Unknown constraint type in Jacobian calculator!");
143  }
144  h++;
145  }
146  }
147 
148  addJacobian(_assembly,
149  _local_ke,
150  _kappa_var_ptr->dofIndices(),
151  _kappa_var_ptr->dofIndices(),
152  _kappa_var_ptr->scalingFactor());
153 }
154 
155 void
157  const unsigned int jvar_num)
158 {
159  if (!_use_off_diagonal)
160  return;
161 
162  // ONLY assemble the contribution from _alpha component, which is connected with _var
163  // The other components are handled by other kernel instances with other _alpha
164  if (jvar_num != _var.number())
165  return;
166 
167  const auto & jvar = getVariable(jvar_num);
168  const auto jvar_size = jvar.phiSize();
169  _local_ke.resize(_k_order, jvar_size);
170 
171  // The scalar<->disp Jacobian needs `_avg_grad_trial[_alpha]` populated (for the
172  // non-local F-bar chain via `_d_F_stab_d_F_avg * deltaF_avg`). The base
173  // `precalculateOffDiagJacobian` only does this when the off-diag jvar IS a
174  // displacement; for the scalar-driven path it must be triggered explicitly.
175  if (_stabilize_strain)
176  {
177  _fe_problem.prepareShapes(jvar_num, _tid);
178  _avg_grad_trial[_alpha].resize(_phi.size());
180  }
181 
182  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
183  {
184  const auto dV = _JxW[_qp] * _coord[_qp];
185 
186  // index for Jacobian row
187  unsigned int h = 0;
188 
189  for (const auto & [indices, constraint] : cmap())
190  {
191  std::tie(_m, _n) = indices;
192  _ctype = constraint.first;
193  initScalarQpOffDiagJacobian(jvar);
194  for (_j = 0; _j < jvar_size; _j++)
195  _local_ke(h, _j) += dV * computeScalarQpOffDiagJacobian(jvar_num);
196  h++;
197  }
198  }
199 
200  addJacobian(_assembly,
201  _local_ke,
202  _kappa_var_ptr->dofIndices(),
203  jvar.dofIndices(),
204  _kappa_var_ptr->scalingFactor());
205 }
206 
207 void
209  const unsigned int svar_num)
210 {
211  if (!_use_off_diagonal)
212  return;
213 
214  // Just in case, skip any other scalar variables
215  if (svar_num != _kappa_var)
216  return;
217 
218  _local_ke.resize(_test.size(), _k_order);
219 
220  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
221  {
222  unsigned int l = 0;
223  const auto dV = _JxW[_qp] * _coord[_qp];
224  for (const auto & [indices, constraint] : cmap())
225  {
226  // copy constraint indices to protected variables to pass to Qp routine
227  std::tie(_m, _n) = indices;
228  _ctype = constraint.first;
229  initScalarQpJacobian(svar_num);
230  for (_i = 0; _i < _test.size(); _i++)
231  _local_ke(_i, l) += dV * computeQpOffDiagJacobianScalar(svar_num);
232  l++;
233  }
234  }
235 
236  addJacobian(
237  _assembly, _local_ke, _var.dofIndices(), _kappa_var_ptr->dofIndices(), _var.scalingFactor());
238 }
239 
240 Real
242  unsigned int /*svar_num*/)
243 {
244  // d(disp residual) / d(scalar_{m,n}) = int gradTest_alpha : d(PK1)/d(scalar_{m,n}) dV.
245  // The macro_gradient adds to `_F` AFTER F-bar runs (in
246  // `ComputeLagrangianStrainBase::computeQpProperties`), so scalar perturbations
247  // bypass F-bar's chain -- use `_dpk1_bypass_fbar` (pk1_jacobian with the F-bar
248  // `_d_F_stab_d_F_ust` factor REPLACED by identity in the sigma chain).
249  return _dpk1_bypass_fbar[_qp].contractionKl(_m, _n, gradTest(_alpha));
250 }
251 
252 Real
254  unsigned int /*jvar_num*/)
255 {
257  {
258  // d(PK1_{m,n})/d(grad u_beta,j) -- local chain via _dpk1 (= dPK1/d(grad u) including
259  // local F-bar effect via the sigma-chain through `_d_F_stab_d_F_ust`).
260  Real J = _dpk1[_qp].contractionIj(_m, _n, gradTrial(_alpha));
261 
262  // Non-local F-bar contribution to PK1 component (m, n) via the shared helper --
263  // same chain as the regular TL displacement Jacobian but contracted into the single
264  // (m, n) entry rather than doubled with gradTest. Guarded on `_stabilize_strain`
265  // because `_avg_grad_trial` is only populated when F-bar is on.
266  if (_stabilize_strain)
267  {
268  const RankTwoTensor delta_F_avg = _d_F_d_grad_u[_qp] * _avg_grad_trial[_alpha][_j];
269  J += deltaPK1NonLocalFBar(delta_F_avg)(_m, _n);
270  }
271  return J;
272  }
274  {
275  // d(F_stab_{m,n})/d(disp_alpha_j) -- for F-bar on, the F-bar chain couples F_stab to
276  // F_ust through both LOCAL (`_d_F_stab_d_F_ust`) and NON-LOCAL
277  // (`_d_F_stab_d_F_avg * deltaF_avg`) routes. The old `Real(_m == _alpha) *
278  // gradTrial(_m, _n)` form captured only the F-bar-off case correctly.
279  const RankTwoTensor delta_F_ust_local = _d_F_d_grad_u[_qp] * gradTrialUnstabilized(_alpha);
280  RankTwoTensor delta_F_stab = _d_F_stab_d_F_ust[_qp] * delta_F_ust_local;
281  if (_stabilize_strain)
282  {
283  const RankTwoTensor delta_F_avg = _d_F_d_grad_u[_qp] * _avg_grad_trial[_alpha][_j];
284  delta_F_stab += _d_F_stab_d_F_avg[_qp] * delta_F_avg;
285  }
286  if (_large_kinematics)
287  return delta_F_stab(_m, _n);
288  else
289  return 0.5 * (delta_F_stab(_m, _n) + delta_F_stab(_n, _m));
290  }
291  else
292  mooseError("Unknown constraint type in kernel calculation!");
293 }
const unsigned int _alpha
Which component of the vector residual this kernel is responsible for.
const MaterialProperty< RankTwoTensor > & _pk1
The 1st Piola-Kirchhoff stress.
std::vector< std::vector< RankTwoTensor > > _avg_grad_trial
virtual RankTwoTensor gradTrialUnstabilized(unsigned int component)
The unstabilized trial function gradient.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void mooseError(Args &&... args)
const bool _stabilize_strain
If true calculate the deformation gradient derivatives for F_bar.
char ** vars
RankTwoTensor deltaPK1NonLocalFBar(const RankTwoTensor &delta_F_avg) const
Non-local F-bar contribution to deltaPK1 at the current _qp, given the perturbation delta_F_avg of th...
const MaterialProperty< RankFourTensor > & _dpk1_bypass_fbar
Variant of _dpk1 (= pk1_jacobian) computed WITHOUT the F-bar chain factor _d_F_stab_d_F_ust in the si...
registerMooseObject("SolidMechanicsApp", HomogenizedTotalLagrangianStressDivergence)
void renameCoupledVar(const std::string &old_name, const std::string &new_name, const std::string &new_docstring)
virtual void computeScalarOffDiagJacobian(const unsigned int jvar_num) override
Method for computing an off-diagonal jacobian component d-_kappa-residual / d-jvar.
const MaterialProperty< RankTwoTensor > & _F
The actual (stabilized) deformation gradient.
virtual RankTwoTensor gradTest(unsigned int component) override
Interface for objects that use the homogenization constraint.
virtual Real computeQpOffDiagJacobianScalar(const unsigned int svar_num) override
Method for computing d-_var-residual / d-svar at quadrature points.
virtual void computeOffDiagJacobianScalarLocal(const unsigned int svar_num) override
Method for computing an off-diagonal jacobian component d-_var-residual / d-svar. ...
static InputParameters validParams()
const MaterialProperty< RankFourTensor > & _d_F_d_grad_u
Derivative of F_{n+1} w.r.t. the displacement gradient.
const MaterialProperty< RankFourTensor > & _d_F_stab_d_F_ust
Partials of the F-bar-stabilized deformation gradient.
virtual Real computeScalarQpOffDiagJacobian(const unsigned int jvar_num) override
Method for computing an off-diagonal jacobian component at quadrature points.
Total Lagrangian formulation with all homogenization terms (one disp_xyz field and macro_gradient sca...
const MaterialProperty< RankFourTensor > & _dpk1
The derivative of the PK1 stress with respect to the deformation gradient (F that the stress material...
const MaterialProperty< RankFourTensor > & _d_F_stab_d_F_avg
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int _m
Indices for off-diagonal Jacobian components.
Enforce equilibrium with a total Lagrangian formulation.
Homogenization::ConstraintType _ctype
Type of current homogenization constraint.
void addClassDescription(const std::string &doc_string)
const bool _use_off_diagonal
Whether to use the off diagonal term.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
HomogenizedTotalLagrangianStressDivergence(const InputParameters &parameters)
virtual void computeScalarResidual() override
Method for computing the scalar part of residual for _kappa.
virtual void computeScalarJacobian() override
Method for computing the scalar variable part of Jacobian for d-_kappa-residual / d-_kappa...
virtual RankTwoTensor gradTrial(unsigned int component) override
virtual std::set< std::string > additionalROVariables() override
Inform moose that this kernel covers the constraint scalar variable.
bool _large_kinematics
If true use large deformation kinematics.
virtual void precalculateJacobianDisplacement(unsigned int component) override
Prepare the average shape function gradients for stabilization.
static const std::string k
Definition: NS.h:134
const Homogenization::ConstraintMap & cmap() const
Get the constraint map.