176 std::string action_name = MooseUtils::shortName(
name());
179 const unsigned int ndisp = displacements.size();
182 const std::string master_subdomain_name = action_name +
"_master_subdomain";
183 const std::string slave_subdomain_name = action_name +
"_slave_subdomain";
184 const std::string normal_lagrange_multiplier_name = action_name +
"_normal_lm";
185 const std::string tangential_lagrange_multiplier_name = action_name +
"_tangential_lm";
187 if (_current_task ==
"add_mesh_generator")
190 if (!(_app.isRecovering() && _app.isUltimateMaster()) && !_app.masterMesh())
192 const MeshGeneratorName master_name = master_subdomain_name +
"_generator";
193 const MeshGeneratorName slave_name = slave_subdomain_name +
"_generator";
195 auto master_params = _factory.getValidParams(
"LowerDBlockFromSidesetGenerator");
196 auto slave_params = _factory.getValidParams(
"LowerDBlockFromSidesetGenerator");
199 slave_params.set<MeshGeneratorName>(
"input") = master_name;
201 master_params.set<SubdomainName>(
"new_block_name") = master_subdomain_name;
202 slave_params.set<SubdomainName>(
"new_block_name") = slave_subdomain_name;
204 master_params.set<std::vector<BoundaryName>>(
"sidesets") = {
_master};
205 slave_params.set<std::vector<BoundaryName>>(
"sidesets") = {
_slave};
207 _app.addMeshGenerator(
"LowerDBlockFromSidesetGenerator", master_name, master_params);
208 _app.addMeshGenerator(
"LowerDBlockFromSidesetGenerator", slave_name, slave_params);
212 if (_current_task ==
"add_variable")
215 const auto addLagrangeMultiplier =
216 [
this, &slave_subdomain_name, &displacements](
const std::string & variable_name,
217 const int codimension)
219 InputParameters params = _factory.getValidParams(
"MooseVariableBase");
221 mooseAssert(_problem->systemBaseNonlinear().hasVariable(displacements[0]),
222 "Displacement variable is missing");
223 const auto primal_type =
224 _problem->systemBaseNonlinear().system().variable_type(displacements[0]);
225 const int lm_order = std::max(primal_type.order.get_order() - codimension, 0);
227 if (primal_type.family == MONOMIAL || (primal_type.family == LAGRANGE && lm_order < 1))
229 params.set<MooseEnum>(
"family") =
"MONOMIAL";
230 params.set<MooseEnum>(
"order") =
"CONSTANT";
232 else if (primal_type.family == LAGRANGE)
234 params.set<MooseEnum>(
"family") = Utility::enum_to_string<FEFamily>(primal_type.family);
235 params.set<MooseEnum>(
"order") = Utility::enum_to_string<Order>(OrderWrapper{lm_order});
238 mooseError(
"Primal variable type must be either MONOMIAL or LAGRANGE for mortar contact.");
240 params.set<std::vector<SubdomainName>>(
"block") = {slave_subdomain_name};
241 auto fe_type = AddVariableAction::feType(params);
242 auto var_type = AddVariableAction::determineType(fe_type, 1);
243 _problem->addVariable(var_type, variable_name, params);
247 addLagrangeMultiplier(normal_lagrange_multiplier_name, 0);
249 addLagrangeMultiplier(tangential_lagrange_multiplier_name, 1);
252 if (_current_task ==
"add_constraint")
256 InputParameters params = _factory.getValidParams(
"NormalNodalLMMechanicalContact");
258 params.set<BoundaryName>(
"master") =
_master;
259 params.set<BoundaryName>(
"slave") =
_slave;
260 params.set<NonlinearVariableName>(
"variable") = normal_lagrange_multiplier_name;
261 params.set<
bool>(
"use_displaced_mesh") =
true;
262 params.set<MooseEnum>(
"ncp_function_type") =
"min";
263 params.set<Real>(
"c") = getParam<Real>(
"c_normal");
265 params.set<std::vector<VariableName>>(
"master_variable") = {displacements[0]};
267 params.set<std::vector<VariableName>>(
"disp_y") = {displacements[1]};
269 params.set<std::vector<VariableName>>(
"disp_z") = {displacements[2]};
271 _problem->addConstraint(
"NormalNodalLMMechanicalContact", action_name +
"_normal_lm", params);
277 InputParameters params =
278 _factory.getValidParams(
"TangentialMortarLMMechanicalContact<RESIDUAL>");
280 params.set<BoundaryName>(
"master_boundary") =
_master;
281 params.set<BoundaryName>(
"slave_boundary") =
_slave;
282 params.set<SubdomainName>(
"master_subdomain") = master_subdomain_name;
283 params.set<SubdomainName>(
"slave_subdomain") = slave_subdomain_name;
284 params.set<NonlinearVariableName>(
"variable") = tangential_lagrange_multiplier_name;
285 params.set<
bool>(
"use_displaced_mesh") =
true;
286 params.set<MooseEnum>(
"ncp_function_type") =
"fb";
287 params.set<Real>(
"c") = getParam<Real>(
"c_tangential");
288 params.set<
bool>(
"compute_primal_residuals") =
false;
289 params.set<NonlinearVariableName>(
"contact_pressure") = normal_lagrange_multiplier_name;
290 params.set<Real>(
"friction_coefficient") = getParam<Real>(
"friction_coefficient");
292 params.set<VariableName>(
"slave_variable") = displacements[0];
294 params.set<NonlinearVariableName>(
"slave_disp_y") = displacements[1];
297 _problem->addConstraint(
"TangentialMortarLMMechanicalContact<RESIDUAL>",
298 action_name +
"_tangential_lm_residual",
300 _problem->addConstraint(
"TangentialMortarLMMechanicalContact<JACOBIAN>",
301 action_name +
"_tangential_lm_jacobian",
305 const auto addMechanicalContactConstraints =
306 [
this, &master_subdomain_name, &slave_subdomain_name, &displacements](
307 const std::string & variable_name,
308 const std::string & constraint_prefix,
309 const std::string & constraint_type)
311 InputParameters params = _factory.getValidParams(constraint_type +
"<RESIDUAL>");
313 params.set<BoundaryName>(
"master_boundary") =
_master;
314 params.set<BoundaryName>(
"slave_boundary") =
_slave;
315 params.set<SubdomainName>(
"master_subdomain") = master_subdomain_name;
316 params.set<SubdomainName>(
"slave_subdomain") = slave_subdomain_name;
317 params.set<NonlinearVariableName>(
"variable") = variable_name;
318 params.set<
bool>(
"use_displaced_mesh") =
true;
319 params.set<
bool>(
"compute_lm_residuals") =
false;
321 for (
unsigned int i = 0; i < displacements.size(); ++i)
323 std::string constraint_name = constraint_prefix + Moose::stringify(i);
325 params.set<VariableName>(
"slave_variable") = displacements[i];
326 params.set<MooseEnum>(
"component") = i;
328 _problem->addConstraint(
329 constraint_type +
"<RESIDUAL>", constraint_name +
"_residual", params);
330 _problem->addConstraint(
331 constraint_type +
"<JACOBIAN>", constraint_name +
"_jacobian", params);
333 _problem->haveADObjects(
true);
337 addMechanicalContactConstraints(normal_lagrange_multiplier_name,
338 action_name +
"_normal_constraint_",
339 "NormalMortarMechanicalContact");
341 addMechanicalContactConstraints(tangential_lagrange_multiplier_name,
342 action_name +
"_tangential_constraint_",
343 "TangentialMortarMechanicalContact");