https://mooseframework.inl.gov
QuasiStaticSolidMechanicsPhysics.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 
10 #include "Conversion.h"
11 #include "FEProblem.h"
12 #include "Factory.h"
13 #include "MooseMesh.h"
14 #include "MooseObjectAction.h"
16 #include "Material.h"
18 
19 #include "BlockRestrictable.h"
20 
22 #include "AddVariableAction.h"
23 
24 #include "libmesh/string_to_enum.h"
25 #include <algorithm>
26 
27 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "meta_action");
28 
29 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "setup_mesh_complete");
30 
31 registerMooseAction("SolidMechanicsApp",
33  "validate_coordinate_systems");
34 
35 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "add_variable");
36 
37 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "add_aux_variable");
38 
39 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "add_kernel");
40 
41 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "add_aux_kernel");
42 
43 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "add_material");
44 
45 registerMooseAction("SolidMechanicsApp",
47  "add_master_action_material");
48 
49 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "add_scalar_kernel");
50 
51 registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "add_user_object");
52 
55 {
57  params.addClassDescription("Set up stress divergence kernels with coordinate system aware logic");
58 
59  // parameters specified here only appear in the input file sub-blocks of the solid mechanics
60  // action, not in the common parameters area
61  params.addParam<std::vector<SubdomainName>>("block",
62  {},
63  "The list of ids of the blocks (subdomain) "
64  "that the stress divergence kernels will be "
65  "applied to");
66  params.addParamNamesToGroup("block", "Advanced");
67 
68  params.addParam<MultiMooseEnum>("additional_generate_output",
70  "Add scalar quantity output for stress and/or strain (will be "
71  "appended to the list in `generate_output`)");
72  params.addParam<MultiMooseEnum>(
73  "additional_material_output_order",
75  "Specifies the order of the FE shape function to use for this variable.");
76 
77  params.addParam<MultiMooseEnum>(
78  "additional_material_output_family",
80  "Specifies the family of FE shape functions to use for this variable.");
81 
82  params.addParamNamesToGroup("additional_generate_output additional_material_output_order "
83  "additional_material_output_family",
84  "Output");
85  params.addParam<std::string>(
86  "strain_base_name",
87  "The base name used for the strain. If not provided, it will be set equal to base_name");
88  params.addParam<std::vector<TagName>>(
89  "extra_vector_tags",
90  "The tag names for extra vectors that residual data should be saved into");
91  params.addParam<std::vector<TagName>>("absolute_value_vector_tags",
92  "The tag names for extra vectors that the absolute value "
93  "of the residual should be accumulated into");
94  params.addParam<Real>("scaling", "The scaling to apply to the displacement variables");
95  params.addParam<Point>(
96  "cylindrical_axis_point1",
97  "Starting point for direction of axis of rotation for cylindrical stress/strain.");
98  params.addParam<Point>(
99  "cylindrical_axis_point2",
100  "Ending point for direction of axis of rotation for cylindrical stress/strain.");
101  params.addParam<Point>("spherical_center_point",
102  "Center point of the spherical coordinate system.");
103  params.addParam<Point>("direction", "Direction stress/strain is calculated in");
104  params.addParam<bool>("automatic_eigenstrain_names",
105  false,
106  "Collects all material eigenstrains and passes to required strain "
107  "calculator within TMA internally.");
108 
109  // Homogenization system input
110  params.addParam<MultiMooseEnum>(
111  "constraint_types",
113  "Type of each constraint: strain, stress, or none. The types are specified in the "
114  "column-major order, and there must be 9 entries in total.");
115  params.addParam<std::vector<FunctionName>>(
116  "targets", {}, "Functions giving the targets to hit for constraint types that are not none.");
117  params.addParam<bool>(
118  "homogenized_off_diagonal_jacobian",
119  true,
120  "Whether to include the off-diagonal scalar contributions to the homogenized jacobian");
121 
122  params.addParamNamesToGroup("scaling", "Variables");
123  params.addParamNamesToGroup("strain_base_name automatic_eigenstrain_names", "Strain");
124  params.addParamNamesToGroup(
125  "cylindrical_axis_point1 cylindrical_axis_point2 spherical_center_point direction",
126  "Coordinate system");
127  params.addParamNamesToGroup("constraint_types targets homogenized_off_diagonal_jacobian",
128  "Homogenization");
129 
130  return params;
131 }
132 
135  _displacements(getParam<std::vector<VariableName>>("displacements")),
136  _ndisp(_displacements.size()),
137  _coupled_displacements(_ndisp),
138  _save_in(getParam<std::vector<AuxVariableName>>("save_in")),
139  _diag_save_in(getParam<std::vector<AuxVariableName>>("diag_save_in")),
140  _subdomain_names(getParam<std::vector<SubdomainName>>("block")),
141  _subdomain_ids(),
142  _strain(getParam<MooseEnum>("strain").getEnum<Strain>()),
143  _planar_formulation(getParam<MooseEnum>("planar_formulation").getEnum<PlanarFormulation>()),
144  _out_of_plane_direction(
145  getParam<MooseEnum>("out_of_plane_direction").getEnum<OutOfPlaneDirection>()),
146  _base_name(isParamValid("base_name") ? getParam<std::string>("base_name") + "_" : ""),
147  _material_output_order(getParam<MultiMooseEnum>("material_output_order")),
148  _material_output_family(getParam<MultiMooseEnum>("material_output_family")),
149  _cylindrical_axis_point1_valid(params.isParamSetByUser("cylindrical_axis_point1")),
150  _cylindrical_axis_point2_valid(params.isParamSetByUser("cylindrical_axis_point2")),
151  _direction_valid(params.isParamSetByUser("direction")),
152  _verbose(getParam<bool>("verbose")),
153  _spherical_center_point_valid(params.isParamSetByUser("spherical_center_point")),
154  _auto_eigenstrain(getParam<bool>("automatic_eigenstrain_names")),
155  _compatibility_mode(getParam<bool>("compatibility_mode")),
156  _lagrangian_kernels(getParam<bool>("new_system") || _compatibility_mode),
157  _lk_large_kinematics(_strain == Strain::Finite),
158  // compatibility_mode mandates the total Lagrangian kernel; otherwise honor the user choice.
159  _lk_formulation(_compatibility_mode
160  ? LKFormulation::Total
161  : getParam<MooseEnum>("formulation").getEnum<LKFormulation>()),
162  _lk_locking(getParam<bool>("volumetric_locking_correction")),
163  _lk_homogenization(false),
164  _constraint_types(getParam<MultiMooseEnum>("constraint_types")),
165  _targets(getParam<std::vector<FunctionName>>("targets")),
166  _lk_h_off_jac(getParam<bool>("homogenized_off_diagonal_jacobian"))
167 {
168  // determine if incremental strains are to be used
169  if (isParamValid("incremental"))
170  {
171  const bool incremental = getParam<bool>("incremental");
172  if (!incremental && _strain == Strain::Small)
174  else if (!incremental && _strain == Strain::Finite)
176  else if (incremental && _strain == Strain::Small)
178  else if (incremental && _strain == Strain::Finite)
180  else
181  mooseError("Internal error");
182  }
183  else
184  {
185  if (_strain == Strain::Small)
186  {
188  mooseInfo("SolidMechanics Action: selecting 'total small strain' formulation. Use "
189  "`incremental = true` to select 'incremental small strain' instead.");
190  }
191  else if (_strain == Strain::Finite)
192  {
194  mooseInfo("SolidMechanics Action: selecting 'incremental finite strain' formulation.");
195  }
196  else
197  mooseError("Internal error");
198  }
199 
200  // determine if displaced mesh is to be used
202  if (params.isParamSetByUser("use_displaced_mesh") && !_lagrangian_kernels)
203  {
204  bool use_displaced_mesh_param = getParam<bool>("use_displaced_mesh");
205  if (use_displaced_mesh_param != _use_displaced_mesh && params.isParamSetByUser("strain"))
206  mooseError("Wrong combination of use displaced mesh and strain model");
207  _use_displaced_mesh = use_displaced_mesh_param;
208  }
209 
210  // convert vector of VariableName to vector of VariableName
211  for (unsigned int i = 0; i < _ndisp; ++i)
213 
214  if (_save_in.size() != 0 && _save_in.size() != _ndisp)
215  mooseError("Number of save_in variables should equal to the number of displacement variables ",
216  _ndisp);
217 
218  if (_diag_save_in.size() != 0 && _diag_save_in.size() != _ndisp)
219  mooseError(
220  "Number of diag_save_in variables should equal to the number of displacement variables ",
221  _ndisp);
222 
223  // plane strain consistency check
225  {
228  "moose",
229  27340,
230  "Planar formulations are not yet available through the Physics syntax with new_system = "
231  "true. They can be enabled by manually setting up the appropriate objects. Please refer "
232  "to the documentation and regression tests for examples.");
233  if (params.isParamSetByUser("out_of_plane_strain") &&
235  mooseError(
236  "out_of_plane_strain should only be specified with planar_formulation=WEAK_PLANE_STRESS");
237  else if (!params.isParamSetByUser("out_of_plane_strain") &&
239  mooseError("out_of_plane_strain must be specified with planar_formulation=WEAK_PLANE_STRESS");
240  }
241 
242  // convert output variable names to lower case
243  for (const auto & out : getParam<MultiMooseEnum>("generate_output"))
244  {
245  std::string lower(out);
246  std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
247  _generate_output.push_back(lower);
248  }
249 
250  if (!_generate_output.empty())
252 
253  // Error if volumetric locking correction is true for 1D problems
254  if (_ndisp == 1 && getParam<bool>("volumetric_locking_correction"))
255  mooseError("Volumetric locking correction should be set to false for 1D problems.");
256 
257  if (!getParam<bool>("add_variables") && params.isParamSetByUser("scaling"))
258  paramError("scaling",
259  "The scaling parameter has no effect unless add_variables is set to true. Did you "
260  "mean to set 'add_variables = true'?");
261 
262  // Get cylindrical axis points if set by user
264  {
265  _cylindrical_axis_point1 = getParam<Point>("cylindrical_axis_point1");
266  _cylindrical_axis_point2 = getParam<Point>("cylindrical_axis_point2");
267  }
268 
269  // Get spherical center point if set by user
271  _spherical_center_point = getParam<Point>("spherical_center_point");
272 
273  // Get direction for tensor component if set by user
274  if (_direction_valid)
275  _direction = getParam<Point>("direction");
276 
277  // Get eigenstrain names if passed by user
278  _eigenstrain_names = getParam<std::vector<MaterialPropertyName>>("eigenstrain_names");
279 
280  // Determine if we're going to use the homogenization system for the new
281  // lagrangian kernels
282  bool ctype_set = params.isParamSetByUser("constraint_types");
283  bool targets_set = params.isParamSetByUser("targets");
284  if (ctype_set || targets_set)
285  {
286  if (!(ctype_set && targets_set))
287  mooseError("To use the Lagrangian kernel homogenization system you "
288  "most provide both the constraint_types and the targets "
289  "parameters");
290  _lk_homogenization = true;
291  // Do consistency checking on the kernel options
293  mooseError("The Lagrangian kernel homogenization system requires the "
294  "use of formulation = TOTAL");
295  }
296 
297  // The action drives two mutually exclusive kernel systems: the legacy
298  // StressDivergenceTensors + ComputeFiniteStrain system, and the new Lagrangian kernel system
299  // (new_system / compatibility_mode). Many parameters belong exclusively to one system; setting
300  // one that does not match the active system is almost always a copy-paste error, so reject it
301  // explicitly with a clear message instead of silently ignoring it. The lists below are the
302  // single place to register a parameter as system-specific.
303  static const std::vector<std::string> new_system_only = {
304  "formulation", "constraint_types", "targets", "homogenized_off_diagonal_jacobian"};
305  static const std::vector<std::string> legacy_only = {"use_finite_deform_jacobian",
306  "global_strain"};
307 
309  {
310  for (const auto & p : legacy_only)
311  if (params.isParamSetByUser(p))
312  paramError(p,
313  "'",
314  p,
315  "' belongs to the legacy StressDivergenceTensors kernel system and cannot be "
316  "combined with new_system = true or compatibility_mode = true. The Lagrangian "
317  "kernel system produces the exact Jacobian natively; homogenization replaces "
318  "global_strain.");
319 
320  // use_automatic_differentiation is a value (defaults false); reject only when requested.
321  if (_use_ad)
322  paramError("use_automatic_differentiation",
323  "The Lagrangian kernel system is not yet compatible with automatic "
324  "differentiation.");
325 
326  // decomposition_method is legal only in compatibility_mode, where it maps to the strain
327  // calculator's kinematic_approximation; plain new_system exposes those options directly on the
328  // ComputeLagrangianStrain material via `kinematic_approximation`.
329  if (params.isParamSetByUser("decomposition_method") && !_compatibility_mode)
330  paramError("decomposition_method",
331  "decomposition_method is not used by the Lagrangian kernel system. Set the "
332  "equivalent option on the ComputeLagrangianStrain material via "
333  "kinematic_approximation instead.");
334 
335  // compatibility_mode-specific consistency checks.
337  {
338  if (params.isParamSetByUser("formulation") &&
339  getParam<MooseEnum>("formulation").getEnum<LKFormulation>() != LKFormulation::Total)
340  paramError("formulation",
341  "compatibility_mode requires formulation = TOTAL (the OLD kernel system is "
342  "always total Lagrangian on the displaced mesh).");
343 
344  if (_lk_large_kinematics && params.isParamSetByUser("kinematic_approximation"))
345  paramError("kinematic_approximation",
346  "compatibility_mode derives kinematic_approximation from decomposition_method; "
347  "do not set it explicitly.");
349  params.isParamSetByUser("volumetric_locking_correction_mode"))
350  paramError("volumetric_locking_correction_mode",
351  "compatibility_mode derives the F-bar mode from volumetric_locking_correction; "
352  "do not set volumetric_locking_correction_mode explicitly.");
353  if (params.isParamSetByUser("generalized_midpoint_alpha"))
354  paramError("generalized_midpoint_alpha",
355  "compatibility_mode reproduces the legacy backward-Euler update; do not set "
356  "generalized_midpoint_alpha explicitly.");
357 
358  // Validate decomposition_method <-> kinematic_approximation mapping. The NEW strain
359  // calculator's `rashid_approximate` and `rashid_eigen` reproduce OLD's `TaylorExpansion`
360  // and `EigenSolution` exactly; OLD's `HughesWinget` has no NEW counterpart.
362  {
363  const std::string decomp = getParam<MooseEnum>("decomposition_method");
364  if (decomp != "TaylorExpansion" && decomp != "EigenSolution")
365  paramError("decomposition_method",
366  "compatibility_mode + strain = FINITE supports only "
367  "decomposition_method = TaylorExpansion or EigenSolution; '",
368  decomp,
369  "' has no Lagrangian kinematic_approximation counterpart.");
370  }
371  }
372  }
373  else
374  {
375  for (const auto & p : new_system_only)
376  if (params.isParamSetByUser(p))
377  paramError(p,
378  "'",
379  p,
380  "' belongs to the new Lagrangian kernel system. Set new_system = true (or "
381  "compatibility_mode = true) to use it.");
382  }
383 }
384 
385 void
387 {
388  std::string ad_prepend = "";
389  if (_use_ad)
390  ad_prepend = "AD";
391 
392  // Consistency checks across subdomains
394 
395  // Gather info from all other QuasiStaticSolidMechanicsPhysics
397 
398  // Deal with the optional AuxVariable based tensor quantity output
400 
401  // Meta action which optionally spawns other actions
402  if (_current_task == "meta_action")
403  {
405  {
406  if (_use_ad)
407  paramError("use_automatic_differentiation", "AD not setup for use with PlaneStrain");
408  // Set the action parameters
409  const std::string type = "GeneralizedPlaneStrainAction";
410  auto action_params = _action_factory.getValidParams(type);
411  action_params.set<bool>("_built_by_moose") = true;
412  action_params.set<std::string>("registered_identifier") = "(AutoBuilt)";
413 
414  // Skipping selected parameters in applyParameters() and then manually setting them only if
415  // they are set by the user is just to prevent both the current and deprecated variants of
416  // these parameters from both getting passed to the UserObject. Once we get rid of the
417  // deprecated versions, we can just set them all with applyParameters().
418  action_params.applyParameters(parameters(),
419  {"use_displaced_mesh",
420  "out_of_plane_pressure",
421  "out_of_plane_pressure_function",
422  "factor",
423  "pressure_factor"});
424  action_params.set<bool>("use_displaced_mesh") = _use_displaced_mesh;
425 
426  if (parameters().isParamSetByUser("out_of_plane_pressure"))
427  action_params.set<FunctionName>("out_of_plane_pressure") =
428  getParam<FunctionName>("out_of_plane_pressure");
429  if (parameters().isParamSetByUser("out_of_plane_pressure_function"))
430  action_params.set<FunctionName>("out_of_plane_pressure_function") =
431  getParam<FunctionName>("out_of_plane_pressure_function");
432  if (parameters().isParamSetByUser("factor"))
433  action_params.set<Real>("factor") = getParam<Real>("factor");
434  if (parameters().isParamSetByUser("pressure_factor"))
435  action_params.set<Real>("pressure_factor") = getParam<Real>("pressure_factor");
436 
437  // Create and add the action to the warehouse
438  auto action = MooseSharedNamespace::static_pointer_cast<MooseObjectAction>(
439  _action_factory.create(type, name() + "_gps", action_params));
440  _awh.addActionBlock(action);
441  }
442  }
443 
444  // Add variables
445  else if (_current_task == "add_variable")
446  {
447  // Add variables here only if the CommonSolidMechanicsAction does not exist.
448  // This happens notably if the QuasiStaticSolidMechanics was created by a meta_action
449  const auto common_actions = _awh.getActions<CommonSolidMechanicsAction>();
450  if (common_actions.empty() && getParam<bool>("add_variables"))
451  {
452  auto params = _factory.getValidParams("MooseVariable");
453  // determine necessary order
454  const bool second = _problem->mesh().hasSecondOrderElements();
455 
456  params.set<MooseEnum>("order") = second ? "SECOND" : "FIRST";
457  params.set<MooseEnum>("family") = "LAGRANGE";
458  if (isParamValid("scaling"))
459  params.set<std::vector<Real>>("scaling") = {getParam<Real>("scaling")};
460 
461  // Note how we do not add the block restriction because BISON's meta-actions
462  // currently rely on them not being added.
463 
464  // Loop through the displacement variables
465  for (const auto & disp : _displacements)
466  {
467  // Create displacement variables
468  _problem->addVariable("MooseVariable", disp, params);
469  }
470  }
471 
472  // Homogenization scalar
473  if (_lk_homogenization)
474  {
475  InputParameters params = _factory.getValidParams("MooseVariable");
476  const std::map<bool, std::vector<unsigned int>> mg_order_max{{true, {1, 4, 9}},
477  {false, {1, 3, 6}}};
478  std::size_t mg_order = 0;
479  for (auto i : index_range(_constraint_types))
480  {
481  const auto ctype = static_cast<Homogenization::ConstraintType>(_constraint_types.get(i));
483  mg_order++;
484  }
485  if (mg_order > mg_order_max.at(_lk_large_kinematics)[_ndisp - 1])
486  paramError("constraint_types",
487  "Number of non-none constraint types must not be greater than ",
488  mg_order_max.at(_lk_large_kinematics)[_ndisp - 1],
489  ", but ",
490  mg_order,
491  " are provided.");
492  params.set<MooseEnum>("family") = "SCALAR";
493  params.set<MooseEnum>("order") = mg_order;
494  auto fe_type = AddVariableAction::feType(params);
495  auto var_type = AddVariableAction::variableType(fe_type);
496  _problem->addVariable(var_type, _hname, params);
497  }
498  }
499  // Add Materials
500  else if (_current_task == "add_master_action_material")
501  {
502  // Automatic eigenstrain names
503  if (_auto_eigenstrain)
505 
506  // Easiest just to branch on type here, as the strain systems are completely
507  // different
510  else
512  }
513 
514  // Add Stress Divergence (and optionally WeakPlaneStress) Kernels
515  else if (_current_task == "add_kernel")
516  {
517  for (unsigned int i = 0; i < _ndisp; ++i)
518  {
519  auto tensor_kernel_type = getKernelType();
520  auto params = getKernelParameters(ad_prepend + tensor_kernel_type);
521 
522  std::string kernel_name = "TM_" + name() + Moose::stringify(i);
523 
524  // Set appropriate components for kernels, including in the cases where a planar model is
525  // running in planes other than the x-y plane (defined by _out_of_plane_strain_direction).
527  continue;
528  else if (_out_of_plane_direction == OutOfPlaneDirection::y && i == 1)
529  continue;
530 
531  params.set<unsigned int>("component") = i;
532 
533  params.set<NonlinearVariableName>("variable") = _displacements[i];
534 
535  if (_save_in.size() == _ndisp)
536  params.set<std::vector<AuxVariableName>>("save_in") = {_save_in[i]};
537  if (_diag_save_in.size() == _ndisp)
538  params.set<std::vector<AuxVariableName>>("diag_save_in") = {_diag_save_in[i]};
539  if (isParamValid("out_of_plane_strain") && !_lagrangian_kernels)
540  params.set<std::vector<VariableName>>("out_of_plane_strain") = {
541  getParam<VariableName>("out_of_plane_strain")};
542 
543  if (_lk_homogenization)
544  {
545  params.set<std::vector<VariableName>>("scalar_variable") = {_hname};
546  params.set<MultiMooseEnum>("constraint_types") = _constraint_types;
547  params.set<std::vector<FunctionName>>("targets") = _targets;
548  }
549 
550  _problem->addKernel(ad_prepend + tensor_kernel_type, kernel_name, params);
551  }
552 
554  {
555  auto params = getKernelParameters(ad_prepend + "WeakPlaneStress");
556  std::string wps_kernel_name = "TM_WPS_" + name();
557  params.set<NonlinearVariableName>("variable") = getParam<VariableName>("out_of_plane_strain");
558 
559  _problem->addKernel(ad_prepend + "WeakPlaneStress", wps_kernel_name, params);
560  }
561  }
562 }
563 
564 void
566 {
567  // Do the coordinate system check only once the problem is created
568  if (_current_task == "setup_mesh_complete")
569  {
570  // get subdomain IDs
571  for (auto & name : _subdomain_names)
572  {
573  auto id = _mesh->getSubdomainID(name);
574  if (id == Moose::INVALID_BLOCK_ID)
575  paramError("block", "Subdomain \"" + name + "\" not found in mesh.");
576  else
577  _subdomain_ids.insert(id);
578  }
579  }
580 
581  if (_current_task == "validate_coordinate_systems")
582  {
583  // use either block restriction list or list of all subdomains in the mesh
584  const auto & check_subdomains =
585  _subdomain_ids.empty() ? _problem->mesh().meshSubdomains() : _subdomain_ids;
586  if (check_subdomains.empty())
587  mooseError("No subdomains found");
588 
589  // make sure all subdomains are using the same coordinate system
590  _coord_system = _problem->getCoordSystem(*check_subdomains.begin());
591  for (auto subdomain : check_subdomains)
592  if (_problem->getCoordSystem(subdomain) != _coord_system)
593  mooseError("The SolidMechanics action requires all subdomains to have the same coordinate "
594  "system.");
595 
597  {
599  mooseError("'out_of_plane_direction' must be 'z' for axisymmetric simulations");
600  }
602  {
604  mooseError(
605  "Must specify two displacements for plane strain when the out of plane direction is z");
607  mooseError("Must specify three displacements for plane strain when the out of plane "
608  "direction is x or y");
609  }
610  }
611 }
612 
613 void
615 {
616  if (_current_task == "add_material")
618 
619  // Add variables (optional)
620  if (_current_task == "add_aux_variable")
621  {
622  unsigned int index = 0;
623  for (auto out : _generate_output)
624  {
625  const auto & order = _material_output_order[index];
626  const auto & family = _material_output_family[index];
627 
628  std::string type = (order == "CONSTANT" && family == "MONOMIAL")
629  ? "MooseVariableConstMonomial"
630  : "MooseVariable";
631 
632  // Create output helper aux variables
633  auto params = _factory.getValidParams(type);
634  params.set<MooseEnum>("order") = order;
635  params.set<MooseEnum>("family") = family;
636 
637  if (family == "MONOMIAL")
638  _problem->addAuxVariable(type, _base_name + out, params);
639  else
640  _problem->addVariable(type, _base_name + out, params);
641 
642  index++;
643  }
644  }
645 
646  // Add output AuxKernels
647  else if (_current_task == "add_aux_kernel")
648  {
649  std::string ad_prepend = _use_ad ? "AD" : "";
650  // Loop through output aux variables
651  unsigned int index = 0;
652  for (auto out : _generate_output)
653  {
654  if (_material_output_family[index] == "MONOMIAL")
655  {
657 
658  params = _factory.getValidParams("MaterialRealAux");
659  params.applyParameters(parameters());
660  params.set<MaterialPropertyName>("property") = _base_name + out;
661  params.set<AuxVariableName>("variable") = _base_name + out;
662  params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
663 
664  _problem->addAuxKernel(
665  ad_prepend + "MaterialRealAux", _base_name + out + '_' + name(), params);
666  }
667  index++;
668  }
669  }
670  else if (_current_task == "add_kernel")
671  {
672  std::string ad_prepend = _use_ad ? "AD" : "";
673  // Loop through output aux variables
674  unsigned int index = 0;
675  for (auto out : _generate_output)
676  {
677  if (_material_output_family[index] != "MONOMIAL")
678  {
680 
681  params = _factory.getValidParams("MaterialPropertyValue");
682  params.applyParameters(parameters());
683  params.set<MaterialPropertyName>("prop_name") = _base_name + out;
684  params.set<NonlinearVariableName>("variable") = _base_name + out;
685 
686  _problem->addKernel(
687  ad_prepend + "MaterialPropertyValue", _base_name + out + '_' + name(), params);
688  }
689  index++;
690  }
691  }
692 }
693 
694 void
696 {
697  // Create containers for collecting blockIDs and eigenstrain names from materials
698  std::map<std::string, std::set<SubdomainID>> material_eigenstrain_map;
699  std::set<std::string> eigenstrain_set;
700 
701  std::set<MaterialPropertyName> verified_eigenstrain_names;
702 
703  std::map<std::string, std::string> remove_add_map;
704  std::set<std::string> remove_reduced_set;
705 
706  // Loop over all the materials(eigenstrains) already created
707  auto materials = _problem->getMaterialWarehouse().getObjects();
708  for (auto & mat : materials)
709  {
710  std::shared_ptr<BlockRestrictable> blk = std::dynamic_pointer_cast<BlockRestrictable>(mat);
711  const InputParameters & mat_params = mat->parameters();
712  auto & mat_name = mat->type();
713 
714  // Check for eigenstrain names, only deal with those materials
715  if (mat_params.isParamValid("eigenstrain_name"))
716  {
717  std::shared_ptr<MaterialData> mat_dat;
718  auto name = mat_params.get<std::string>("eigenstrain_name");
719 
720  // Check for base_name prefix
721  if (mat_params.isParamValid("base_name"))
722  name = mat_params.get<std::string>("base_name") + '_' + name;
723 
724  // Check block restrictions
725  if (!blk)
726  mooseError("Internal error, Material object that does not inherit form BlockRestricted");
727  const std::set<SubdomainID> & blocks =
728  blk->blockRestricted() ? blk->blockIDs() : blk->meshBlockIDs();
729 
730  if (std::includes(blocks.begin(), blocks.end(), _subdomain_ids.begin(), _subdomain_ids.end()))
731  {
732  material_eigenstrain_map[name].insert(blocks.begin(), blocks.end());
733  eigenstrain_set.insert(name);
734  }
735  }
736 
737  // Account for reduced eigenstrains and CompositeEigenstrains
738  if (mat_name == "ComputeReducedOrderEigenstrain")
739  {
740  auto input_eigenstrain_names =
741  mat_params.get<std::vector<MaterialPropertyName>>("input_eigenstrain_names");
742  remove_reduced_set.insert(input_eigenstrain_names.begin(), input_eigenstrain_names.end());
743  }
744  // Account for CompositeEigenstrains
745  if (mat_name == "CompositeEigenstrain")
746  {
747  auto remove_list = mat_params.get<std::vector<MaterialPropertyName>>("tensors");
748  for (auto i : remove_list)
749  remove_reduced_set.insert(i);
750  }
751 
752  // Account for MaterialADConverter , add or remove later
753  if (mat_name == "RankTwoTensorMaterialADConverter")
754  {
755  std::vector<MaterialPropertyName> remove_list;
756  std::vector<MaterialPropertyName> add_list;
757 
758  if (mat_params.isParamValid("ad_props_out") && mat_params.isParamValid("reg_props_in") &&
759  _use_ad)
760  {
761  remove_list = mat_params.get<std::vector<MaterialPropertyName>>("reg_props_in");
762  add_list = mat_params.get<std::vector<MaterialPropertyName>>("ad_props_out");
763  }
764  if (mat_params.isParamValid("ad_props_in") && mat_params.isParamValid("reg_props_out") &&
765  !_use_ad)
766  {
767  remove_list = mat_params.get<std::vector<MaterialPropertyName>>("ad_props_in");
768  add_list = mat_params.get<std::vector<MaterialPropertyName>>("reg_props_out");
769  }
770 
771  // These vectors are the same size as checked in MaterialADConverter
772  for (unsigned int index = 0; index < remove_list.size(); index++)
773  remove_add_map.emplace(remove_list[index], add_list[index]);
774  }
775  }
776  // All the materials have been accounted for, now remove or add parts
777 
778  // Remove names which aren't eigenstrains (converter properties)
779  for (auto remove_add_index : remove_add_map)
780  {
781  const bool is_in = eigenstrain_set.find(remove_add_index.first) != eigenstrain_set.end();
782  if (is_in)
783  {
784  eigenstrain_set.erase(remove_add_index.first);
785  eigenstrain_set.insert(remove_add_index.second);
786  }
787  }
788  for (auto index : remove_reduced_set)
789  eigenstrain_set.erase(index);
790 
791  // Compare the blockIDs set of eigenstrain names with the vector of _eigenstrain_names for the
792  // current subdomainID
793  std::set_union(eigenstrain_set.begin(),
794  eigenstrain_set.end(),
795  _eigenstrain_names.begin(),
796  _eigenstrain_names.end(),
797  std::inserter(verified_eigenstrain_names, verified_eigenstrain_names.begin()));
798 
799  // Ensure the eigenstrain names previously passed include any missing names
800  _eigenstrain_names.resize(verified_eigenstrain_names.size());
801  std::copy(verified_eigenstrain_names.begin(),
802  verified_eigenstrain_names.end(),
803  _eigenstrain_names.begin());
804 
805  Moose::out << COLOR_CYAN << "*** Automatic Eigenstrain Names ***"
806  << "\n"
807  << _name << ": " << Moose::stringify(_eigenstrain_names) << "\n"
808  << COLOR_DEFAULT << std::flush;
809 }
810 
811 void
813 {
814  // Ensure material output order and family vectors are same size as generate output
815 
816  // check number of supplied orders and families
818  paramError("material_output_order",
819  "The number of orders assigned to material outputs must be: 0 to be assigned "
820  "CONSTANT; 1 to assign all outputs the same value, or the same size as the number "
821  "of generate outputs listed.");
822 
823  if (_material_output_family.size() > 1 &&
825  paramError("material_output_family",
826  "The number of families assigned to material outputs must be: 0 to be assigned "
827  "MONOMIAL; 1 to assign all outputs the same value, or the same size as the number "
828  "of generate outputs listed.");
829 
830  // if no value was provided, chose the default CONSTANT
831  if (_material_output_order.size() == 0)
833 
834  // For only one order, make all orders the same magnitude
835  if (_material_output_order.size() == 1)
837  std::vector<std::string>(_generate_output.size(), _material_output_order[0]);
838 
839  if (_verbose)
840  Moose::out << COLOR_CYAN << "*** Automatic applied material output orders ***"
841  << "\n"
842  << _name << ": " << Moose::stringify(_material_output_order) << "\n"
843  << COLOR_DEFAULT << std::flush;
844 
845  // if no value was provided, chose the default MONOMIAL
846  if (_material_output_family.size() == 0)
848 
849  // For only one family, make all families that value
850  if (_material_output_family.size() == 1)
852  std::vector<std::string>(_generate_output.size(), _material_output_family[0]);
853 
854  if (_verbose)
855  Moose::out << COLOR_CYAN << "*** Automatic applied material output families ***"
856  << "\n"
857  << _name << ": " << Moose::stringify(_material_output_family) << "\n"
858  << COLOR_DEFAULT << std::flush;
859 }
860 
861 std::string
863 {
864  // The OLD pipeline publishes `stress` and `mechanical_strain` directly. The NEW pipeline
865  // publishes Cauchy stress under `cauchy_stress` and (when the strain calc is configured for
866  // OLD compatibility) the OLD-equivalent mechanical strain under `rotated_mechanical_strain`.
867  // Redirect the underlying property name so user output requests like `stress_xx` keep their
868  // OLD-style aux variable name but read from the NEW-style source.
869  if (!_compatibility_mode)
870  return prop_name;
871  if (prop_name == "stress")
872  return "cauchy_stress";
873  if (prop_name == "mechanical_strain")
874  return "rotated_mechanical_strain";
875  return prop_name;
876 }
877 
878 void
880 {
881  std::string ad_prepend = _use_ad ? "AD" : "";
882 
883  if (_current_task == "add_material")
884  {
885  // Add output Materials
886  for (auto out : _generate_output)
887  {
889 
890  // RankTwoCartesianComponent
891  if (
892  [&]()
893  {
894  for (const auto & r2q : _rank_two_cartesian_component_table)
895  for (unsigned int a = 0; a < 3; ++a)
896  for (unsigned int b = 0; b < 3; ++b)
897  if (r2q.first + '_' + _component_table[a] + _component_table[b] == out)
898  {
899  auto type = ad_prepend + "RankTwoCartesianComponent";
900  params = _factory.getValidParams(type);
901  params.set<MaterialPropertyName>("rank_two_tensor") =
902  _base_name + remapCompatOutputProp(r2q.second);
903  params.set<unsigned int>("index_i") = a;
904  params.set<unsigned int>("index_j") = b;
905 
906  params.applyParameters(parameters());
907  params.set<MaterialPropertyName>("property_name") = _base_name + out;
908  _problem->addMaterial(type, _base_name + out + '_' + name(), params);
909  return true;
910  }
911  return false;
912  }())
913  continue;
914 
915  // RankTwoDirectionalComponent
916  if (setupOutput(out,
918  [&](std::string prop_name, std::string invariant)
919  {
920  auto type = ad_prepend + "RankTwoDirectionalComponent";
921  params = _factory.getValidParams(type);
922  params.set<MaterialPropertyName>("rank_two_tensor") =
923  _base_name + remapCompatOutputProp(prop_name);
924  params.set<MooseEnum>("invariant") = invariant;
925  params.applyParameters(parameters());
926  params.set<MaterialPropertyName>("property_name") = _base_name + out;
927  _problem->addMaterial(type, _base_name + out + '_' + name(), params);
928  }))
929  continue;
930 
931  // RankTwoInvariant
932  if (setupOutput(out,
934  [&](std::string prop_name, std::string invariant)
935  {
936  auto type = ad_prepend + "RankTwoInvariant";
937  params = _factory.getValidParams(type);
938  params.set<MaterialPropertyName>("rank_two_tensor") =
939  _base_name + remapCompatOutputProp(prop_name);
940  params.set<MooseEnum>("invariant") = invariant;
941  params.applyParameters(parameters());
942  params.set<MaterialPropertyName>("property_name") = _base_name + out;
943  _problem->addMaterial(type, _base_name + out + '_' + name(), params);
944  }))
945  continue;
946 
947  // RankTwoCylindricalComponent
948  if (setupOutput(
949  out,
951  [&](std::string prop_name, std::string component)
952  {
954  mooseError(
955  "Cannot use cylindrical component output in a spherical coordinate system.");
956  auto type = ad_prepend + "RankTwoCylindricalComponent";
957  params = _factory.getValidParams(type);
958  params.set<MaterialPropertyName>("rank_two_tensor") =
959  _base_name + remapCompatOutputProp(prop_name);
960  params.set<MooseEnum>("cylindrical_component") = component;
961  params.applyParameters(parameters());
962  params.set<MaterialPropertyName>("property_name") = _base_name + out;
963  _problem->addMaterial(type, _base_name + out + '_' + name(), params);
964  }))
965  continue;
966 
967  // RankTwoSphericalComponent
968  if (setupOutput(out,
970  [&](std::string prop_name, std::string component)
971  {
972  auto type = ad_prepend + "RankTwoSphericalComponent";
973  params = _factory.getValidParams(type);
974  params.set<MaterialPropertyName>("rank_two_tensor") =
975  _base_name + remapCompatOutputProp(prop_name);
976  params.set<MooseEnum>("spherical_component") = component;
977  params.applyParameters(parameters());
978  params.set<MaterialPropertyName>("property_name") = _base_name + out;
979  _problem->addMaterial(type, _base_name + out + '_' + name(), params);
980  }))
981  continue;
982 
983  paramError("generate_output", "Unable to add output Material for '", out, "'");
984  }
985  }
986 }
987 
988 void
990 {
991  // Gather info about all other solid mechanics physics when we add variables
992  if (_current_task == "validate_coordinate_systems" && getParam<bool>("add_variables"))
993  {
995  for (const auto & action : actions)
996  {
997  const auto size_before = _subdomain_id_union.size();
998  const auto added_size = action->_subdomain_ids.size();
999  _subdomain_id_union.insert(action->_subdomain_ids.begin(), action->_subdomain_ids.end());
1000  const auto size_after = _subdomain_id_union.size();
1001 
1002  if (size_after != size_before + added_size)
1003  mooseError("The block restrictions in the SolidMechanics/QuasiStatic actions must be "
1004  "non-overlapping.");
1005 
1006  if (added_size == 0 && actions.size() > 1)
1007  mooseError(
1008  "No SolidMechanics/QuasiStatic action can be block unrestricted if more than one "
1009  "SolidMechanics/QuasiStatic action is specified.");
1010  }
1011  }
1012 }
1013 
1014 void
1016 {
1017  std::string type;
1019  type = "ComputeLagrangianStrain";
1020  else if (_coord_system == Moose::COORD_RZ)
1021  type = "ComputeLagrangianStrainAxisymmetricCylindrical";
1023  type = "ComputeLagrangianStrainCentrosymmetricSpherical";
1024  else
1025  mooseError("Unsupported coordinate system");
1026 
1027  auto params = _factory.getValidParams(type);
1028 
1029  if (isParamValid("strain_base_name"))
1030  params.set<std::string>("base_name") = getParam<std::string>("strain_base_name");
1031 
1032  params.set<std::vector<VariableName>>("displacements") = _coupled_displacements;
1033  params.set<std::vector<MaterialPropertyName>>("eigenstrain_names") = _eigenstrain_names;
1034  params.set<bool>("large_kinematics") = _lk_large_kinematics;
1035  params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
1036 
1037  // Error if volumetric locking correction is on for higher-order elements
1038  if (_problem->mesh().hasSecondOrderElements() && _lk_locking)
1039  mooseError("Volumetric locking correction should not be used for "
1040  "higher-order elements.");
1041 
1042  params.set<bool>("stabilize_strain") = _lk_locking;
1043 
1044  // Forward the strain time-integration options. In compatibility mode kinematic_approximation
1045  // and F_bar_mode are overridden below (and the action errors if the user also set them).
1046  params.set<MooseEnum>("kinematic_approximation") = getParam<MooseEnum>("kinematic_approximation");
1047  params.set<Real>("alpha") = getParam<Real>("generalized_midpoint_alpha");
1048  params.set<MooseEnum>("F_bar_mode") = getParam<MooseEnum>("volumetric_locking_correction_mode");
1049 
1050  if (_lk_homogenization)
1051  {
1052  params.set<std::vector<MaterialPropertyName>>("homogenization_gradient_names") = {
1054  }
1055 
1056  // OLD-compat configuration: map decomposition_method -> kinematic_approximation, switch the
1057  // F-bar to incremental mode (matches OLD `ComputeFiniteStrain`'s `_Fhat` F-bar), and have
1058  // the strain calc publish a real rotation_increment so the wrapped ComputeStressBase
1059  // material's FSR rotates correctly across steps.
1060  if (_compatibility_mode)
1061  {
1063  {
1064  const std::string decomp = getParam<MooseEnum>("decomposition_method");
1065  if (decomp == "TaylorExpansion")
1066  params.set<MooseEnum>("kinematic_approximation") = "rashid_approximate";
1067  else if (decomp == "EigenSolution")
1068  params.set<MooseEnum>("kinematic_approximation") = "rashid_eigen";
1069  // HughesWinget rejected in the ctor; SMALL strain ignores kinematic_approximation.
1070  }
1071 
1072  // OLD's `volumetric_locking_correction = true` in incremental finite strain maps to
1073  // `F_bar_mode = incremental` on the NEW strain calc. The strain calc rejects
1074  // `incremental` for small kinematics -- for SMALL + locking we leave `F_bar_mode` at its
1075  // default (`total`), which is the additive trace correction (matches OLD's small-strain
1076  // B-bar in the locked-flag-equivalent form).
1078  params.set<MooseEnum>("F_bar_mode") = "incremental";
1079 
1080  // Only meaningful with FINITE -- in SMALL the wrap runs in passthrough-off mode and the
1081  // rotation increment isn't consumed downstream.
1082  params.set<bool>("publish_rotation_increment") = _lk_large_kinematics;
1083  }
1084 
1085  _problem->addMaterial(type, name() + "_strain", params);
1086 
1087  // OLD-compat configuration: auto-add ComputeLagrangianWrappedStress around the user's
1088  // ComputeStressBase-style stress material. `input_stress = "stress"` and
1089  // `input_jacobian = "Jacobian_mult"` default to the property names every
1090  // ComputeStressBase descendant publishes.
1091  if (_compatibility_mode)
1092  {
1093  const std::string wrap_type = "ComputeLagrangianWrappedStress";
1094  auto wrap_params = _factory.getValidParams(wrap_type);
1095  if (isParamValid("base_name"))
1096  wrap_params.set<std::string>("base_name") = getParam<std::string>("base_name");
1097  wrap_params.set<std::vector<SubdomainName>>("block") = _subdomain_names;
1098  // large_kinematics is derived from the strain calculator's LARGE_KINEMATICS guarantee.
1099  wrap_params.set<MooseEnum>("objective_rate") = "rashid";
1100  // FINITE: the wrap runs in passthrough mode (the wrapped material's FSR already produced
1101  // the correctly-rotated cumulative Cauchy stress, fed by our published rotation_increment).
1102  // SMALL: nothing to rotate, plain Cauchy passthrough via the rate's small-kinematics branch.
1103  wrap_params.set<bool>("rotate_old_stress") = _lk_large_kinematics;
1104  _problem->addMaterial(wrap_type, name() + "_compatibility_wrap", wrap_params);
1105  }
1106 
1107  // Add the homogenization strain calculator
1108  if (_lk_homogenization)
1109  {
1110  std::string type = "ComputeHomogenizedLagrangianStrain";
1111  auto params = _factory.getValidParams(type);
1112 
1113  params.set<MaterialPropertyName>("homogenization_gradient_name") = _homogenization_strain_name;
1114  params.set<std::vector<VariableName>>("macro_gradient") = {_hname};
1115  params.set<MultiMooseEnum>("constraint_types") = _constraint_types;
1116  params.set<std::vector<FunctionName>>("targets") = _targets;
1117 
1118  _problem->addMaterial(type, name() + "_compute_" + _homogenization_strain_name, params);
1119  }
1120 }
1121 
1122 void
1124 {
1125  std::string ad_prepend = _use_ad ? "AD" : "";
1126 
1127  std::string type;
1128 
1129  // no plane strain
1131  {
1132  std::map<std::pair<Moose::CoordinateSystemType, StrainAndIncrement>, std::string> type_map = {
1133  {{Moose::COORD_XYZ, StrainAndIncrement::SmallTotal}, "ComputeSmallStrain"},
1134  {{Moose::COORD_XYZ, StrainAndIncrement::SmallIncremental}, "ComputeIncrementalStrain"},
1135  {{Moose::COORD_XYZ, StrainAndIncrement::FiniteIncremental}, "ComputeFiniteStrain"},
1136  {{Moose::COORD_RZ, StrainAndIncrement::SmallTotal}, "ComputeAxisymmetricRZSmallStrain"},
1138  "ComputeAxisymmetricRZIncrementalStrain"},
1140  "ComputeAxisymmetricRZFiniteStrain"},
1141  {{Moose::COORD_RSPHERICAL, StrainAndIncrement::SmallTotal}, "ComputeRSphericalSmallStrain"},
1143  "ComputeRSphericalIncrementalStrain"},
1145  "ComputeRSphericalFiniteStrain"}};
1146 
1147  auto type_it = type_map.find(std::make_pair(_coord_system, _strain_and_increment));
1148  if (type_it != type_map.end())
1149  type = type_it->second;
1150  else
1151  mooseError("Unsupported strain formulation");
1152  }
1156  {
1159  paramError("use_automatic_differentiation",
1160  "AD not setup for use with PlaneStrain or GeneralizedPlaneStrain");
1161 
1162  std::map<std::pair<Moose::CoordinateSystemType, StrainAndIncrement>, std::string> type_map = {
1163  {{Moose::COORD_XYZ, StrainAndIncrement::SmallTotal}, "ComputePlaneSmallStrain"},
1164  {{Moose::COORD_XYZ, StrainAndIncrement::SmallIncremental}, "ComputePlaneIncrementalStrain"},
1165  {{Moose::COORD_XYZ, StrainAndIncrement::FiniteIncremental}, "ComputePlaneFiniteStrain"},
1166  {{Moose::COORD_RZ, StrainAndIncrement::SmallTotal}, "ComputeAxisymmetric1DSmallStrain"},
1168  "ComputeAxisymmetric1DIncrementalStrain"},
1170  "ComputeAxisymmetric1DFiniteStrain"}};
1171 
1172  // choose kernel type based on coordinate system
1173  auto type_it = type_map.find(std::make_pair(_coord_system, _strain_and_increment));
1174  if (type_it != type_map.end())
1175  type = type_it->second;
1176  else
1177  mooseError("Unsupported coordinate system for plane strain.");
1178  }
1179  else
1180  mooseError("Unsupported planar formulation");
1181 
1182  // set material parameters
1183  auto params = _factory.getValidParams(ad_prepend + type);
1184  params.applyParameters(
1185  parameters(),
1186  {"displacements", "use_displaced_mesh", "out_of_plane_strain", "scalar_out_of_plane_strain"});
1187 
1188  if (isParamValid("strain_base_name"))
1189  params.set<std::string>("base_name") = getParam<std::string>("strain_base_name");
1190 
1191  params.set<std::vector<VariableName>>("displacements") = _coupled_displacements;
1192  params.set<bool>("use_displaced_mesh") = false;
1193 
1194  if (isParamValid("scalar_out_of_plane_strain"))
1195  params.set<std::vector<VariableName>>("scalar_out_of_plane_strain") = {
1196  getParam<VariableName>("scalar_out_of_plane_strain")};
1197 
1198  if (isParamValid("out_of_plane_strain"))
1199  params.set<std::vector<VariableName>>("out_of_plane_strain") = {
1200  getParam<VariableName>("out_of_plane_strain")};
1201 
1202  params.set<std::vector<MaterialPropertyName>>("eigenstrain_names") = _eigenstrain_names;
1203 
1204  _problem->addMaterial(ad_prepend + type, name() + "_strain", params);
1205 }
1206 
1207 std::string
1209 {
1210  if (_lagrangian_kernels)
1211  {
1212  std::string type;
1214  {
1215  if (_lk_homogenization)
1216  type = "HomogenizedTotalLagrangianStressDivergence";
1218  type = "TotalLagrangianStressDivergence";
1220  type = "UpdatedLagrangianStressDivergence";
1221  else
1222  mooseError("Unknown formulation type");
1223  }
1224  else if (_coord_system == Moose::COORD_RZ)
1225  {
1226  if (_lk_homogenization)
1227  mooseError("The Lagrangian mechanics kernels do not yet support homogenization in "
1228  "coordinate systems other than Cartesian.");
1230  type = "TotalLagrangianStressDivergenceAxisymmetricCylindrical";
1232  mooseError("The Lagrangian mechanics kernels do not yet support the updated Lagrangian "
1233  "formulation in RZ coordinates.");
1234  }
1236  {
1237  if (_lk_homogenization)
1238  mooseError("The Lagrangian mechanics kernels do not yet support homogenization in "
1239  "coordinate systems other than Cartesian.");
1241  type = "TotalLagrangianStressDivergenceCentrosymmetricSpherical";
1243  mooseError("The Lagrangian mechanics kernels do not yet support the updated Lagrangian "
1244  "formulation in RZ coordinates.");
1245  }
1246  else
1247  mooseError("Unsupported coordinate system");
1248  return type;
1249  }
1250  else
1251  {
1252  std::map<Moose::CoordinateSystemType, std::string> type_map = {
1253  {Moose::COORD_XYZ, "StressDivergenceTensors"},
1254  {Moose::COORD_RZ, "StressDivergenceRZTensors"},
1255  {Moose::COORD_RSPHERICAL, "StressDivergenceRSphericalTensors"}};
1256 
1257  // choose kernel type based on coordinate system
1258  auto type_it = type_map.find(_coord_system);
1259  if (type_it != type_map.end())
1260  return type_it->second;
1261  else
1262  mooseError("Unsupported coordinate system");
1263  }
1264 }
1265 
1268 {
1270  params.applyParameters(
1271  parameters(),
1272  {"displacements", "use_displaced_mesh", "save_in", "diag_save_in", "out_of_plane_strain"});
1273 
1274  params.set<std::vector<VariableName>>("displacements") = _coupled_displacements;
1275 
1276  if (_lagrangian_kernels)
1277  {
1278  params.set<bool>("use_displaced_mesh") =
1280  // large_kinematics is derived from the strain calculator's LARGE_KINEMATICS guarantee.
1281  params.set<bool>("stabilize_strain") = _lk_locking;
1282  params.set<MooseEnum>("F_bar_mode") = getParam<MooseEnum>("volumetric_locking_correction_mode");
1283  if (_lk_homogenization)
1284  params.set<bool>("off_diagonal_jacobian") = _lk_h_off_jac;
1285  // Match the strain calc's F-bar mode on the kernel -- the TL kernel's OLD-compat B-bar
1286  // residual is gated on `F_bar_mode = incremental && stabilize_strain`. Setting it on
1287  // both keeps the kernel and the strain material on the same F-bar formulation. Only
1288  // applicable to large kinematics (the strain calc rejects `incremental` for small).
1290  params.set<MooseEnum>("F_bar_mode") = "incremental";
1291  }
1292  else
1293  params.set<bool>("use_displaced_mesh") = _use_displaced_mesh;
1294 
1295  return params;
1296 }
const bool _lk_large_kinematics
Simplified flag for small/large deformations, Lagrangian kernel system.
void mooseInfo(Args &&... args) const
std::set< SubdomainID > _subdomain_id_union
set generated from the combined block restrictions of all SolidMechanics/Master action blocks ...
enum QuasiStaticSolidMechanicsPhysics::StrainAndIncrement _strain_and_increment
std::vector< AuxVariableName > _save_in
residual debugging
virtual InputParameters getKernelParameters(std::string type)
const std::string & _name
bool setupOutput(std::string out, T table, T2 setup)
Helper function to decode generate_outputs options using a "table" of scalar output quantities and a ...
ActionWarehouse & _awh
const bool _compatibility_mode
OLD-compat shim: auto-configures the Lagrangian kernel system to reproduce StressDivergenceTensors + ...
void paramError(const std::string &param, Args... args) const
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
std::vector< AuxVariableName > _diag_save_in
static const std::map< std::string, std::pair< std::string, std::vector< std::string > > > _rank_two_invariant_table
char ** blocks
std::set< SubdomainID > _subdomain_ids
set generated from the passed in vector of subdomain names
InputParameters getValidParams(const std::string &name)
void setAdditionalValue(const std::string &names)
Factory & _factory
unsigned int _ndisp
Number of displacement variables.
static const std::string component
Definition: NS.h:157
const InputParameters & parameters() const
ActionFactory & _action_factory
LKFormulation
New kernel system kinematics types.
static const std::map< std::string, std::pair< std::string, std::vector< std::string > > > _rank_two_cylindrical_component_table
T & set(const std::string &name, bool quiet_mode=false)
InputParameters getValidParams(const std::string &name) const
const bool _auto_eigenstrain
automatically gather names of eigenstrain tensors provided by simulation objects
registerMooseAction("SolidMechanicsApp", QuasiStaticSolidMechanicsPhysics, "meta_action")
unsigned int size() const
void applyParameters(const InputParameters &common, const std::vector< std::string > &exclude={}, const bool allow_private=false)
void mooseDocumentedError(const std::string &repo_name, const unsigned int issue_num, Args &&... args) const
void addActionBlock(std::shared_ptr< Action > blk)
Store common tensor mechanics parameters.
COORD_RSPHERICAL
const ExecFlagType EXEC_TIMESTEP_END
std::vector< VariableName > _displacements
displacement variables
std::vector< std::string > _generate_output
output materials to generate scalar stress/strain tensor quantities
static const std::vector< char > _component_table
table data for output generation
std::shared_ptr< Action > create(const std::string &action, const std::string &action_name, InputParameters &parameters)
InputParameters emptyInputParameters()
enum QuasiStaticSolidMechanicsPhysics::PlanarFormulation _planar_formulation
QuasiStaticSolidMechanicsPhysics(const InputParameters &params)
const SubdomainID INVALID_BLOCK_ID
std::vector< SubdomainName > _subdomain_names
if this vector is not empty the variables, kernels and materials are restricted to these subdomains ...
bool _use_displaced_mesh
use displaced mesh (true unless _strain is SMALL)
const std::string & name() const
enum QuasiStaticSolidMechanicsPhysics::Strain _strain
std::vector< VariableName > _coupled_displacements
Coupled displacement variables.
bool _cylindrical_axis_point1_valid
booleans used to determine if cylindrical axis points are passed
const std::string & type() const
const std::string & _current_task
static std::string variableType(const libMesh::FEType &fe_type, const bool is_fv=false, const bool is_array=false)
std::string stringify(const T &t)
static const std::map< std::string, std::pair< std::string, std::vector< std::string > > > _rank_two_directional_component_table
static std::map< std::string, std::string > _rank_two_cartesian_component_table
std::vector< MaterialPropertyName > _eigenstrain_names
bool isParamSetByUser(const std::string &name) const
std::shared_ptr< MooseMesh > & _mesh
static libMesh::FEType feType(const InputParameters &params)
unsigned int get(unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
ConstraintType
Constraint type: stress/PK stress or strain/deformation gradient.
const Real p
OStreamProxy out
const bool _lagrangian_kernels
New or old kernel system. True if new_system = true OR compatibility_mode = true. ...
const bool _lk_locking
Simplified volumetric locking correction flag for new kernels.
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
std::shared_ptr< FEProblemBase > & _problem
Point _spherical_center_point
center point for spherical stress/strain quantities
const MultiMooseEnum constraintType("strain stress none")
bool isParamValid(const std::string &name) const
bool _spherical_center_point_valid
booleans used to determine if spherical center point is passed
const std::string _base_name
base name for the current master action block
std::vector< const T *> getActions()
auto index_range(const T &sizable)
PlanarFormulation
use an out of plane stress/strain formulation
static const std::map< std::string, std::pair< std::string, std::vector< std::string > > > _rank_two_spherical_component_table
Point _cylindrical_axis_point1
points used to determine axis of rotation for cylindrical stress/strain quantities ...
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
const bool _lk_h_off_jac
Whether to use the off diagonal scalar jacobian for the homogenization system.
std::string remapCompatOutputProp(const std::string &prop_name) const
Apply compatibility_mode remapping to a property name pulled from the _rank_two_* output tables: in c...
bool _lk_homogenization
Flag indicating if the homogenization system is present for new kernels.