11 #include "PenetrationLocator.h"
12 #include "PenetrationInfo.h"
13 #include "SystemBase.h"
16 #include "DualRealOps.h"
18 using MetaPhysicL::DualNumber;
26 InputParameters params = validParams<NodeFaceConstraint>();
27 params.set<
bool>(
"use_displaced_mesh") =
true;
29 params.addCoupledVar(
"disp_y",
"The y displacement");
30 params.addCoupledVar(
"disp_z",
"The z displacement");
31 params.addParam<Real>(
"c", 1,
"Parameter for balancing the size of the gap and contact pressure");
33 MooseEnum ncp_function_type(
"min fb",
"min");
34 params.addParam<MooseEnum>(
35 "ncp_function_type", ncp_function_type,
"The type of NCP function to use");
37 params.addClassDescription(
"Implements the KKT conditions for normal contact using an NCP "
38 "function. Requires that either the gap distance or the normal "
39 "contact pressure (represented by the value of `variable`) is zero. "
40 "The LM variable must be of the same order as the mesh");
45 : NodeFaceConstraint(parameters),
46 _disp_y_id(coupled(
"disp_y")),
47 _disp_z_id(coupled(
"disp_z")),
48 _c(getParam<Real>(
"c")),
49 _epsilon(std::numeric_limits<Real>::epsilon()),
50 _ncp_type(getParam<MooseEnum>(
"ncp_function_type"))
53 _overwrite_slave_residual =
false;
65 DenseVector<Number> & re = _assembly.residualBlock(_var.number());
76 _connected_dof_indices.clear();
77 _connected_dof_indices.push_back(_var.nodalDofIndex());
87 if (jvar == _var.number())
93 MooseVariableFEBase & var = _sys.getVariable(0, jvar);
94 _connected_dof_indices.clear();
95 _connected_dof_indices.push_back(var.nodalDofIndex());
102 DenseMatrix<Number> & Ken =
103 _assembly.jacobianBlockNeighbor(Moose::ElementNeighbor, _var.number(), jvar);
105 for (_j = 0; _j < _phi_master.size(); ++_j)
111 std::map<dof_id_type, PenetrationInfo *>::iterator found =
112 _penetration_locator._penetration_info.find(_current_node->id());
113 if (found != _penetration_locator._penetration_info.end())
115 PenetrationInfo * pinfo = found->second;
118 Real a = -pinfo->_distance *
_c;
120 _qp < _u_slave.size(),
121 "qp is greater than the size of u_slave in NormalNodalLMMechanicalContact. Check and "
122 "make sure that your Lagrange multiplier variable has the same order as the mesh");
123 Real b = _u_slave[_qp];
126 return a + b - std::sqrt(a * a + b * b +
_epsilon);
128 return std::min(a, b);
139 std::map<dof_id_type, PenetrationInfo *>::iterator found =
140 _penetration_locator._penetration_info.find(_current_node->id());
141 if (found != _penetration_locator._penetration_info.end())
143 PenetrationInfo * pinfo = found->second;
146 DualNumber<Real, Real> dual_u_slave(_u_slave[_qp]);
147 dual_u_slave.derivatives() = 1.;
149 auto a = -pinfo->_distance *
_c;
150 auto b = dual_u_slave;
153 return (a + b - std::sqrt(a * a + b * b +
_epsilon)).derivatives();
155 return std::min(a, b).derivatives();
165 std::map<dof_id_type, PenetrationInfo *>::iterator found =
166 _penetration_locator._penetration_info.find(_current_node->id());
167 if (found != _penetration_locator._penetration_info.end())
169 PenetrationInfo * pinfo = found->second;
172 DualNumber<Real, Real> gap(-pinfo->_distance);
175 if (jvar == _master_var_num)
184 gap.derivatives() = pinfo->_normal(comp);
188 case Moose::SlaveSlave:
189 gap.derivatives() *= 1;
191 case Moose::SlaveMaster:
192 gap.derivatives() *= -_phi_master[_j][_qp];
195 mooseError(
"LMs do not have a master contribution.");
199 auto b = _u_slave[_qp];
202 return (a + b - std::sqrt(a * a + b * b +
_epsilon)).derivatives();
204 return std::min(a, b).derivatives();