581 if (!
_problem->getDisplacedProblem())
583 "Contact requires updated coordinates. Use the 'displacements = ...' parameter in the "
590 if (!
_problem->isSNESMFReuseBaseSetbyUser())
591 _problem->setSNESMFReuseBase(
false,
false);
610 if (!
_problem->getDisplacedProblem())
611 mooseError(
"Contact requires updated coordinates. Use the 'displacements = ...' line in the "
617 const auto & [primary_name, secondary_name] = contact_pair;
623 {
"secondary_gap_offset",
"mapped_primary_gap_offset",
"order"});
625 std::vector<VariableName> displacements =
626 getParam<std::vector<VariableName>>(
"displacements");
627 const auto order =
_problem->systemBaseNonlinear(0)
629 .variable_type(displacements[0])
632 params.
set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{order});
634 params.
set<std::vector<BoundaryName>>(
"boundary") = {secondary_name};
635 params.
set<BoundaryName>(
"paired_boundary") = primary_name;
636 params.
set<AuxVariableName>(
"variable") =
"penetration";
638 params.
set<std::vector<VariableName>>(
"secondary_gap_offset") = {
639 getParam<VariableName>(
"secondary_gap_offset")};
641 params.
set<std::vector<VariableName>>(
"mapped_primary_gap_offset") = {
642 getParam<VariableName>(
"mapped_primary_gap_offset")};
643 params.
set<
bool>(
"use_displaced_mesh") =
true;
650 const auto type =
"MortarUserObjectAux";
652 params.
set<std::vector<BoundaryName>>(
"boundary") = {secondary_name};
653 params.
set<AuxVariableName>(
"variable") =
"gap";
654 params.
set<
bool>(
"use_displaced_mesh") =
true;
656 params.
set<
MooseEnum>(
"contact_quantity") =
"normal_gap";
657 const auto & [primary_id, secondary_id, uo_name] =
659 params.
set<UserObjectName>(
"user_object") = uo_name;
660 std::string
name =
_name +
"_contact_gap_" + std::to_string(primary_id) +
"_" +
661 std::to_string(secondary_id);
669 const unsigned int ndisp = getParam<std::vector<VariableName>>(
"displacements").size();
672 if (
_formulation == ContactFormulation::MORTAR &&
_model == ContactModel::COULOMB && ndisp > 2)
675 for (
const auto & [primary_boundary, secondary_boundary] :
_boundary_pairs)
677 const std::string suffix =
pairSuffix({primary_boundary, secondary_boundary});
680 params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
681 params.set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
682 params.set<std::vector<BoundaryName>>(
"boundary") = {secondary_boundary};
684 params.set<std::vector<VariableName>>(
"tangent_one") = {action_name +
"_tangential_lm" +
686 params.set<std::vector<VariableName>>(
"tangent_two") = {action_name +
"_tangential_3d_lm" +
689 std::vector<std::string> disp_components({
"x",
"y",
"z"});
690 unsigned component_index = 0;
693 for (
const auto & disp_component : disp_components)
695 params.set<AuxVariableName>(
"variable") =
_name +
"_tangent_" + disp_component;
696 params.set<
unsigned int>(
"component") = component_index;
698 std::string
name =
_name +
"_mortar_frictional_pressure_" + disp_component +
"_" +
701 _problem->addAuxKernel(
"MortarFrictionalPressureVectorAux",
name, params);
710 std::vector<VariableName> displacements = getParam<std::vector<VariableName>>(
"displacements");
711 const auto order =
_problem->systemBaseNonlinear(0)
713 .variable_type(displacements[0])
715 const auto mortar_lm_order =
716 _lm_space == ContactLMSpace::LINEAR ?
static_cast<int>(FIRST) : order;
717 std::unique_ptr<InputParameters> current_params;
718 const auto create_aux_var_params =
725 const auto aux_order =
_formulation == ContactFormulation::MORTAR ? mortar_lm_order : order;
726 current_params->set<
MooseEnum>(
"order") =
727 Utility::enum_to_string<Order>(OrderWrapper{aux_order});
728 current_params->set<
MooseEnum>(
"family") =
"LAGRANGE";
729 return *current_params;
736 _problem->addAuxVariable(
"MooseVariable",
"penetration", create_aux_var_params());
738 _problem->addAuxVariable(
"MooseVariable",
"nodal_area", create_aux_var_params());
741 _problem->addAuxVariable(
"MooseVariable",
"gap", create_aux_var_params());
744 _problem->addAuxVariable(
"MooseVariable",
"contact_pressure", create_aux_var_params());
746 const unsigned int ndisp = getParam<std::vector<VariableName>>(
"displacements").size();
749 if (
_formulation == ContactFormulation::MORTAR &&
_model == ContactModel::COULOMB && ndisp > 2)
752 std::vector<std::string> disp_components({
"x",
"y",
"z"});
754 for (
const auto & disp_component : disp_components)
758 Utility::enum_to_string<Order>(OrderWrapper{mortar_lm_order});
759 var_params.set<
MooseEnum>(
"family") =
"LAGRANGE";
762 "MooseVariable",
_name +
"_tangent_" + disp_component, var_params);
777 std::vector<BoundaryName> secondary_boundary_vector;
778 for (
const auto *
const action : actions)
779 for (
const auto j : index_range(action->_boundary_pairs))
780 secondary_boundary_vector.push_back(action->_boundary_pairs[j].second);
782 var_params.set<std::vector<BoundaryName>>(
"boundary") = secondary_boundary_vector;
783 var_params.set<std::vector<VariableName>>(
"variable") = {
"nodal_area"};
785 mooseAssert(
_problem,
"Problem pointer is NULL");
787 var_params.set<
bool>(
"use_displaced_mesh") =
true;
789 _problem->addUserObject(
"NodalArea",
919 std::vector<VariableName> displacements = getParam<std::vector<VariableName>>(
"displacements");
920 const unsigned int ndisp = displacements.size();
923 const auto addLagrangeMultiplier = [
this, &displacements](
const std::string & secondary_subdomain,
924 const std::string & variable_name,
925 const Real scaling_factor,
926 const bool add_aux_lm,
927 const bool penalty_traction)
934 if (!add_aux_lm || penalty_traction)
937 mooseAssert(
_problem->systemBaseNonlinear(0).hasVariable(displacements[0]),
938 "Displacement variable is missing");
939 const auto primal_type =
940 _problem->systemBaseNonlinear(0).system().variable_type(displacements[0]);
946 ?
static_cast<int>(FIRST)
947 : primal_type.order.get_order();
949 if (primal_type.family == LAGRANGE)
951 params.
set<
MooseEnum>(
"family") = Utility::enum_to_string<FEFamily>(primal_type.family);
952 params.
set<
MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{lm_order});
955 mooseError(
"Invalid bases for mortar contact.");
957 params.
set<std::vector<SubdomainName>>(
"block") = {secondary_subdomain};
958 if (!(add_aux_lm || penalty_traction))
959 params.
set<std::vector<Real>>(
"scaling") = {scaling_factor};
963 if (add_aux_lm || penalty_traction)
964 _problem->addAuxVariable(var_type, variable_name, params);
966 _problem->addVariable(var_type, variable_name, params);
978 for (
const auto & [primary_boundary, secondary_boundary] :
_boundary_pairs)
980 const std::string suffix =
pairSuffix({primary_boundary, secondary_boundary});
981 const std::string primary_subdomain_name = action_name +
"_primary_subdomain" + suffix;
982 const std::string secondary_subdomain_name = action_name +
"_secondary_subdomain" + suffix;
984 const MeshGeneratorName primary_name = primary_subdomain_name +
"_generator";
985 const MeshGeneratorName secondary_name = secondary_subdomain_name +
"_generator";
990 primary_params.
set<SubdomainName>(
"new_block_name") = primary_subdomain_name;
991 secondary_params.set<SubdomainName>(
"new_block_name") = secondary_subdomain_name;
993 primary_params.set<std::vector<BoundaryName>>(
"sidesets") = {primary_boundary};
994 secondary_params.set<std::vector<BoundaryName>>(
"sidesets") = {secondary_boundary};
998 "LowerDBlockFromSidesetGenerator", secondary_name, secondary_params);
1007 const std::string suffix =
pairSuffix(contact_pair);
1008 const std::string secondary_subdomain_name = action_name +
"_secondary_subdomain" + suffix;
1009 const std::string normal_lagrange_multiplier_name = action_name +
"_normal_lm" + suffix;
1010 const std::string tangential_lagrange_multiplier_name =
1011 action_name +
"_tangential_lm" + suffix;
1012 const std::string tangential_lagrange_multiplier_3d_name =
1013 action_name +
"_tangential_3d_lm" + suffix;
1014 const std::string auxiliary_lagrange_multiplier_name = action_name +
"_aux_lm" + suffix;
1016 addLagrangeMultiplier(secondary_subdomain_name,
1017 normal_lagrange_multiplier_name,
1018 getParam<Real>(
"normal_lm_scaling"),
1022 if (
_model == ContactModel::COULOMB)
1024 addLagrangeMultiplier(secondary_subdomain_name,
1025 tangential_lagrange_multiplier_name,
1026 getParam<Real>(
"tangential_lm_scaling"),
1030 addLagrangeMultiplier(secondary_subdomain_name,
1031 tangential_lagrange_multiplier_3d_name,
1032 getParam<Real>(
"tangential_lm_scaling"),
1037 if (getParam<bool>(
"use_petrov_galerkin"))
1038 addLagrangeMultiplier(
1039 secondary_subdomain_name, auxiliary_lagrange_multiplier_name, 1.0,
true,
false);
1047 const std::string suffix =
pairSuffix(contact_pair);
1048 const std::string secondary_subdomain_name = action_name +
"_secondary_subdomain" + suffix;
1049 const std::string auxiliary_lagrange_multiplier_name = action_name +
"_aux_lm" + suffix;
1052 addLagrangeMultiplier(
1053 secondary_subdomain_name, auxiliary_lagrange_multiplier_name, 1.0,
false,
true);
1060 if (
_formulation == ContactFormulation::MORTAR_PENALTY &&
1063 const std::vector<std::string> params = {
"penalty_multiplier",
1064 "penalty_multiplier_friction",
1065 "al_penetration_tolerance",
1066 "al_incremental_slip_tolerance",
1067 "al_frictional_force_tolerance"};
1068 for (
const auto & param : params)
1071 "Augmented Lagrange parameter was specified, but the selected problem type "
1072 "does not support Augmented Lagrange iterations.");
1075 for (
const auto & [primary_boundary, secondary_boundary] :
_boundary_pairs)
1077 const std::string suffix =
pairSuffix({primary_boundary, secondary_boundary});
1078 const std::string primary_subdomain_name = action_name +
"_primary_subdomain" + suffix;
1079 const std::string secondary_subdomain_name = action_name +
"_secondary_subdomain" + suffix;
1080 const std::string normal_lagrange_multiplier_name = action_name +
"_normal_lm" + suffix;
1081 const std::string tangential_lagrange_multiplier_name =
1082 action_name +
"_tangential_lm" + suffix;
1083 const std::string tangential_lagrange_multiplier_3d_name =
1084 action_name +
"_tangential_3d_lm" + suffix;
1085 const std::string auxiliary_lagrange_multiplier_name = action_name +
"_aux_lm" + suffix;
1087 const auto register_mortar_uo_name =
1088 [
this, &suffix](
const auto & bnd_pair,
const auto & uo_prefix)
1090 const auto & [primary_name, secondary_name] = bnd_pair;
1091 const auto primary_id =
_mesh->getBoundaryID(primary_name);
1092 const auto secondary_id =
_mesh->getBoundaryID(secondary_name);
1093 const auto uo_name = uo_prefix +
name() + suffix;
1102 uo_params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
1103 uo_params.set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
1104 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1105 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1106 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1107 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1109 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1110 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
1111 uo_params.set<std::vector<VariableName>>(
"lm_variable") = {normal_lagrange_multiplier_name};
1112 uo_params.applySpecificParameters(
parameters(),
1113 {
"correct_edge_dropping",
1114 "use_nodal_scaling",
1116 "triangulate_triangles",
1117 "minimum_projection_angle",
1118 "mortar_3d_subpatch_plane",
1119 "mortar_3d_qp_mapping",
1120 "use_petrov_galerkin",
1122 if (getParam<bool>(
"use_petrov_galerkin"))
1123 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
1126 "LMWeightedGapUserObject",
1127 register_mortar_uo_name(std::make_pair(primary_boundary, secondary_boundary),
1128 "lm_weightedgap_object_"),
1131 else if (
_model == ContactModel::COULOMB &&
_formulation == ContactFormulation::MORTAR)
1134 uo_params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
1135 uo_params.set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
1136 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1137 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1138 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1139 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1141 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1143 uo_params.set<VariableName>(
"secondary_variable") = displacements[0];
1144 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
1145 uo_params.set<std::vector<VariableName>>(
"lm_variable_normal") = {
1146 normal_lagrange_multiplier_name};
1147 uo_params.set<std::vector<VariableName>>(
"lm_variable_tangential_one") = {
1148 tangential_lagrange_multiplier_name};
1150 uo_params.set<std::vector<VariableName>>(
"lm_variable_tangential_two") = {
1151 tangential_lagrange_multiplier_3d_name};
1152 uo_params.applySpecificParameters(
parameters(),
1153 {
"correct_edge_dropping",
1154 "use_nodal_scaling",
1156 "triangulate_triangles",
1157 "minimum_projection_angle",
1158 "mortar_3d_subpatch_plane",
1159 "mortar_3d_qp_mapping",
1160 "use_petrov_galerkin",
1162 if (getParam<bool>(
"use_petrov_galerkin"))
1163 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
1166 "LMWeightedVelocitiesUserObject",
1167 register_mortar_uo_name(std::make_pair(primary_boundary, secondary_boundary),
1168 "lm_weightedvelocities_object_"),
1172 if (
_model != ContactModel::COULOMB &&
_formulation == ContactFormulation::MORTAR_PENALTY)
1176 uo_params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
1177 uo_params.set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
1178 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1179 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1180 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1181 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1184 uo_params.applySpecificParameters(
parameters(),
1185 {
"correct_edge_dropping",
1187 "triangulate_triangles",
1188 "minimum_projection_angle",
1189 "mortar_3d_subpatch_plane",
1190 "mortar_3d_qp_mapping",
1193 "max_penalty_multiplier",
1194 "adaptivity_penalty_normal"});
1197 uo_params.set<Real>(
"penetration_tolerance") = getParam<Real>(
"al_penetration_tolerance");
1199 uo_params.set<Real>(
"penalty_multiplier") = getParam<Real>(
"penalty_multiplier");
1202 uo_params.set<
bool>(
"use_physical_gap") =
true;
1205 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
1208 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1209 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
1212 "PenaltyWeightedGapUserObject",
1213 register_mortar_uo_name(std::make_pair(primary_boundary, secondary_boundary),
1214 "penalty_weightedgap_object_"),
1218 else if (
_model == ContactModel::COULOMB &&
1222 uo_params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
1223 uo_params.set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
1224 uo_params.set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1225 uo_params.set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1226 uo_params.set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1227 uo_params.set<
bool>(
"correct_edge_dropping") = getParam<bool>(
"correct_edge_dropping");
1228 uo_params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1230 uo_params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1232 uo_params.set<VariableName>(
"secondary_variable") = displacements[0];
1233 uo_params.set<
bool>(
"use_displaced_mesh") =
true;
1234 uo_params.set<Real>(
"friction_coefficient") = getParam<Real>(
"friction_coefficient");
1235 uo_params.set<Real>(
"penalty") = getParam<Real>(
"penalty");
1236 uo_params.set<Real>(
"penalty_friction") = getParam<Real>(
"penalty_friction");
1239 uo_params.set<Real>(
"max_penalty_multiplier") = getParam<Real>(
"max_penalty_multiplier");
1240 uo_params.set<
MooseEnum>(
"adaptivity_penalty_normal") =
1241 getParam<MooseEnum>(
"adaptivity_penalty_normal");
1242 uo_params.set<
MooseEnum>(
"adaptivity_penalty_friction") =
1243 getParam<MooseEnum>(
"adaptivity_penalty_friction");
1245 uo_params.set<Real>(
"penetration_tolerance") = getParam<Real>(
"al_penetration_tolerance");
1247 uo_params.set<Real>(
"penalty_multiplier") = getParam<Real>(
"penalty_multiplier");
1249 uo_params.set<Real>(
"penalty_multiplier_friction") =
1250 getParam<Real>(
"penalty_multiplier_friction");
1253 uo_params.set<Real>(
"slip_tolerance") = getParam<Real>(
"al_incremental_slip_tolerance");
1256 uo_params.set<
bool>(
"use_physical_gap") =
true;
1259 uo_params.set<std::vector<VariableName>>(
"aux_lm") = {auxiliary_lagrange_multiplier_name};
1261 uo_params.applySpecificParameters(
parameters(),
1263 "triangulate_triangles",
1264 "minimum_projection_angle",
1265 "mortar_3d_subpatch_plane",
1266 "mortar_3d_qp_mapping",
1267 "friction_coefficient",
1269 "penalty_friction"});
1272 "PenaltyFrictionUserObject",
1273 register_mortar_uo_name(std::make_pair(primary_boundary, secondary_boundary),
1274 "penalty_friction_object_"),
1285 const BoundaryName & primary_boundary = contact_pair.first;
1286 const BoundaryName & secondary_boundary = contact_pair.second;
1287 const std::string suffix =
pairSuffix(contact_pair);
1288 const std::string primary_subdomain_name = action_name +
"_primary_subdomain" + suffix;
1289 const std::string secondary_subdomain_name = action_name +
"_secondary_subdomain" + suffix;
1290 const std::string normal_lagrange_multiplier_name = action_name +
"_normal_lm" + suffix;
1291 const std::string tangential_lagrange_multiplier_name =
1292 action_name +
"_tangential_lm" + suffix;
1293 const std::string tangential_lagrange_multiplier_3d_name =
1294 action_name +
"_tangential_3d_lm" + suffix;
1299 std::string mortar_constraint_name;
1302 mortar_constraint_name =
"ComputeWeightedGapLMMechanicalContact";
1304 mortar_constraint_name =
"ComputeDynamicWeightedGapLMMechanicalContact";
1309 parameters(), {
"newmark_beta",
"newmark_gamma",
"capture_tolerance",
"wear_depth"});
1312 params.
set<UserObjectName>(
"weighted_gap_uo") =
1313 "lm_weightedgap_object_" +
name() + suffix;
1315 params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
1316 params.
set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
1317 params.
set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1318 params.
set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1319 params.
set<NonlinearVariableName>(
"variable") = normal_lagrange_multiplier_name;
1320 params.
set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1321 params.
set<Real>(
"c") = getParam<Real>(
"c_normal");
1324 params.
set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1326 params.
set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1328 params.
set<
bool>(
"use_displaced_mesh") =
true;
1331 {
"correct_edge_dropping",
1333 "triangulate_triangles",
1334 "minimum_projection_angle",
1335 "mortar_3d_subpatch_plane",
1336 "mortar_3d_qp_mapping",
1338 "extra_vector_tags",
1339 "absolute_value_vector_tags",
1343 mortar_constraint_name, action_name +
"_normal_lm_weighted_gap" + suffix, params);
1347 else if (
_model == ContactModel::COULOMB &&
_formulation == ContactFormulation::MORTAR)
1349 std::string mortar_constraint_name;
1352 mortar_constraint_name =
"ComputeFrictionalForceLMMechanicalContact";
1354 mortar_constraint_name =
"ComputeDynamicFrictionalForceLMMechanicalContact";
1359 parameters(), {
"newmark_beta",
"newmark_gamma",
"capture_tolerance",
"wear_depth"});
1362 params.
set<UserObjectName>(
"weighted_gap_uo") =
1363 "lm_weightedvelocities_object_" +
name() + suffix;
1364 params.
set<UserObjectName>(
"weighted_velocities_uo") =
1365 "lm_weightedvelocities_object_" +
name() + suffix;
1368 params.
set<
bool>(
"correct_edge_dropping") = getParam<bool>(
"correct_edge_dropping");
1369 params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
1370 params.
set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
1371 params.
set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1372 params.
set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1373 params.
set<
bool>(
"use_displaced_mesh") =
true;
1374 params.
set<Real>(
"c_t") = getParam<Real>(
"c_tangential");
1375 params.
set<Real>(
"c") = getParam<Real>(
"c_normal");
1376 params.
set<
bool>(
"normalize_c") = getParam<bool>(
"normalize_c");
1377 params.
set<
bool>(
"compute_primal_residuals") =
false;
1379 params.
set<
MooseEnum>(
"segment_quadrature") = getParam<MooseEnum>(
"segment_quadrature");
1381 params.
set<std::vector<VariableName>>(
"disp_x") = {displacements[0]};
1384 params.
set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
1386 params.
set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
1388 params.
set<NonlinearVariableName>(
"variable") = normal_lagrange_multiplier_name;
1389 params.
set<std::vector<VariableName>>(
"friction_lm") = {
1390 tangential_lagrange_multiplier_name};
1393 params.
set<std::vector<VariableName>>(
"friction_lm_dir") = {
1394 tangential_lagrange_multiplier_3d_name};
1396 params.
set<Real>(
"mu") = getParam<Real>(
"friction_coefficient");
1398 getParam<MooseEnum>(
"friction_projection_degree");
1401 "triangulate_triangles",
1402 "minimum_projection_angle",
1403 "mortar_3d_subpatch_plane",
1404 "mortar_3d_qp_mapping",
1405 "extra_vector_tags",
1406 "absolute_value_vector_tags",
1410 mortar_constraint_name, action_name +
"_tangential_lm" + suffix, params);
1414 const auto addMechanicalContactConstraints =
1417 &secondary_boundary,
1419 &primary_subdomain_name,
1420 &secondary_subdomain_name,
1421 &displacements](
const std::string & variable_name,
1422 const std::string & constraint_prefix,
1423 const std::string & constraint_type,
1424 const bool is_additional_frictional_constraint,
1425 const bool is_normal_constraint)
1429 params.
set<
bool>(
"correct_edge_dropping") = getParam<bool>(
"correct_edge_dropping");
1430 params.
set<BoundaryName>(
"primary_boundary") = primary_boundary;
1431 params.
set<BoundaryName>(
"secondary_boundary") = secondary_boundary;
1432 params.
set<SubdomainName>(
"primary_subdomain") = primary_subdomain_name;
1433 params.
set<SubdomainName>(
"secondary_subdomain") = secondary_subdomain_name;
1436 params.
set<NonlinearVariableName>(
"variable") = variable_name;
1438 params.
set<
MooseEnum>(
"segment_quadrature") = getParam<MooseEnum>(
"segment_quadrature");
1439 params.
set<
bool>(
"use_displaced_mesh") =
true;
1440 params.
set<
bool>(
"compute_lm_residuals") =
false;
1444 if (is_additional_frictional_constraint)
1448 "triangulate_triangles",
1449 "minimum_projection_angle",
1450 "mortar_3d_subpatch_plane",
1451 "mortar_3d_qp_mapping",
1452 "extra_vector_tags",
1453 "absolute_value_vector_tags",
1456 for (
const auto i : index_range(displacements))
1460 params.
set<VariableName>(
"secondary_variable") = displacements[i];
1463 if (is_normal_constraint &&
_model != ContactModel::COULOMB &&
1465 params.
set<UserObjectName>(
"weighted_gap_uo") =
1466 "lm_weightedgap_object_" +
name() + suffix;
1467 else if (is_normal_constraint &&
_model == ContactModel::COULOMB &&
1469 params.
set<UserObjectName>(
"weighted_gap_uo") =
1470 "lm_weightedvelocities_object_" +
name() + suffix;
1472 params.
set<UserObjectName>(
"weighted_velocities_uo") =
1473 "lm_weightedvelocities_object_" +
name() + suffix;
1474 else if (is_normal_constraint &&
_model != ContactModel::COULOMB &&
1476 params.
set<UserObjectName>(
"weighted_gap_uo") =
1477 "penalty_weightedgap_object_" +
name() + suffix;
1478 else if (is_normal_constraint &&
_model == ContactModel::COULOMB &&
1480 params.
set<UserObjectName>(
"weighted_gap_uo") =
1481 "penalty_friction_object_" +
name() + suffix;
1482 else if (
_formulation == ContactFormulation::MORTAR_PENALTY)
1483 params.
set<UserObjectName>(
"weighted_velocities_uo") =
1484 "penalty_friction_object_" +
name() + suffix;
1486 _problem->addConstraint(constraint_type, constraint_name, params);
1492 addMechanicalContactConstraints(normal_lagrange_multiplier_name,
1493 action_name +
"_normal_constraint" + suffix +
"_",
1494 "NormalMortarMechanicalContact",
1498 if (
_model == ContactModel::COULOMB)
1500 addMechanicalContactConstraints(tangential_lagrange_multiplier_name,
1501 action_name +
"_tangential_constraint" + suffix +
"_",
1502 "TangentialMortarMechanicalContact",
1506 addMechanicalContactConstraints(tangential_lagrange_multiplier_3d_name,
1507 action_name +
"_tangential_constraint_3d" + suffix +
"_",
1508 "TangentialMortarMechanicalContact",