26 #include <unordered_map> 29 #include "libmesh/petsc_nonlinear_solver.h" 30 #include "libmesh/string_to_enum.h" 33 #if NANOFLANN_VERSION < 0x150 38 template <
typename T,
typename U>
77 params.
addParam<std::vector<BoundaryName>>(
78 "primary",
"The list of boundary IDs referring to primary sidesets");
79 params.
addParam<std::vector<BoundaryName>>(
80 "secondary",
"The list of boundary IDs referring to secondary sidesets");
81 params.
addParam<std::vector<BoundaryName>>(
82 "automatic_pairing_boundaries",
84 "List of boundary IDs for sidesets that are automatically paired with any other boundary in " 85 "this list having a centroid-to-centroid distance less than the value specified in the " 86 "'automatic_pairing_distance' parameter. ");
88 "automatic_pairing_distance",
89 "automatic_pairing_distance>=0",
90 "The maximum distance the centroids of the boundaries provided in the " 91 "'automatic_pairing_boundaries' parameter can be to generate a contact pair automatically. " 92 "Due to numerical error in the determination of the centroids, it is encouraged that " 93 "the user adds a tolerance to this distance (e.g. extra 10%) to make sure no suitable " 94 "contact pair is missed. If the 'automatic_pairing_method = NODE' option is chosen instead, " 95 "this distance is recommended to be set to at least twice the minimum distance between " 96 "nodes of boundaries to be paired.");
99 "The mesh generator for mortar method",
100 "This parameter is not used anymore and can simply be removed");
101 params.
addParam<VariableName>(
"secondary_gap_offset",
102 "Offset to gap distance from secondary side");
103 params.
addParam<VariableName>(
"mapped_primary_gap_offset",
104 "Offset to gap distance mapped from primary side");
105 params.
addParam<std::vector<VariableName>>(
108 "The displacements appropriate for the simulation geometry and coordinate system");
112 "The penalty to apply. This can vary depending on the stiffness of your materials");
116 "The penalty factor to apply in mortar penalty frictional constraints. It is applied to the " 117 "tangential accumulated slip to build the frictional force");
119 "penalty_multiplier",
121 "penalty_multiplier > 0",
122 "The growth factor for the penalty applied at the end of each augmented " 123 "Lagrange update iteration (a value larger than one, e.g., 10, tends to speed up " 126 "penalty_multiplier_friction",
128 "penalty_multiplier_friction > 0",
129 "The penalty growth factor between augmented Lagrange " 130 "iterations for penalizing relative slip distance if the node is under stick conditions.(a " 131 "value larger than one, e.g., 10, tends to speed up convergence.)");
132 params.
addParam<
Real>(
"friction_coefficient", 0,
"The friction coefficient");
135 "Tension release threshold. A node in contact " 136 "will not be released if its tensile load is below " 137 "this value. No tension release if negative.");
140 "Tangential distance to extend edges of contact surfaces");
143 "Normal distance from surface within which nodes are captured. This " 144 "parameter is used for node-face and mortar formulations.");
146 "normal_smoothing_distance",
147 "Distance from edge in parametric coordinates over which to smooth contact normal");
149 params.
addParam<
bool>(
"normalize_penalty",
151 "Whether to normalize the penalty parameter with the nodal area.");
153 "primary_secondary_jacobian",
155 "Whether to include Jacobian entries coupling primary and secondary nodes.");
157 "The tolerance of the penetration for augmented Lagrangian method.");
159 "The tolerance of the incremental slip for augmented Lagrangian method.");
161 "max_penalty_multiplier",
163 "max_penalty_multiplier >= 1.0",
164 "Maximum multiplier applied to penalty factors when adaptivity is used in an augmented " 165 "Lagrange setting. The penalty factor supplied by the user is used as a reference to " 166 "determine its maximum. If this multiplier is too large, the condition number of the system " 167 "to be solved may be negatively impacted.");
168 MooseEnum adaptivity_penalty_normal(
"SIMPLE BUSSETTA",
"SIMPLE");
169 adaptivity_penalty_normal.addDocumentation(
170 "SIMPLE",
"Keep multiplying by the penalty multiplier between AL iterations");
171 adaptivity_penalty_normal.addDocumentation(
173 "Modify the penalty using an algorithm from Bussetta et al, 2012, Comput Mech 49:259-275 " 174 "between AL iterations.");
176 "adaptivity_penalty_normal",
177 adaptivity_penalty_normal,
178 "The augmented Lagrange update strategy used on the normal penalty coefficient.");
179 MooseEnum adaptivity_penalty_friction(
"SIMPLE FRICTION_LIMIT",
"FRICTION_LIMIT");
180 adaptivity_penalty_friction.addDocumentation(
181 "SIMPLE",
"Keep multiplying by the frictional penalty multiplier between AL iterations");
182 adaptivity_penalty_friction.addDocumentation(
184 "This strategy will be guided by the Coulomb limit and be less reliant on the initial " 185 "penalty factor provided by the user.");
187 "adaptivity_penalty_friction",
188 adaptivity_penalty_friction,
189 "The augmented Lagrange update strategy used on the frictional penalty coefficient.");
191 "The tolerance of the frictional force for augmented Lagrangian method.");
195 "Parameter for balancing the size of the gap and contact pressure for a mortar formulation. " 196 "This purely numerical " 197 "parameter affects convergence behavior and, in general, should be larger for stiffer " 198 "materials. It is recommended that the user tries out various orders of magnitude for this " 199 "parameter if the default value generates poor contact convergence.");
201 "c_tangential", 1,
"Numerical parameter for nonlinear mortar frictional constraints");
202 params.
addParam<
bool>(
"ping_pong_protection",
204 "Whether to protect against ping-ponging, e.g. the oscillation of the " 205 "secondary node between two " 206 "different primary faces, by tying the secondary node to the " 207 "edge between the involved primary faces");
211 "Scaling factor to apply to the normal LM variable for a mortar formulation");
213 "tangential_lm_scaling",
215 "Scaling factor to apply to the tangential LM variable for a mortar formulation");
219 "Whether to normalize c by weighting function norm for mortar contact. When unnormalized " 220 "the value of c effectively depends on element size since in the constraint we compare nodal " 221 "Lagrange Multiplier values to integrated gap values (LM nodal value is independent of " 222 "element size, where integrated values are dependent on element size).");
223 params.
addClassDescription(
"Sets up all objects needed for mechanical contact enforcement");
226 "Whether to use the dual mortar approach within a mortar formulation. It is defaulted to " 228 "weighted quantity approach, and to false for the legacy approach. To avoid instabilities " 229 "in the solution and obtain the full benefits of a variational enforcement," 230 "use of dual mortar with weighted constraints is strongly recommended. This " 231 "input is only intended for advanced users.");
233 "correct_edge_dropping",
235 "Whether to enable correct edge dropping treatment for mortar constraints. When disabled " 236 "any Lagrange Multiplier degree of freedom on a secondary element without full primary " 237 "contributions will be set (strongly) to 0.");
239 "generate_mortar_mesh",
241 "Whether to generate the mortar mesh from the action. Typically this will be the case, but " 242 "one may also want to reuse an existing lower-dimensional mesh prior to a restart.");
245 "The proximity method used for automatic pairing of boundaries.");
249 "Whether to use constraints that account for the persistency condition, giving rise to " 250 "smoother normal contact pressure evolution. This flag should only be set to yes for dynamic " 251 "simulations using the Newmark-beta numerical integrator");
255 "Newmark-beta beta parameter for its inclusion in the weighted gap update formula");
259 "Newmark-beta gamma parameter for its inclusion in the weighted gap update formula");
261 "The name of the mortar auxiliary variable that is used to modify the " 262 "weighted gap definition");
263 params.
addParam<std::vector<TagName>>(
265 "The tag names for extra vectors that residual data should be saved into");
266 params.
addParam<std::vector<TagName>>(
267 "absolute_value_vector_tags",
268 "The tags for the vectors this residual object should fill with the " 269 "absolute value of the residual contribution");
271 "use_petrov_galerkin",
273 "Whether to use the Petrov-Galerkin approach for the mortar-based constraints. If set to " 274 "true, we use the standard basis as the test function and dual basis as " 275 "the shape function for the interpolation of the Lagrange multiplier variable.");
279 "Whether we are going to enable mortar segment mesh debug information. An exodus" 280 "file will be generated if the user sets this flag to true");
286 _boundary_pairs(getParam<BoundaryName, BoundaryName>(
"primary",
"secondary")),
289 _generate_mortar_mesh(getParam<bool>(
"generate_mortar_mesh")),
290 _mortar_dynamics(getParam<bool>(
"mortar_dynamics"))
293 if (
getParam<std::vector<BoundaryName>>(
"automatic_pairing_boundaries").size() > 1)
295 getParam<std::vector<BoundaryName>>(
"automatic_pairing_boundaries");
299 "For automatic selection of contact pairs (for particular geometries) in contact " 300 "action, 'automatic_pairing_distance' needs to be provided.");
304 "For automatic selection of contact pairs (for particular geometries) in contact " 305 "action, 'automatic_pairing_method' needs to be provided.");
309 "If a boundary list is provided, primary and secondary surfaces will be identified " 310 "automatically. Therefore, one cannot provide an automatic pairing boundary list " 311 "and primary/secondary lists.");
314 "'primary' and 'secondary' surfaces or a list of boundaries for automatic pair " 315 "generation need to be provided.");
320 paramError(
"formulation",
"When using mortar, a vector of contact pairs cannot be used");
324 "The 'tangential_penalty' formulation can only be used with the 'coulomb' model");
335 paramError(
"model",
"The 'mortar_penalty' formulation does not support glued contact");
337 if (getParam<bool>(
"mortar_dynamics"))
339 "The 'mortar_penalty' formulation does not support implicit dynamic simulations");
341 if (getParam<bool>(
"use_petrov_galerkin"))
343 "The 'mortar_penalty' formulation does not support usage of the Petrov-Galerkin " 344 "flag. The default (use_dual = true) behavior is such that contact tractions are " 345 "interpolated with dual bases whereas mortar or weighted contact quantities are " 346 "interpolated with Lagrange shape functions.");
352 paramError(
"model",
"The 'mortar' formulation does not support glued contact (yet)");
360 if (!getParam<bool>(
"mortar_dynamics"))
363 paramError(
"newmark_beta",
"newmark_beta can only be used with the mortar_dynamics option");
367 "newmark_gamma can only be used with the mortar_dynamics option");
372 "The 'penalty' parameter is not used for the 'mortar' formulation which instead " 373 "uses Lagrange multipliers");
379 "correct_edge_dropping",
380 "The 'correct_edge_dropping' option can only be used with the 'mortar' formulation " 385 "The 'use_dual' option can only be used with the 'mortar' formulation");
388 "The 'c_normal' option can only be used with the 'mortar' formulation");
391 "The 'c_tangential' option can only be used with the 'mortar' formulation");
394 "The 'mortar_dynamics' constraint option can only be used with the 'mortar' " 395 "formulation and in dynamic simulations using Newmark-beta");
402 "The 'secondary_gap_offset' option can only be used with the " 403 "'MechanicalContactConstraint'");
406 "The 'mapped_primary_gap_offset' option can only be used with the " 407 "'MechanicalContactConstraint'");
409 else if (getParam<bool>(
"ping_pong_protection"))
411 "The 'ping_pong_protection' option can only be used with the 'ranfs' formulation");
423 "Number of contact pairs in the contact action is zero. Please revise your input file.");
426 std::vector<std::pair<BoundaryName, BoundaryName>> lean_boundary_pairs;
431 auto it = std::find_if(lean_boundary_pairs.begin(),
432 lean_boundary_pairs.end(),
433 [&, primary_copy = primary, secondary_copy = secondary](
434 const std::pair<BoundaryName, BoundaryName> & lean_pair)
436 const bool match_one = lean_pair.second == secondary_copy &&
437 lean_pair.first == primary_copy;
438 const bool match_two = lean_pair.second == primary_copy &&
439 lean_pair.first == secondary_copy;
440 const bool exist = match_one || match_two;
444 if (it == lean_boundary_pairs.end())
445 lean_boundary_pairs.emplace_back(primary, secondary);
451 " has been removed from the contact interaction list due to " 452 "duplicates in the input file.");
464 if (!
_problem->getDisplacedProblem())
466 "Contact requires updated coordinates. Use the 'displacements = ...' parameter in the " 473 if (!
_problem->isSNESMFReuseBaseSetbyUser())
474 _problem->setSNESMFReuseBase(
false,
false);
485 if (!
_problem->getDisplacedProblem())
486 mooseError(
"Contact requires updated coordinates. Use the 'displacements = ...' line in the " 492 const auto & [primary_name, secondary_name] = contact_pair;
498 {
"secondary_gap_offset",
"mapped_primary_gap_offset",
"order"});
500 std::vector<VariableName> displacements =
501 getParam<std::vector<VariableName>>(
"displacements");
502 const auto order =
_problem->systemBaseNonlinear(0)
504 .variable_type(displacements[0])
507 params.
set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{order});
509 params.
set<std::vector<BoundaryName>>(
"boundary") = {secondary_name};
510 params.
set<BoundaryName>(
"paired_boundary") = primary_name;
511 params.
set<AuxVariableName>(
"variable") =
"penetration";
513 params.
set<std::vector<VariableName>>(
"secondary_gap_offset") = {
514 getParam<VariableName>(
"secondary_gap_offset")};
516 params.
set<std::vector<VariableName>>(
"mapped_primary_gap_offset") = {
517 getParam<VariableName>(
"mapped_primary_gap_offset")};
518 params.
set<
bool>(
"use_displaced_mesh") =
true;
525 const auto type =
"MortarUserObjectAux";
527 params.
set<std::vector<BoundaryName>>(
"boundary") = {secondary_name};
528 params.
set<AuxVariableName>(
"variable") =
"gap";
529 params.
set<
bool>(
"use_displaced_mesh") =
true;
531 params.
set<
MooseEnum>(
"contact_quantity") =
"normal_gap";
532 const auto & [primary_id, secondary_id, uo_name] =
534 params.
set<UserObjectName>(
"user_object") = uo_name;
535 std::string
name =
_name +
"_contact_gap_" + std::to_string(primary_id) +
"_" +
536 std::to_string(secondary_id);
544 const unsigned int ndisp = getParam<std::vector<VariableName>>(
"displacements").size();
558 const std::string tangential_lagrange_multiplier_name = action_name +
"_tangential_lm";
559 const std::string tangential_lagrange_multiplier_3d_name =
560 action_name +
"_tangential_3d_lm";
562 params.
set<std::vector<VariableName>>(
"tangent_one") = {
563 tangential_lagrange_multiplier_name};
564 params.
set<std::vector<VariableName>>(
"tangent_two") = {
565 tangential_lagrange_multiplier_3d_name};
567 std::vector<std::string> disp_components({
"x",
"y",
"z"});
568 unsigned component_index = 0;
571 for (
const auto & disp_component : disp_components)
573 params.
set<AuxVariableName>(
"variable") =
_name +
"_tangent_" + disp_component;
574 params.
set<
unsigned int>(
"component") = component_index;
576 std::string
name =
_name +
"_mortar_frictional_pressure_" + disp_component +
"_" +
579 _problem->addAuxKernel(
"MortarFrictionalPressureVectorAux",
name, params);
588 std::vector<VariableName> displacements = getParam<std::vector<VariableName>>(
"displacements");
589 const auto order =
_problem->systemBaseNonlinear(0)
591 .variable_type(displacements[0])
593 std::unique_ptr<InputParameters> current_params;
594 const auto create_aux_var_params = [
this, order, ¤t_params]() ->
InputParameters &
597 current_params->set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{order});
598 current_params->set<
MooseEnum>(
"family") =
"LAGRANGE";
599 return *current_params;
606 _problem->addAuxVariable(
"MooseVariable",
"penetration", create_aux_var_params());
608 _problem->addAuxVariable(
"MooseVariable",
"nodal_area", create_aux_var_params());
611 _problem->addAuxVariable(
"MooseVariable",
"gap", create_aux_var_params());
614 _problem->addAuxVariable(
"MooseVariable",
"contact_pressure", create_aux_var_params());
616 const unsigned int ndisp = getParam<std::vector<VariableName>>(
"displacements").size();
622 std::vector<std::string> disp_components({
"x",
"y",
"z"});
624 for (
const auto & disp_component : disp_components)
627 var_params.
set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{order});
628 var_params.set<
MooseEnum>(
"family") =
"LAGRANGE";
631 "MooseVariable",
_name +
"_tangent_" + disp_component, var_params);
646 std::vector<BoundaryName> secondary_boundary_vector;
647 for (
const auto *
const action : actions)
648 for (
const auto j :
index_range(action->_boundary_pairs))
649 secondary_boundary_vector.push_back(action->_boundary_pairs[
j].second);
651 var_params.set<std::vector<BoundaryName>>(
"boundary") = secondary_boundary_vector;
652 var_params.set<std::vector<VariableName>>(
"variable") = {
"nodal_area"};
654 mooseAssert(
_problem,
"Problem pointer is NULL");
656 var_params.set<
bool>(
"use_displaced_mesh") =
true;
658 _problem->addUserObject(
"NodalArea",
679 std::vector<BoundaryName> boundary_vector;
680 std::vector<BoundaryName> pair_boundary_vector;
682 for (
const auto *
const action : actions)
683 for (
const auto j :
index_range(action->_boundary_pairs))
685 boundary_vector.push_back(action->_boundary_pairs[
j].second);
686 pair_boundary_vector.push_back(action->_boundary_pairs[
j].first);
692 std::vector<VariableName> displacements =
693 getParam<std::vector<VariableName>>(
"displacements");
694 const auto order =
_problem->systemBaseNonlinear(0)
696 .variable_type(displacements[0])
699 params.
set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{order});
700 params.
set<std::vector<BoundaryName>>(
"boundary") = boundary_vector;
701 params.
set<std::vector<BoundaryName>>(
"paired_boundary") = pair_boundary_vector;
702 params.
set<AuxVariableName>(
"variable") =
"contact_pressure";
704 params.
set<std::vector<VariableName>>(
"nodal_area") = {
"nodal_area"};
705 params.
set<
bool>(
"use_displaced_mesh") =
true;
707 std::string
name =
_name +
"_contact_pressure";
710 _problem->addAuxKernel(
"ContactPressureAux",
name, params);
716 const auto & [_, secondary_name] = contact_pair;
717 const auto type =
"MortarUserObjectAux";
719 params.
set<std::vector<BoundaryName>>(
"boundary") = {secondary_name};
720 params.
set<AuxVariableName>(
"variable") =
"contact_pressure";
721 params.
set<
bool>(
"use_displaced_mesh") =
true;
723 params.
set<
MooseEnum>(
"contact_quantity") =
"normal_pressure";
724 const auto & [primary_id, secondary_id, uo_name] =
726 params.
set<UserObjectName>(
"user_object") = uo_name;
727 const std::string
name =
_name +
"_contact_pressure" + std::to_string(primary_id) +
"_" +
728 std::to_string(secondary_id);
741 params.set<
bool>(
"use_displaced_mesh") =
true;
743 const std::string primary_subdomain_name = action_name +
"_primary_subdomain";
744 const std::string secondary_subdomain_name = action_name +
"_secondary_subdomain";
745 params.set<BoundaryName>(
"primary_boundary") =
_boundary_pairs[0].first;
746 params.set<BoundaryName>(
"secondary_boundary") =
_boundary_pairs[0].second;
747 params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
748 params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
749 params.set<
bool>(
"use_petrov_galerkin") = getParam<bool>(
"use_petrov_galerkin");
759 std::vector<VariableName> displacements = getParam<std::vector<VariableName>>(
"displacements");
760 const unsigned int ndisp = displacements.size();
763 const std::string primary_subdomain_name = action_name +
"_primary_subdomain";
764 const std::string secondary_subdomain_name = action_name +
"_secondary_subdomain";
765 const std::string normal_lagrange_multiplier_name = action_name +
"_normal_lm";
766 const std::string tangential_lagrange_multiplier_name = action_name +
"_tangential_lm";
767 const std::string tangential_lagrange_multiplier_3d_name = action_name +
"_tangential_3d_lm";
768 const std::string auxiliary_lagrange_multiplier_name = action_name +
"_aux_lm";
778 const MeshGeneratorName primary_name = primary_subdomain_name +
"_generator";
779 const MeshGeneratorName secondary_name = secondary_subdomain_name +
"_generator";
784 primary_params.
set<SubdomainName>(
"new_block_name") = primary_subdomain_name;
785 secondary_params.set<SubdomainName>(
"new_block_name") = secondary_subdomain_name;
787 primary_params.set<std::vector<BoundaryName>>(
"sidesets") = {
_boundary_pairs[0].first};
788 secondary_params.set<std::vector<BoundaryName>>(
"sidesets") = {
_boundary_pairs[0].second};
796 const auto addLagrangeMultiplier =
797 [
this, &secondary_subdomain_name, &displacements](
const std::string & variable_name,
798 const Real scaling_factor,
799 const bool add_aux_lm,
800 const bool penalty_traction)
807 if (!add_aux_lm || penalty_traction)
810 mooseAssert(
_problem->systemBaseNonlinear(0).hasVariable(displacements[0]),
811 "Displacement variable is missing");
812 const auto primal_type =
813 _problem->systemBaseNonlinear(0).system().variable_type(displacements[0]);
815 const int lm_order = primal_type.order.get_order();
819 params.
set<
MooseEnum>(
"family") = Utility::enum_to_string<FEFamily>(primal_type.family);
820 params.
set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{lm_order});
823 mooseError(
"Invalid bases for mortar contact.");
825 params.
set<std::vector<SubdomainName>>(
"block") = {secondary_subdomain_name};
826 if (!(add_aux_lm || penalty_traction))
827 params.
set<std::vector<Real>>(
"scaling") = {scaling_factor};
831 if (add_aux_lm || penalty_traction)
832 _problem->addAuxVariable(var_type, variable_name, params);
834 _problem->addVariable(var_type, variable_name, params);
839 addLagrangeMultiplier(
840 normal_lagrange_multiplier_name, getParam<Real>(
"normal_lm_scaling"),
false,
false);
844 addLagrangeMultiplier(tangential_lagrange_multiplier_name,
845 getParam<Real>(
"tangential_lm_scaling"),
849 addLagrangeMultiplier(tangential_lagrange_multiplier_3d_name,
850 getParam<Real>(
"tangential_lm_scaling"),
855 if (getParam<bool>(
"use_petrov_galerkin"))
856 addLagrangeMultiplier(auxiliary_lagrange_multiplier_name, 1.0,
true,
false);
862 addLagrangeMultiplier(auxiliary_lagrange_multiplier_name, 1.0,
false,
true);
867 const auto register_mortar_uo_name = [
this](
const auto & bnd_pair,
const auto & uo_prefix)
869 const auto & [primary_name, secondary_name] = bnd_pair;
870 const auto primary_id =
_mesh->getBoundaryID(primary_name);
871 const auto secondary_id =
_mesh->getBoundaryID(secondary_name);
872 const auto uo_name = uo_prefix +
name();
879 !dynamic_cast<AugmentedLagrangianContactProblemInterface *>(
_problem.get()))
881 const std::vector<std::string> params = {
"penalty_multiplier",
882 "penalty_multiplier_friction",
883 "al_penetration_tolerance",
884 "al_incremental_slip_tolerance",
885 "al_frictional_force_tolerance"};
886 for (
const auto & param : params)
889 "Augmented Lagrange parameter was specified, but the selected problem type " 890 "does not support Augmented Lagrange iterations.");
898 uo_params.set<BoundaryName>(
"secondary_boundary") =
_boundary_pairs[0].second;
899 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
900 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
901 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
902 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
904 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
905 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
906 uo_params.set<std::vector<VariableName>>(
"lm_variable") = {normal_lagrange_multiplier_name};
907 uo_params.applySpecificParameters(
908 parameters(), {
"correct_edge_dropping",
"use_petrov_galerkin",
"debug_mesh"});
909 if (getParam<bool>(
"use_petrov_galerkin"))
910 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
912 _problem->addUserObject(
"LMWeightedGapUserObject",
920 uo_params.set<BoundaryName>(
"secondary_boundary") =
_boundary_pairs[0].second;
921 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
922 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
923 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
924 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
926 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
928 uo_params.set<VariableName>(
"secondary_variable") = displacements[0];
929 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
930 uo_params.set<std::vector<VariableName>>(
"lm_variable_normal") = {
931 normal_lagrange_multiplier_name};
932 uo_params.set<std::vector<VariableName>>(
"lm_variable_tangential_one") = {
933 tangential_lagrange_multiplier_name};
935 uo_params.set<std::vector<VariableName>>(
"lm_variable_tangential_two") = {
936 tangential_lagrange_multiplier_3d_name};
937 uo_params.applySpecificParameters(
938 parameters(), {
"correct_edge_dropping",
"use_petrov_galerkin",
"debug_mesh"});
939 if (getParam<bool>(
"use_petrov_galerkin"))
940 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
942 const auto uo_name =
_problem->addUserObject(
943 "LMWeightedVelocitiesUserObject",
944 register_mortar_uo_name(
_boundary_pairs[0],
"lm_weightedvelocities_object_"),
953 uo_params.set<BoundaryName>(
"secondary_boundary") =
_boundary_pairs[0].second;
954 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
955 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
956 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
957 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
960 uo_params.applySpecificParameters(
parameters(),
961 {
"correct_edge_dropping",
964 "max_penalty_multiplier",
965 "adaptivity_penalty_normal"});
968 uo_params.set<
Real>(
"penetration_tolerance") = getParam<Real>(
"al_penetration_tolerance");
970 uo_params.set<
Real>(
"penalty_multiplier") = getParam<Real>(
"penalty_multiplier");
973 uo_params.set<
bool>(
"use_physical_gap") =
true;
976 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
979 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
980 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
983 "PenaltyWeightedGapUserObject",
984 register_mortar_uo_name(
_boundary_pairs[0],
"penalty_weightedgap_object_"),
992 uo_params.set<BoundaryName>(
"secondary_boundary") =
_boundary_pairs[0].second;
993 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
994 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
995 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
996 uo_params.set<
bool>(
"correct_edge_dropping") = getParam<bool>(
"correct_edge_dropping");
997 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
999 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1001 uo_params.set<VariableName>(
"secondary_variable") = displacements[0];
1002 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
1003 uo_params.set<
Real>(
"friction_coefficient") = getParam<Real>(
"friction_coefficient");
1004 uo_params.set<
Real>(
"penalty") = getParam<Real>(
"penalty");
1005 uo_params.set<
Real>(
"penalty_friction") = getParam<Real>(
"penalty_friction");
1008 uo_params.set<
Real>(
"max_penalty_multiplier") = getParam<Real>(
"max_penalty_multiplier");
1009 uo_params.set<
MooseEnum>(
"adaptivity_penalty_normal") =
1010 getParam<MooseEnum>(
"adaptivity_penalty_normal");
1011 uo_params.set<
MooseEnum>(
"adaptivity_penalty_friction") =
1012 getParam<MooseEnum>(
"adaptivity_penalty_friction");
1014 uo_params.set<
Real>(
"penetration_tolerance") = getParam<Real>(
"al_penetration_tolerance");
1016 uo_params.set<
Real>(
"penalty_multiplier") = getParam<Real>(
"penalty_multiplier");
1018 uo_params.set<
Real>(
"penalty_multiplier_friction") =
1019 getParam<Real>(
"penalty_multiplier_friction");
1022 uo_params.set<
Real>(
"slip_tolerance") = getParam<Real>(
"al_incremental_slip_tolerance");
1025 uo_params.set<
bool>(
"use_physical_gap") =
true;
1028 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
1030 uo_params.applySpecificParameters(
parameters(),
1031 {
"friction_coefficient",
"penalty",
"penalty_friction"});
1034 "PenaltyFrictionUserObject",
1035 register_mortar_uo_name(
_boundary_pairs[0],
"penalty_friction_object_"),
1046 std::string mortar_constraint_name;
1049 mortar_constraint_name =
"ComputeWeightedGapLMMechanicalContact";
1051 mortar_constraint_name =
"ComputeDynamicWeightedGapLMMechanicalContact";
1056 parameters(), {
"newmark_beta",
"newmark_gamma",
"capture_tolerance",
"wear_depth"});
1059 params.
set<UserObjectName>(
"weighted_gap_uo") =
"lm_weightedgap_object_" +
name();
1063 params.
set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1064 params.
set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1065 params.
set<NonlinearVariableName>(
"variable") = normal_lagrange_multiplier_name;
1066 params.
set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1067 params.
set<
Real>(
"c") = getParam<Real>(
"c_normal");
1070 params.
set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1072 params.
set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1074 params.
set<
bool>(
"use_displaced_mesh") =
true;
1077 {
"correct_edge_dropping",
1079 "extra_vector_tags",
1080 "absolute_value_vector_tags",
1084 mortar_constraint_name, action_name +
"_normal_lm_weighted_gap", params);
1090 std::string mortar_constraint_name;
1093 mortar_constraint_name =
"ComputeFrictionalForceLMMechanicalContact";
1095 mortar_constraint_name =
"ComputeDynamicFrictionalForceLMMechanicalContact";
1100 parameters(), {
"newmark_beta",
"newmark_gamma",
"capture_tolerance",
"wear_depth"});
1103 params.
set<UserObjectName>(
"weighted_gap_uo") =
"lm_weightedvelocities_object_" +
name();
1104 params.
set<UserObjectName>(
"weighted_velocities_uo") =
1105 "lm_weightedvelocities_object_" +
name();
1108 params.
set<
bool>(
"correct_edge_dropping") = getParam<bool>(
"correct_edge_dropping");
1111 params.
set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1112 params.
set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1113 params.
set<
bool>(
"use_displaced_mesh") =
true;
1114 params.
set<
Real>(
"c_t") = getParam<Real>(
"c_tangential");
1115 params.
set<
Real>(
"c") = getParam<Real>(
"c_normal");
1116 params.
set<
bool>(
"normalize_c") = getParam<bool>(
"normalize_c");
1117 params.
set<
bool>(
"compute_primal_residuals") =
false;
1119 params.
set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1122 params.
set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1124 params.
set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1126 params.
set<NonlinearVariableName>(
"variable") = normal_lagrange_multiplier_name;
1127 params.
set<std::vector<VariableName>>(
"friction_lm") = {tangential_lagrange_multiplier_name};
1130 params.
set<std::vector<VariableName>>(
"friction_lm_dir") = {
1131 tangential_lagrange_multiplier_3d_name};
1133 params.
set<
Real>(
"mu") = getParam<Real>(
"friction_coefficient");
1135 parameters(), {
"extra_vector_tags",
"absolute_value_vector_tags",
"debug_mesh"});
1137 _problem->addConstraint(mortar_constraint_name, action_name +
"_tangential_lm", params);
1141 const auto addMechanicalContactConstraints =
1142 [
this, &primary_subdomain_name, &secondary_subdomain_name, &displacements](
1143 const std::string & variable_name,
1144 const std::string & constraint_prefix,
1145 const std::string & constraint_type,
1146 const bool is_additional_frictional_constraint,
1147 const bool is_normal_constraint)
1151 params.
set<
bool>(
"correct_edge_dropping") = getParam<bool>(
"correct_edge_dropping");
1154 params.
set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1155 params.
set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1158 params.
set<NonlinearVariableName>(
"variable") = variable_name;
1160 params.
set<
bool>(
"use_displaced_mesh") =
true;
1161 params.
set<
bool>(
"compute_lm_residuals") =
false;
1165 if (is_additional_frictional_constraint)
1168 parameters(), {
"extra_vector_tags",
"absolute_value_vector_tags",
"debug_mesh"});
1170 for (
unsigned int i = 0; i < displacements.size(); ++i)
1174 params.
set<VariableName>(
"secondary_variable") = displacements[i];
1179 params.
set<UserObjectName>(
"weighted_gap_uo") =
"lm_weightedgap_object_" +
name();
1182 params.
set<UserObjectName>(
"weighted_gap_uo") =
"lm_weightedvelocities_object_" +
name();
1184 params.
set<UserObjectName>(
"weighted_velocities_uo") =
1185 "lm_weightedvelocities_object_" +
name();
1188 params.
set<UserObjectName>(
"weighted_gap_uo") =
"penalty_weightedgap_object_" +
name();
1191 params.
set<UserObjectName>(
"weighted_gap_uo") =
"penalty_friction_object_" +
name();
1193 params.
set<UserObjectName>(
"weighted_velocities_uo") =
1194 "penalty_friction_object_" +
name();
1196 _problem->addConstraint(constraint_type, constraint_name, params);
1202 addMechanicalContactConstraints(normal_lagrange_multiplier_name,
1203 action_name +
"_normal_constraint_",
1204 "NormalMortarMechanicalContact",
1210 addMechanicalContactConstraints(tangential_lagrange_multiplier_name,
1211 action_name +
"_tangential_constraint_",
1212 "TangentialMortarMechanicalContact",
1216 addMechanicalContactConstraints(tangential_lagrange_multiplier_3d_name,
1217 action_name +
"_tangential_constraint_3d_",
1218 "TangentialMortarMechanicalContact",
1230 if (getParam<MooseEnum>(
"automatic_pairing_method").getEnum<
ProximityMethod>() ==
1233 else if (getParam<MooseEnum>(
"automatic_pairing_method").getEnum<ProximityMethod>() ==
1242 std::vector<VariableName> displacements = getParam<std::vector<VariableName>>(
"displacements");
1243 const unsigned int ndisp = displacements.size();
1245 std::string constraint_type;
1248 constraint_type =
"RANFSNormalMechanicalContact";
1250 constraint_type =
"MechanicalContactConstraint";
1256 "secondary_gap_offset",
1257 "mapped_primary_gap_offset",
1261 const auto order =
_problem->systemBaseNonlinear(0)
1263 .variable_type(displacements[0])
1266 params.
set<std::vector<VariableName>>(
"displacements") = displacements;
1267 params.
set<
bool>(
"use_displaced_mesh") =
true;
1268 params.
set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{order});
1274 params.
set<std::vector<VariableName>>(
"nodal_area") = {
"nodal_area"};
1275 params.
set<BoundaryName>(
"boundary") = contact_pair.first;
1277 params.
set<std::vector<VariableName>>(
"secondary_gap_offset") = {
1278 getParam<VariableName>(
"secondary_gap_offset")};
1280 params.
set<std::vector<VariableName>>(
"mapped_primary_gap_offset") = {
1281 getParam<VariableName>(
"mapped_primary_gap_offset")};
1284 for (
unsigned int i = 0; i < ndisp; ++i)
1292 params.
set<
unsigned int>(
"component") = i;
1294 params.
set<BoundaryName>(
"primary") = contact_pair.first;
1295 params.
set<BoundaryName>(
"secondary") = contact_pair.second;
1296 params.
set<NonlinearVariableName>(
"variable") = displacements[i];
1297 params.
set<std::vector<VariableName>>(
"primary_variable") = {displacements[i]};
1299 {
"extra_vector_tags",
"absolute_value_vector_tags"});
1300 _problem->addConstraint(constraint_type,
name, params);
1308 inline const Point &
1311 return *(item.first);
1317 mooseInfo(
"The contact action is reading the list of boundaries and automatically pairs them " 1318 "if the distance between nodes is less than a specified distance.");
1321 mooseError(
"Failed to obtain mesh for automatically generating contact pairs.");
1323 if (!
_mesh->getMesh().is_serial())
1325 "automatic_pairing_boundaries",
1326 "The generation of automatic contact pairs in the contact action requires a serial mesh.");
1329 std::vector<BoundaryID> _automatic_pairing_boundaries_id;
1331 _automatic_pairing_boundaries_id.emplace_back(
_mesh->getBoundaryID(sideset_name));
1334 std::vector<NodeBoundaryIDInfo> node_boundary_id_vector;
1339 for (
const auto & bnode : bnd_nodes)
1341 const BoundaryID boundary_id = bnode->_bnd_id;
1342 const Node * node_ptr = bnode->_node;
1345 auto it = std::find(_automatic_pairing_boundaries_id.begin(),
1346 _automatic_pairing_boundaries_id.end(),
1349 if (it != _automatic_pairing_boundaries_id.end())
1350 node_boundary_id_vector.emplace_back(node_ptr, boundary_id);
1354 std::sort(node_boundary_id_vector.begin(),
1355 node_boundary_id_vector.end(),
1357 {
return first_pair.second < second_pair.second; });
1360 using KDTreeType = nanoflann::KDTreeSingleIndexAdaptor<
1361 nanoflann::L2_Simple_Adaptor<Real, PointListAdaptor<NodeBoundaryIDInfo>,
Real, std::size_t>,
1367 const unsigned int max_leaf_size = 20;
1371 node_boundary_id_vector.end());
1372 auto kd_tree = std::make_unique<KDTreeType>(
1373 LIBMESH_DIM, point_list, nanoflann::KDTreeSingleIndexAdaptorParams(max_leaf_size));
1376 mooseError(
"Internal error. KDTree was not properly initialized in the contact action.");
1378 kd_tree->buildIndex();
1382 std::vector<nanoflann::ResultItem<std::size_t, Real>> ret_matches;
1384 const auto radius_for_search = getParam<Real>(
"automatic_pairing_distance");
1387 for (
const auto & pair : node_boundary_id_vector)
1390 ret_matches.clear();
1393 const Point search_point = *pair.first;
1396 kd_tree->radiusSearch(
1397 &(search_point)(0), radius_for_search * radius_for_search, ret_matches, search_params);
1399 for (
auto & match_pair : ret_matches)
1401 const auto & match = node_boundary_id_vector[match_pair.first];
1408 auto it = std::find(_automatic_pairing_boundaries_id.begin(),
1409 _automatic_pairing_boundaries_id.end(),
1413 if (match.second == pair.second)
1419 if (it != _automatic_pairing_boundaries_id.end())
1421 const auto index_one = cast_int<int>(it - _automatic_pairing_boundaries_id.begin());
1422 auto it_other = std::find(_automatic_pairing_boundaries_id.begin(),
1423 _automatic_pairing_boundaries_id.end(),
1426 mooseAssert(it_other != _automatic_pairing_boundaries_id.end(),
1427 "Error in contact action. Unable to find boundary ID for node proximity " 1428 "automatic pairing.");
1430 const auto index_two = cast_int<int>(it_other - _automatic_pairing_boundaries_id.begin());
1432 if (pair.second > match.second)
1446 "The following boundary pairs were created by the contact action using nodal proximity: ");
1449 "Primary boundary ID: ", primary,
" and secondary boundary ID: ", secondary,
".");
1455 mooseInfo(
"The contact action is reading the list of boundaries and automatically pairs them " 1456 "if their centroids fall within a specified distance of each other.");
1459 mooseError(
"Failed to obtain mesh for automatically generating contact pairs.");
1461 if (!
_mesh->getMesh().is_serial())
1463 "automatic_pairing_boundaries",
1464 "The generation of automatic contact pairs in the contact action requires a serial mesh.");
1467 std::vector<std::pair<BoundaryName, Point>> automatic_pairing_boundaries_cog;
1468 const auto & sideset_ids =
_mesh->meshSidesetIds();
1470 const auto & bnd_to_elem_map =
_mesh->getBoundariesToActiveSemiLocalElemIds();
1475 const auto find_set = sideset_ids.find(
_mesh->getBoundaryID(sideset_name));
1476 if (find_set == sideset_ids.end())
1479 " is not defined as a sideset in the mesh.");
1481 auto dofs_set = bnd_to_elem_map.find(
_mesh->getBoundaryID(sideset_name));
1484 Point center_of_gravity(0, 0, 0);
1485 Real accumulated_sideset_area(0);
1488 std::unique_ptr<const Elem> side_ptr;
1489 const std::unordered_set<dof_id_type> & bnd_elems = dofs_set->second;
1491 for (
auto elem_id : bnd_elems)
1493 const Elem * elem =
_mesh->elemPtr(elem_id);
1494 unsigned int side =
_mesh->sideWithBoundaryID(elem,
_mesh->getBoundaryID(sideset_name));
1497 elem->side_ptr(side_ptr, side);
1500 const auto side_area = side_ptr->volume();
1503 const auto side_position = side_ptr->true_centroid();
1505 center_of_gravity += side_position * side_area;
1506 accumulated_sideset_area += side_area;
1510 center_of_gravity /= accumulated_sideset_area;
1513 automatic_pairing_boundaries_cog.emplace_back(sideset_name, center_of_gravity);
1517 std::vector<std::pair<std::pair<BoundaryName, BoundaryName>,
Real>> pairs_distances;
1520 for (std::size_t i = 0; i < automatic_pairing_boundaries_cog.size() - 1; i++)
1521 for (std::size_t
j = i + 1;
j < automatic_pairing_boundaries_cog.size();
j++)
1523 const Point & distance_vector =
1524 automatic_pairing_boundaries_cog[i].second - automatic_pairing_boundaries_cog[
j].second;
1526 if (automatic_pairing_boundaries_cog[i].first != automatic_pairing_boundaries_cog[
j].first)
1529 const std::pair pair = std::make_pair(automatic_pairing_boundaries_cog[i].first,
1530 automatic_pairing_boundaries_cog[
j].first);
1531 pairs_distances.emplace_back(std::make_pair(pair,
distance));
1535 const auto automatic_pairing_distance = getParam<Real>(
"automatic_pairing_distance");
1538 std::vector<std::pair<std::pair<BoundaryName, BoundaryName>,
Real>> lean_pairs_distances;
1539 for (
const auto & pair_distance : pairs_distances)
1540 if (pair_distance.second <= automatic_pairing_distance)
1542 lean_pairs_distances.emplace_back(pair_distance);
1544 pair_distance.first.first,
1546 pair_distance.first.second,
1547 ", with a relative distance of ",
1548 pair_distance.second);
1552 for (
const auto & lean_pairs_distance : lean_pairs_distances)
1557 if (
_mesh->getBoundaryID(lean_pairs_distance.first.first) >
1558 _mesh->getBoundaryID(lean_pairs_distance.first.second))
1560 {lean_pairs_distance.first.first, lean_pairs_distance.first.second});
1563 {lean_pairs_distance.first.second, lean_pairs_distance.first.first});
1573 return MooseEnum(
"frictionless glued coulomb",
"frictionless");
1586 "ranfs kinematic penalty augmented_lagrange tangential_penalty mortar mortar_penalty",
1589 formulations.addDocumentation(
1591 "Reduced Active Nonlinear Function Set scheme for node-on-face contact. Provides exact " 1592 "enforcement without Lagrange multipliers or penalty terms.");
1593 formulations.addDocumentation(
1595 "Kinematic contact constraint enforcement transfers the internal forces at secondary nodes " 1596 "to the corresponding primary face for node-on-face contact. Provides exact " 1597 "enforcement without Lagrange multipliers or penalty terms.");
1598 formulations.addDocumentation(
1600 "Node-on-face penalty based contact constraint enforcement. Interpenetration is penalized. " 1601 "Enforcement depends on the penalty magnitude. High penalties can introduce ill conditioning " 1603 formulations.addDocumentation(
"augmented_lagrange",
1604 "Node-on-face augmented Lagrange penalty based contact constraint " 1605 "enforcement. Interpenetration is enforced up to a user specified " 1606 "tolerance, ill-conditioning is generally avoided. Requires an " 1607 "Augmented Lagrange Problem class to be used in the simulation.");
1608 formulations.addDocumentation(
1609 "tangential_penalty",
1610 "Node-on-face penalty based frictional contact constraint enforcement. Interpenetration and " 1611 "slip distance for sticking nodes are penalized. Enforcement depends on the penalty " 1612 "magnitudes. High penalties can introduce ill conditioning of the system.");
1613 formulations.addDocumentation(
1615 "Mortar based contact constraint enforcement using Lagrange multipliers. Provides exact " 1616 "enforcement and a variationally consistent formulation. Lagrange multipliers introduce a " 1617 "saddle point character in the system matrix which can have a negative impact on scalability " 1618 "with iterative solvers");
1619 formulations.addDocumentation(
1621 "Mortar and penalty based contact constraint enforcement. When using an Augmented Lagrange " 1622 "Problem class this provides normal (and tangential) contact constratint enforced up to a " 1623 "user specified tolerances. Without AL the enforcement depends on the penalty magnitudes. " 1624 "High penalties can introduce ill conditioning of the system.");
1626 return formulations;
1632 return MooseEnum(
"Constraint",
"Constraint");
1638 return MooseEnum(
"edge_based nodal_normal_based",
"");
1648 "Method to use to smooth normals");
1650 "normal_smoothing_distance",
1651 "Distance from edge in parametric coordinates over which to smooth contact normal");
void mooseInfo(Args &&... args) const
bool isUltimateMaster() const
const std::string & _name
void paramError(const std::string ¶m, Args... args) const
const T & getParam(const std::string &name) const
const InputParameters & parameters() const
const Point & getPoint(const PointObject &item) const
InputParameters getValidParams(const std::string &name) const
void mooseInfoRepeated(Args &&... args)
const ExecFlagType EXEC_TIMESTEP_END
Real distance(const Point &p)
std::string shortName(const std::string &name)
static InputParameters validParams()
const std::string & name() const
static InputParameters validParams()
const ExecFlagType EXEC_TIMESTEP_BEGIN
boundary_id_type BoundaryID
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)
const ExecFlagType EXEC_LINEAR
std::string stringify(const T &t)
const MeshGenerator & appendMeshGenerator(const std::string &type, const std::string &name, InputParameters params)
std::pair< T, U > ResultItem
const ExecFlagType EXEC_NONLINEAR
std::shared_ptr< MooseMesh > & _mesh
static libMesh::FEType feType(const InputParameters ¶ms)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
bool useMasterMesh() const
void mooseError(Args &&... args) const
std::shared_ptr< FEProblemBase > & _problem
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
bool isParamValid(const std::string &name) const
std::vector< const T *> getActions()
bool isRecovering() const
SearchParams SearchParameters
bool isParamSetByUser(const std::string &name) const
auto index_range(const T &sizable)
const ExecFlagType EXEC_INITIAL