https://mooseframework.inl.gov
HomogenizedTotalLagrangianStressDivergenceR.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 // #include "Assembly.h"
16 // #include "MooseVariableFE.h"
17 // #include "MooseVariableScalar.h"
18 // #include "SystemBase.h"
19 
20 // #include "libmesh/quadrature.h"
21 
23 
26 {
28  params.addClassDescription("Total Lagrangian stress equilibrium kernel with "
29  "homogenization constraint Jacobian terms");
30  params.renameCoupledVar(
31  "scalar_variable", "macro_var", "Optional scalar field with the macro gradient");
32  params.addRequiredCoupledVar("macro_other", "Other components of coupled scalar variable");
33  params.addRequiredParam<unsigned int>("prime_scalar", "Either 0=_var or 1=_other scalar");
35  "constraint_types",
37  "Type of each constraint: strain, stress, or none. The types are specified in the "
38  "column-major order, and there must be 9 entries in total.");
39  params.addRequiredParam<std::vector<FunctionName>>(
40  "targets", "Functions giving the targets to hit for constraint types that are not none.");
41 
42  return params;
43 }
44 
46  const InputParameters & parameters)
48  _beta(getParam<unsigned int>("prime_scalar")),
49  _kappao_var_ptr(getScalarVar("macro_other", 0)),
50  _kappao_var(coupledScalar("macro_other")),
51  _ko_order(getScalarVar("macro_other", 0)->order()),
52  _kappa_other(coupledScalarValue("macro_other"))
53 {
54  // Constraint types
55  auto types = getParam<MultiMooseEnum>("constraint_types");
56  if (types.size() != Moose::dim * Moose::dim)
57  mooseError("Number of constraint types must equal dim * dim. ", types.size(), " are provided.");
58 
59  // Targets to hit
60  const std::vector<FunctionName> & fnames = getParam<std::vector<FunctionName>>("targets");
61 
62  // Prepare the constraint map
63  unsigned int fcount = 0;
64  for (const auto j : make_range(Moose::dim))
65  for (const auto i : make_range(Moose::dim))
66  {
67  const auto idx = i + Moose::dim * j;
68  const auto ctype = static_cast<HomogenizationR::ConstraintType>(types.get(idx));
70  {
71  const Function * const f = &getFunctionByName(fnames[fcount++]);
72  _cmap[{i, j}] = {ctype, f};
73  }
74  }
75 }
76 
77 Real
79 {
80  // Assemble R_alpha
81  return gradTest(_alpha).doubleContraction(_pk1[_qp]);
82 }
83 
84 Real
86  unsigned int beta)
87 {
88  // Assemble J-alpha-beta
89  return gradTest(alpha).doubleContraction(_dpk1[_qp] * gradTrial(beta));
90 }
91 
92 void
94 {
95  std::vector<Real> scalar_residuals(_k_order);
96 
97  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
98  {
99  initScalarQpResidual();
100  Real dV = _JxW[_qp] * _coord[_qp];
101  _h = 0; // single index for residual vector; double indices for constraint tensor component
102  for (auto && [indices, constraint] : _cmap)
103  {
104  auto && [i, j] = indices;
105  auto && [ctype, ctarget] = constraint;
106 
107  // ONLY the component(s) that this constraint will contribute here;
108  // other one is handled in the other constraint
109  if (_beta == 0)
110  {
111  if (_h == 1) // only assemble first=0 component of _hvar, then break the loop
112  break;
113  }
114  else
115  {
116  // skip the first component (_hvar) and continue to "first" component of _avar
117  if (_h == 0)
118  {
119  _h++;
120  continue;
121  }
122  }
123 
124  // I am not great with C++ precedence; so, store the index
125  unsigned int r_ind = -_beta + _h; // move 1 row up if _beta=1 for the other scalar
126  _h++; // increment the index before we forget
127  if (_large_kinematics)
128  {
130  scalar_residuals[r_ind] += dV * (_pk1[_qp](i, j) - ctarget->value(_t, _q_point[_qp]));
131  else if (ctype == HomogenizationR::ConstraintType::Strain)
132  scalar_residuals[r_ind] +=
133  dV * (_F[_qp](i, j) - (Real(i == j) + ctarget->value(_t, _q_point[_qp])));
134  else
135  mooseError("Unknown constraint type in the integral!");
136  }
137  else
138  {
140  scalar_residuals[r_ind] += dV * (_pk1[_qp](i, j) - ctarget->value(_t, _q_point[_qp]));
141  else if (ctype == HomogenizationR::ConstraintType::Strain)
142  scalar_residuals[r_ind] += dV * (0.5 * (_F[_qp](i, j) + _F[_qp](j, i)) -
143  (Real(i == j) + ctarget->value(_t, _q_point[_qp])));
144  else
145  mooseError("Unknown constraint type in the integral!");
146  }
147  }
148  }
149 
150  addResiduals(
151  _assembly, scalar_residuals, _kappa_var_ptr->dofIndices(), _kappa_var_ptr->scalingFactor());
152 }
153 
154 void
156 {
157  _local_ke.resize(_k_order, _k_order);
158 
159  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
160  {
161  initScalarQpJacobian(_kappa_var);
162  Real dV = _JxW[_qp] * _coord[_qp];
163 
164  _h = 0;
165  for (auto && [indices1, constraint1] : _cmap)
166  {
167  auto && [i, j] = indices1;
168  auto && ctype = constraint1.first;
169 
170  // identical logic to computeScalarResidual
171  if (_beta == 0)
172  {
173  if (_h == 1)
174  break;
175  }
176  else
177  {
178  if (_h == 0)
179  {
180  _h++;
181  continue;
182  }
183  }
184 
185  _l = 0;
186  for (auto && indices2 : _cmap)
187  {
188  auto && [a, b] = indices2.first;
189 
190  // identical logic to computeScalarResidual, but for column index
191  if (_beta == 0)
192  {
193  if (_l == 1)
194  break;
195  }
196  else
197  {
198  if (_l == 0)
199  {
200  _l++;
201  continue;
202  }
203  }
204 
205  unsigned int c_ind = -_beta + _l; // move 1 column left if _beta=1 for the other scalar
206  _l++; // increment the index before we forget
208  _local_ke(-_beta + _h, c_ind) += dV * (_dpk1[_qp](i, j, a, b));
209  else if (ctype == HomogenizationR::ConstraintType::Strain)
210  {
211  if (_large_kinematics)
212  _local_ke(-_beta + _h, c_ind) += dV * (Real(i == a && j == b));
213  else
214  _local_ke(-_beta + _h, c_ind) +=
215  dV * (0.5 * Real(i == a && j == b) + 0.5 * Real(i == b && j == a));
216  }
217  else
218  mooseError("Unknown constraint type in Jacobian calculator!");
219  }
220  _h++;
221  }
222  }
223 
224  addJacobian(_assembly,
225  _local_ke,
226  _kappa_var_ptr->dofIndices(),
227  _kappa_var_ptr->dofIndices(),
228  _kappa_var_ptr->scalingFactor());
229 }
230 
231 void
233  const unsigned int jvar_num)
234 {
235  // Bail if jvar not coupled
236  if (getJvarMap()[jvar_num] >= 0)
237  {
238 
239  const auto & jvar = getVariable(jvar_num);
240  _local_ke.resize(_k_order, _test.size());
241 
242  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
243  {
244  // single index for Jacobian column; double indices for constraint tensor component
245  unsigned int h = 0;
246  Real dV = _JxW[_qp] * _coord[_qp];
247  for (auto && [indices, constraint] : _cmap)
248  {
249  // identical logic to computeScalarResidual
250  if (_beta == 0)
251  {
252  if (h == 1)
253  break;
254  }
255  else
256  {
257  if (h == 0)
258  {
259  h++;
260  continue;
261  }
262  }
263  // copy constraint indices to protected variables to pass to Qp routine
264  _m = indices.first;
265  _n = indices.second;
266  _ctype = constraint.first;
267  initScalarQpOffDiagJacobian(_var);
268  for (_j = 0; _j < _test.size(); _j++)
269  _local_ke(-_beta + h, _j) += dV * computeScalarQpOffDiagJacobian(jvar_num);
270  h++;
271  }
272  }
273 
274  addJacobian(_assembly,
275  _local_ke,
276  _kappa_var_ptr->dofIndices(),
277  jvar.dofIndices(),
278  _kappa_var_ptr->scalingFactor());
279  }
280 }
281 
282 void
284  const unsigned int svar_num)
285 {
286  // Bail if jvar not coupled
287  if ((svar_num == _kappa_var) || (svar_num == _kappao_var))
288  {
289  // Get dofs and order of this scalar; at least one will be _kappa_var
290  const auto & svar = _sys.getScalarVariable(_tid, svar_num);
291  const unsigned int s_order = svar.order();
292  _local_ke.resize(_test.size(), s_order);
293 
294  // set the local beta based on the current svar_num
295  unsigned int beta = 0;
296  if (svar_num == _kappa_var)
297  beta = 0;
298  else // svar_num == _kappao_var
299  beta = 1;
300 
301  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
302  {
303  // single index for Jacobian row; double indices for constraint tensor component
304  unsigned int l = 0;
305  Real dV = _JxW[_qp] * _coord[_qp];
306  for (auto && [indices, constraint] : _cmap)
307  {
308  // identical logic to computeScalarResidual, but for column index
309  if (beta == 0)
310  {
311  if (l == 1)
312  break;
313  }
314  else
315  {
316  if (l == 0)
317  {
318  l++;
319  continue;
320  }
321  }
322  // copy constraint indices to protected variables to pass to Qp routine
323  _m = indices.first;
324  _n = indices.second;
325  _ctype = constraint.first;
326  initScalarQpJacobian(svar_num);
327  for (_i = 0; _i < _test.size(); _i++)
328  {
329  _local_ke(_i, -beta + l) += dV * computeQpOffDiagJacobianScalar(svar_num);
330  }
331  l++;
332  }
333  }
334 
335  addJacobian(_assembly, _local_ke, _var.dofIndices(), svar.dofIndices(), _var.scalingFactor());
336  }
337 }
338 
339 Real
341  unsigned int /*svar_num*/)
342 {
343  return _dpk1[_qp].contractionKl(_m, _n, gradTest(_alpha));
344 }
345 
346 Real
348 {
349  // set the local alpha based on the current jvar_num
350  for (auto alpha : make_range(_ndisp))
351  {
352  if (jvar_num == _disp_nums[alpha])
353  {
355  return _dpk1[_qp].contractionIj(_m, _n, gradTrial(alpha));
357  if (_large_kinematics)
358  return Real(_m == alpha) * gradTrial(alpha)(_m, _n);
359  else
360  return 0.5 * (Real(_m == alpha) * gradTrial(alpha)(_m, _n) +
361  Real(_n == alpha) * gradTrial(alpha)(_n, _m));
362  else
363  mooseError("Unknown constraint type in kernel calculation!");
364  }
365  }
366  return 0.0;
367 }
368 
369 void
371  const unsigned int svar_num)
372 {
373  // Only do this for the other macro variable
374  if (svar_num == _kappao_var)
375  {
376  _local_ke.resize(_k_order, _ko_order);
377 
378  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
379  {
380  initScalarQpJacobian(_kappa_var);
381  Real dV = _JxW[_qp] * _coord[_qp];
382 
383  _h = 0;
384  for (auto && [indices1, constraint1] : _cmap)
385  {
386  auto && [i, j] = indices1;
387  auto && ctype = constraint1.first;
388 
389  // identical logic to computeScalarResidual
390  if (_beta == 0)
391  {
392  if (_h == 1)
393  break;
394  }
395  else
396  {
397  if (_h == 0)
398  {
399  _h++;
400  continue;
401  }
402  }
403 
404  _l = 0;
405  for (auto && indices2 : _cmap)
406  {
407  auto && [a, b] = indices2.first;
408 
409  // OPPOSITE logic/scalar from computeScalarResidual, AND for column index
410  if (_beta == 1)
411  {
412  if (_l == 1) // only assemble first=0 component of _hvar, then break the loop
413  break;
414  }
415  else
416  {
417  if (_l == 0) // skip first component (_hvar) & continue to "first" component of _avar
418  {
419  _l++;
420  continue;
421  }
422  }
423 
424  unsigned int c_ind =
425  -(1 - _beta) + _l; // DON'T move 1 column left if _beta=1 for the other scalar
426  _l++;
428  _local_ke(-_beta + _h, c_ind) += dV * (_dpk1[_qp](i, j, a, b));
429  else if (ctype == HomogenizationR::ConstraintType::Strain)
430  {
431  if (_large_kinematics)
432  _local_ke(-_beta + _h, c_ind) += dV * (Real(i == a && j == b));
433  else
434  _local_ke(-_beta + _h, c_ind) +=
435  dV * (0.5 * Real(i == a && j == b) + 0.5 * Real(i == b && j == a));
436  }
437  else
438  mooseError("Unknown constraint type in Jacobian calculator!");
439  }
440  _h++;
441  }
442  }
443 
444  addJacobian(_assembly,
445  _local_ke,
446  _kappa_var_ptr->dofIndices(),
448  _kappa_var_ptr->scalingFactor());
449  }
450 }
static InputParameters validParams()
registerMooseObject("SolidMechanicsTestApp", HomogenizedTotalLagrangianStressDivergenceR)
std::vector< unsigned int > _disp_nums
The displacement numbers.
const unsigned int _alpha
Which component of the vector residual this kernel is responsible for.
const bool _large_kinematics
If true use large deformation kinematics.
void mooseError(Args &&... args)
static constexpr std::size_t dim
void renameCoupledVar(const std::string &old_name, const std::string &new_name, const std::string &new_docstring)
Total Lagrangian formulation with most homogenization terms (one disp_xyz field and one scalar) The m...
Enforce equilibrium with a total Lagrangian formulation.
virtual void computeScalarJacobian() override
Method for computing the scalar variable part of Jacobian for d-_kappa-residual / d-_kappa...
virtual void computeScalarResidual() override
Method for computing the scalar part of residual for _kappa.
const unsigned int _kappao_var
The unknown scalar variable ID.
void addRequiredParam(const std::string &name, const std::string &doc_string)
virtual void computeScalarOffDiagJacobian(const unsigned int jvar_num) override
Method for computing an off-diagonal jacobian component d-_kappa-residual / d-jvar jvar is looped ove...
virtual void computeOffDiagJacobianScalarLocal(const unsigned int svar_num) override
Method for computing an off-diagonal jacobian component d-_var-residual / d-svar. ...
HomogenizationR::ConstraintType _ctype
The constraint type; initialize with &#39;none&#39;.
HomogenizationR::ConstraintMap _cmap
Type of each constraint (stress or strain) for each component.
const unsigned int _ndisp
Total number of displacements/size of residual vector.
virtual Real computeQpOffDiagJacobianScalar(const unsigned int) override
Method for computing d-_var-residual / d-_svar at quadrature points.
Real f(Real x)
Test function for Brents method.
const unsigned int _ko_order
Order of the scalar variable, used in several places.
virtual void computeScalarOffDiagJacobianScalar(const unsigned int svar_num) override
Method for computing an off-diagonal jacobian component d-_kappa-residual / d-svar svar is looped ove...
virtual RankTwoTensor gradTest(unsigned int component) override
const MooseVariableScalar *const _kappao_var_ptr
(Pointer to) Scalar variable this kernel operates on
virtual const std::vector< dof_id_type > & dofIndices() const
Real doubleContraction(const RankTwoTensorTempl< Real > &a) const
const MaterialProperty< RankTwoTensor > & _F
The actual (stabilized) deformation gradient.
unsigned int _m
Used internally to iterate over each scalar component.
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
virtual Real computeQpJacobianDisplacement(unsigned int alpha, unsigned int beta) override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string alpha
Definition: NS.h:134
virtual Real computeScalarQpOffDiagJacobian(const unsigned int jvar_num) override
Method for computing an off-diagonal jacobian component at quadrature points.
IntRange< T > make_range(T beg, T end)
void addClassDescription(const std::string &doc_string)
const unsigned int _beta
Which component of the scalar vector residual this constraint is responsible for. ...
const MultiMooseEnum constraintType("strain stress none")
Moose constraint type, for input.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
const MaterialProperty< RankFourTensor > & _dpk1
The derivative of the PK1 stress with respect to the deformation gradient.
ConstraintType
Constraint type: stress/PK stress or strain/deformation gradient.
void ErrorVector unsigned int
const MaterialProperty< RankTwoTensor > & _pk1
The 1st Piola-Kirchhoff stress.
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
virtual RankTwoTensor gradTrial(unsigned int component) override