https://mooseframework.inl.gov
HomogenizedTotalLagrangianStressDivergenceA.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<HomogenizationA::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 if _beta==0
81  if (_beta == 0)
82  return gradTest(_alpha).doubleContraction(_pk1[_qp]);
83  else
84  return 0.0;
85 }
86 
87 Real
89  unsigned int beta)
90 {
91  // Assemble J-alpha-beta if _beta==0
92  if (_beta == 0)
93  return gradTest(alpha).doubleContraction(_dpk1[_qp] * gradTrial(beta));
94  else
95  return 0.0;
96 }
97 
98 void
100 {
101  std::vector<Real> scalar_residuals(_k_order);
102 
103  // Assemble R_beta if _alpha==0
104  if (_alpha == 0)
105  {
106  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
107  {
108  initScalarQpResidual();
109  Real dV = _JxW[_qp] * _coord[_qp];
110  _h = 0; // single index for residual vector; double indices for constraint tensor component
111  for (auto && [indices, constraint] : _cmap)
112  {
113  auto && [i, j] = indices;
114  auto && [ctype, ctarget] = constraint;
115 
116  // ONLY the component(s) that this constraint will contribute here;
117  // other one is handled in the other constraint
118  if (_beta == 0)
119  {
120  if (_h == 1) // only assemble first=0 component of _hvar, then break the loop
121  break;
122  }
123  else
124  {
125  // skip the first component (_hvar) and continue to "first" component of _avar
126  if (_h == 0)
127  {
128  _h++;
129  continue;
130  }
131  }
132 
133  // I am not great with C++ precedence; so, store the index
134  unsigned int r_ind = -_beta + _h; // move 1 row up if _beta=1 for the other scalar
135  _h++; // increment the index before we forget
136  if (_large_kinematics)
137  {
139  scalar_residuals[r_ind] += dV * (_pk1[_qp](i, j) - ctarget->value(_t, _q_point[_qp]));
140  else if (ctype == HomogenizationA::ConstraintType::Strain)
141  scalar_residuals[r_ind] +=
142  dV * (_F[_qp](i, j) - (Real(i == j) + ctarget->value(_t, _q_point[_qp])));
143  else
144  mooseError("Unknown constraint type in the integral!");
145  }
146  else
147  {
149  scalar_residuals[r_ind] += dV * (_pk1[_qp](i, j) - ctarget->value(_t, _q_point[_qp]));
150  else if (ctype == HomogenizationA::ConstraintType::Strain)
151  scalar_residuals[r_ind] += dV * (0.5 * (_F[_qp](i, j) + _F[_qp](j, i)) -
152  (Real(i == j) + ctarget->value(_t, _q_point[_qp])));
153  else
154  mooseError("Unknown constraint type in the integral!");
155  }
156  }
157  }
158  }
159 
160  addResiduals(
161  _assembly, scalar_residuals, _kappa_var_ptr->dofIndices(), _kappa_var_ptr->scalingFactor());
162 }
163 
164 void
166 {
167  _local_ke.resize(_k_order, _k_order);
168 
169  // Assemble J_beta_beta if _alpha==0
170  if (_alpha == 0)
171  {
172  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
173  {
174  initScalarQpJacobian(_kappa_var);
175  Real dV = _JxW[_qp] * _coord[_qp];
176 
177  _h = 0;
178  for (auto && [indices1, constraint1] : _cmap)
179  {
180  auto && [i, j] = indices1;
181  auto && ctype = constraint1.first;
182 
183  // identical logic to computeScalarResidual
184  if (_beta == 0)
185  {
186  if (_h == 1)
187  break;
188  }
189  else
190  {
191  if (_h == 0)
192  {
193  _h++;
194  continue;
195  }
196  }
197 
198  _l = 0;
199  for (auto && indices2 : _cmap)
200  {
201  auto && [a, b] = indices2.first;
202 
203  // identical logic to computeScalarResidual, but for column index
204  if (_beta == 0)
205  {
206  if (_l == 1)
207  break;
208  }
209  else
210  {
211  if (_l == 0)
212  {
213  _l++;
214  continue;
215  }
216  }
217 
218  unsigned int c_ind = -_beta + _l; // move 1 column left if _beta=1 for the other scalar
219  _l++; // increment the index before we forget
221  _local_ke(-_beta + _h, c_ind) += dV * (_dpk1[_qp](i, j, a, b));
222  else if (ctype == HomogenizationA::ConstraintType::Strain)
223  {
224  if (_large_kinematics)
225  _local_ke(-_beta + _h, c_ind) += dV * (Real(i == a && j == b));
226  else
227  _local_ke(-_beta + _h, c_ind) +=
228  dV * (0.5 * Real(i == a && j == b) + 0.5 * Real(i == b && j == a));
229  }
230  else
231  mooseError("Unknown constraint type in Jacobian calculator!");
232  }
233  _h++;
234  }
235  }
236  }
237 
238  addJacobian(_assembly,
239  _local_ke,
240  _kappa_var_ptr->dofIndices(),
241  _kappa_var_ptr->dofIndices(),
242  _kappa_var_ptr->scalingFactor());
243 }
244 
245 void
247  const unsigned int jvar_num)
248 {
249  // Assembly J_alpha_beta ONLY
250  if (jvar_num == _var.number())
251  {
252  _local_ke.resize(_k_order, _test.size());
253 
254  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
255  {
256  // single index for Jacobian column; double indices for constraint tensor component
257  unsigned int h = 0;
258  Real dV = _JxW[_qp] * _coord[_qp];
259  for (auto && [indices, constraint] : _cmap)
260  {
261  // identical logic to computeScalarResidual
262  if (_beta == 0)
263  {
264  if (h == 1)
265  break;
266  }
267  else
268  {
269  if (h == 0)
270  {
271  h++;
272  continue;
273  }
274  }
275  // copy constraint indices to protected variables to pass to Qp routine
276  _m = indices.first;
277  _n = indices.second;
278  _ctype = constraint.first;
279  initScalarQpOffDiagJacobian(_var);
280  for (_j = 0; _j < _test.size(); _j++)
281  _local_ke(-_beta + h, _j) += dV * computeScalarQpOffDiagJacobian(jvar_num);
282  h++;
283  }
284  }
285 
286  addJacobian(_assembly,
287  _local_ke,
288  _kappa_var_ptr->dofIndices(),
289  _var.dofIndices(),
290  _kappa_var_ptr->scalingFactor());
291  }
292 }
293 
294 void
296  const unsigned int svar_num)
297 {
298  // Assembly J_beta_alpha ONLY
299  if (svar_num == _kappa_var)
300  {
301  _local_ke.resize(_test.size(), _k_order);
302 
303  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
304  {
305  // single index for Jacobian row; double indices for constraint tensor component
306  unsigned int l = 0;
307  Real dV = _JxW[_qp] * _coord[_qp];
308  for (auto && [indices, constraint] : _cmap)
309  {
310  // identical logic to computeScalarResidual, but for column index
311  if (_beta == 0)
312  {
313  if (l == 1)
314  break;
315  }
316  else
317  {
318  if (l == 0)
319  {
320  l++;
321  continue;
322  }
323  }
324  // copy constraint indices to protected variables to pass to Qp routine
325  _m = indices.first;
326  _n = indices.second;
327  _ctype = constraint.first;
328  initScalarQpJacobian(svar_num);
329  for (_i = 0; _i < _test.size(); _i++)
330  {
331  _local_ke(_i, -_beta + l) += dV * computeQpOffDiagJacobianScalar(svar_num);
332  }
333  l++;
334  }
335  }
336 
337  addJacobian(_assembly,
338  _local_ke,
339  _var.dofIndices(),
340  _kappa_var_ptr->dofIndices(),
341  _var.scalingFactor());
342  }
343 }
344 
345 Real
347 {
348  if (svar_num == _kappa_var)
349  return _dpk1[_qp].contractionKl(_m, _n, gradTest(_alpha));
350  else
351  return 0.;
352 }
353 
354 Real
356 {
357  if (jvar_num == _var.number())
358  {
360  return _dpk1[_qp].contractionIj(_m, _n, gradTrial(_alpha));
362  if (_large_kinematics)
363  return Real(_m == _alpha) * gradTrial(_alpha)(_m, _n);
364  else
365  return 0.5 * (Real(_m == _alpha) * gradTrial(_alpha)(_m, _n) +
366  Real(_n == _alpha) * gradTrial(_alpha)(_n, _m));
367  else
368  mooseError("Unknown constraint type in kernel calculation!");
369  }
370  else
371  return 0.;
372 }
373 
374 void
376  const unsigned int svar_num)
377 {
378  // Only do this for the other macro variable
379  if (svar_num == _kappao_var)
380  {
381  _local_ke.resize(_k_order, _ko_order);
382 
383  // Assemble J-kappa-kappa_other if _alpha==0
384  if (_alpha == 0)
385  {
386  for (_qp = 0; _qp < _qrule->n_points(); _qp++)
387  {
388  initScalarQpJacobian(_kappa_var);
389  Real dV = _JxW[_qp] * _coord[_qp];
390 
391  _h = 0;
392  for (auto && [indices1, constraint1] : _cmap)
393  {
394  auto && [i, j] = indices1;
395  auto && ctype = constraint1.first;
396 
397  // identical logic to computeScalarResidual
398  if (_beta == 0)
399  {
400  if (_h == 1)
401  break;
402  }
403  else
404  {
405  if (_h == 0)
406  {
407  _h++;
408  continue;
409  }
410  }
411 
412  _l = 0;
413  for (auto && indices2 : _cmap)
414  {
415  auto && [a, b] = indices2.first;
416 
417  // OPPOSITE logic/scalar from computeScalarResidual, AND for column index
418  if (_beta == 1)
419  {
420  if (_l == 1) // only assemble first=0 component of _hvar, then break the loop
421  break;
422  }
423  else
424  {
425  if (_l == 0) // skip first component (_hvar) & continue to "first" component of _avar
426  {
427  _l++;
428  continue;
429  }
430  }
431 
432  unsigned int c_ind =
433  -(1 - _beta) + _l; // DON'T move 1 column left if _beta=1 for the other scalar
434  _l++;
436  _local_ke(-_beta + _h, c_ind) += dV * (_dpk1[_qp](i, j, a, b));
437  else if (ctype == HomogenizationA::ConstraintType::Strain)
438  {
439  if (_large_kinematics)
440  _local_ke(-_beta + _h, c_ind) += dV * (Real(i == a && j == b));
441  else
442  _local_ke(-_beta + _h, c_ind) +=
443  dV * (0.5 * Real(i == a && j == b) + 0.5 * Real(i == b && j == a));
444  }
445  else
446  mooseError("Unknown constraint type in Jacobian calculator!");
447  }
448  _h++;
449  }
450  }
451  }
452 
453  addJacobian(_assembly,
454  _local_ke,
455  _kappa_var_ptr->dofIndices(),
457  _kappa_var_ptr->scalingFactor());
458  }
459 }
static InputParameters validParams()
virtual Real computeScalarQpOffDiagJacobian(const unsigned int jvar_num) override
Method for computing an off-diagonal jacobian component at quadrature points.
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.
const unsigned int _ko_order
Order of the scalar variable, used in several places.
void mooseError(Args &&... args)
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...
static constexpr std::size_t dim
void renameCoupledVar(const std::string &old_name, const std::string &new_name, const std::string &new_docstring)
Enforce equilibrium with a total Lagrangian formulation.
HomogenizationA::ConstraintMap _cmap
Type of each constraint (stress or strain) for each component.
const MooseVariableScalar *const _kappao_var_ptr
(Pointer to) Scalar variable this kernel operates on
void addRequiredParam(const std::string &name, const std::string &doc_string)
virtual Real computeQpJacobianDisplacement(unsigned int alpha, unsigned int beta) override
const MultiMooseEnum constraintType("strain stress none")
Moose constraint type, for input.
virtual void computeOffDiagJacobianScalarLocal(const unsigned int svar_num) override
Method for computing an off-diagonal jacobian component d-_var-residual / d-svar. ...
Real f(Real x)
Test function for Brents method.
const unsigned int _beta
Which component of the scalar vector residual this constraint is responsible for. ...
virtual RankTwoTensor gradTest(unsigned int component) override
Total Lagrangian formulation with most homogenization terms (one disp_xyz field and one scalar) The m...
virtual const std::vector< dof_id_type > & dofIndices() const
Real doubleContraction(const RankTwoTensorTempl< Real > &a) const
const unsigned int _kappao_var
The unknown scalar variable ID.
const MaterialProperty< RankTwoTensor > & _F
The actual (stabilized) deformation gradient.
registerMooseObject("SolidMechanicsTestApp", HomogenizedTotalLagrangianStressDivergenceA)
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
HomogenizationA::ConstraintType _ctype
The constraint type; initialize with &#39;none&#39;.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string alpha
Definition: NS.h:134
unsigned int _m
Used internally to iterate over each scalar component.
IntRange< T > make_range(T beg, T end)
ConstraintType
Constraint type: stress/PK stress or strain/deformation gradient.
void addClassDescription(const std::string &doc_string)
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.
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...
void ErrorVector unsigned int
virtual Real computeQpOffDiagJacobianScalar(const unsigned int svar_num) override
Method for computing d-_var-residual / d-_svar at quadrature points.
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
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...