11 #include "PenetrationLocator.h"
12 #include "PenetrationInfo.h"
13 #include "SystemBase.h"
16 #include "DualRealOps.h"
24 InputParameters params = validParams<NodeFaceConstraint>();
25 params.set<
bool>(
"use_displaced_mesh") =
true;
27 params.addRequiredCoupledVar(
29 "The contact pressure. If using LM, this should be the normal lagrange multiplier");
30 params.addRequiredCoupledVar(
"disp_y",
"The y velocity");
31 params.addRequiredParam<Real>(
"mu",
"The coefficient of friction.");
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 frictional Coulomb contact using "
38 "an NCP function. Requires that either the relative tangential "
39 "velocity is zero or the tangential stress is equal to the friction "
40 "coefficient times the normal contact pressure.");
42 params.addRequiredParam<Real>(
"mu",
"The friction coefficient for the Coulomb friction law");
44 params.addParam<Real>(
47 "The smoothing parameter for the function used to approximate std::abs. The approximating "
48 "function is courtesy of https://math.stackexchange.com/a/1115033/408963");
53 const InputParameters & parameters)
54 : NodeFaceConstraint(parameters),
55 _contact_pressure(getVar(
"contact_pressure", 0)->nodalValue()),
56 _contact_pressure_id(coupled(
"contact_pressure")),
57 _disp_x_dot(_master_var.nodalValueDot()),
58 _disp_y_dot(getVar(
"disp_y", 0)->nodalValueDot()),
59 _disp_y_id(coupled(
"disp_y")),
60 _du_dot_du(_master_var.dofValuesDuDotDu()),
62 _mu(getParam<Real>(
"mu")),
63 _epsilon(std::numeric_limits<Real>::epsilon()),
64 _ncp_type(getParam<MooseEnum>(
"ncp_function_type"))
66 _overwrite_slave_residual =
false;
78 DenseVector<Number> & re = _assembly.residualBlock(_var.number());
89 _connected_dof_indices.clear();
90 _connected_dof_indices.push_back(_var.nodalDofIndex());
100 if (jvar == _var.number())
106 MooseVariableFEBase & var = _sys.getVariable(0, jvar);
107 _connected_dof_indices.clear();
108 _connected_dof_indices.push_back(var.nodalDofIndex());
118 std::map<dof_id_type, PenetrationInfo *>::iterator found =
119 _penetration_locator._penetration_info.find(_current_node->id());
120 if (found != _penetration_locator._penetration_info.end())
122 PenetrationInfo * pinfo = found->second;
126 return _u_slave[_qp];
129 RealVectorValue tangent_vec(pinfo->_normal(1), -pinfo->_normal(0), 0);
135 if (v_dot_tan * _u_slave[_qp] < 0)
136 a = -std::abs(v_dot_tan);
138 a = std::abs(v_dot_tan);
145 return a + b - std::sqrt(a * a + b * b +
_epsilon);
147 return std::min(a, b);
156 std::map<dof_id_type, PenetrationInfo *>::iterator found =
157 _penetration_locator._penetration_info.find(_current_node->id());
158 if (found != _penetration_locator._penetration_info.end())
160 PenetrationInfo * pinfo = found->second;
167 RealVectorValue tangent_vec(pinfo->_normal(1), -pinfo->_normal(0), 0);
173 if (v_dot_tan * _u_slave[_qp] < 0)
174 a = -std::abs(v_dot_tan);
176 a = std::abs(v_dot_tan);
180 DualNumber<Real, Real> dual_u_slave(_u_slave[_qp]);
181 dual_u_slave.derivatives() = 1;
186 return (a + b - std::sqrt(a * a + b * b +
_epsilon)).derivatives();
188 return std::min(a, b).derivatives();
199 std::map<dof_id_type, PenetrationInfo *>::iterator found =
200 _penetration_locator._penetration_info.find(_current_node->id());
201 if (found != _penetration_locator._penetration_info.end())
203 PenetrationInfo * pinfo = found->second;
212 typedef DualNumber<Real, DNDerivativeSize<3>> LocalDN;
214 RealVectorValue tangent_vec(pinfo->_normal(1), -pinfo->_normal(0), 0);
219 Moose::derivInsert(dual_disp_x_dot.derivatives(), 0,
_du_dot_du[0]);
222 Moose::derivInsert(dual_disp_y_dot.derivatives(), 1,
_du_dot_du[0]);
225 Moose::derivInsert(dual_contact_pressure.derivatives(), 2, 1);
227 auto v_dot_tan = VectorValue<LocalDN>(dual_disp_x_dot, dual_disp_y_dot, 0) * tangent_vec;
232 if (v_dot_tan * _u_slave[_qp] < 0)
233 a = -std::abs(v_dot_tan);
235 a = std::abs(v_dot_tan);
239 auto b =
_mu * dual_contact_pressure - std::abs(_u_slave[_qp]);
243 ncp_value = a + b - std::sqrt(a * a + b * b +
_epsilon);
245 ncp_value = std::min(a, b);
248 return ncp_value.derivatives()[2];
249 else if (jvar == _master_var.number())
250 return ncp_value.derivatives()[0];
252 return ncp_value.derivatives()[1];