www.mooseframework.org
TangentialNodalLMMechanicalContact.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "PenetrationLocator.h"
12 #include "PenetrationInfo.h"
13 #include "SystemBase.h"
14 #include "Assembly.h"
15 
16 #include "DualRealOps.h"
17 
19 
20 template <>
21 InputParameters
23 {
24  InputParameters params = validParams<NodeFaceConstraint>();
25  params.set<bool>("use_displaced_mesh") = true;
26 
27  params.addRequiredCoupledVar(
28  "contact_pressure",
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.");
32 
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");
36 
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.");
41 
42  params.addRequiredParam<Real>("mu", "The friction coefficient for the Coulomb friction law");
43 
44  params.addParam<Real>(
45  "k_abs",
46  10,
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");
49  return params;
50 }
51 
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()),
61 
62  _mu(getParam<Real>("mu")),
63  _epsilon(std::numeric_limits<Real>::epsilon()),
64  _ncp_type(getParam<MooseEnum>("ncp_function_type"))
65 {
66  _overwrite_slave_residual = false;
67 }
68 
69 Real
71 {
72  return _u_slave[_qp];
73 }
74 
75 void
77 {
78  DenseVector<Number> & re = _assembly.residualBlock(_var.number());
79 
80  _qp = 0;
81 
82  re(0) = computeQpResidual(Moose::Slave);
83 }
84 
85 void
87 {
88  _Kee.resize(1, 1);
89  _connected_dof_indices.clear();
90  _connected_dof_indices.push_back(_var.nodalDofIndex());
91 
92  _qp = 0;
93 
94  _Kee(0, 0) += computeQpJacobian(Moose::SlaveSlave);
95 }
96 
97 void
99 {
100  if (jvar == _var.number())
101  {
102  computeJacobian();
103  return;
104  }
105 
106  MooseVariableFEBase & var = _sys.getVariable(0, jvar);
107  _connected_dof_indices.clear();
108  _connected_dof_indices.push_back(var.nodalDofIndex());
109 
110  _qp = 0;
111 
112  _Kee.resize(1, 1);
113  _Kee(0, 0) += computeQpOffDiagJacobian(Moose::SlaveSlave, jvar);
114 }
115 
116 Real TangentialNodalLMMechanicalContact::computeQpResidual(Moose::ConstraintType /*type*/)
117 {
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())
121  {
122  PenetrationInfo * pinfo = found->second;
123  if (pinfo != NULL)
124  {
126  return _u_slave[_qp];
127  else
128  {
129  RealVectorValue tangent_vec(pinfo->_normal(1), -pinfo->_normal(0), 0);
130  Real v_dot_tan = RealVectorValue(_disp_x_dot, _disp_y_dot, 0) * tangent_vec;
131 
132  // NCP part 1: requirement that either there is no slip **or** slip velocity and
133  // frictional force exerted **by** the slave side are in the same direction
134  Real a;
135  if (v_dot_tan * _u_slave[_qp] < 0)
136  a = -std::abs(v_dot_tan);
137  else
138  a = std::abs(v_dot_tan);
139 
140  // NCP part 2: require that the frictional force can never exceed the frictional
141  // coefficient times the normal force.
142  auto b = _mu * _contact_pressure - std::abs(_u_slave[_qp]);
143 
144  if (_ncp_type == "fb")
145  return a + b - std::sqrt(a * a + b * b + _epsilon);
146  else
147  return std::min(a, b);
148  }
149  }
150  }
151  return 0;
152 }
153 
154 Real TangentialNodalLMMechanicalContact::computeQpJacobian(Moose::ConstraintJacobianType /*type*/)
155 {
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())
159  {
160  PenetrationInfo * pinfo = found->second;
161  if (pinfo != NULL)
162  {
164  return 1.;
165  else
166  {
167  RealVectorValue tangent_vec(pinfo->_normal(1), -pinfo->_normal(0), 0);
168  Real v_dot_tan = RealVectorValue(_disp_x_dot, _disp_y_dot, 0) * tangent_vec;
169 
170  // NCP part 1: requirement that either there is no slip **or** slip velocity and
171  // frictional force exerted **by** the slave side are in the same direction
172  Real a;
173  if (v_dot_tan * _u_slave[_qp] < 0)
174  a = -std::abs(v_dot_tan);
175  else
176  a = std::abs(v_dot_tan);
177 
178  // NCP part 2: require that the frictional force can never exceed the frictional
179  // coefficient times the normal force.
180  DualNumber<Real, Real> dual_u_slave(_u_slave[_qp]);
181  dual_u_slave.derivatives() = 1;
182 
183  auto b = _mu * _contact_pressure - std::abs(dual_u_slave);
184 
185  if (_ncp_type == "fb")
186  return (a + b - std::sqrt(a * a + b * b + _epsilon)).derivatives();
187  else
188  return std::min(a, b).derivatives();
189  }
190  }
191  }
192  return 0;
193 }
194 
195 Real
197  unsigned jvar)
198 {
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())
202  {
203  PenetrationInfo * pinfo = found->second;
204  if (pinfo != NULL)
205  {
207  return 0.;
208 
209  // Our local dual number is going to depend on only three degrees of freedom: the slave nodal
210  // dofs for disp_x (index 0), disp_y (index 1), and the contact pressure (index 2). The latter
211  // of course exists only on the slave side
212  typedef DualNumber<Real, DNDerivativeSize<3>> LocalDN;
213 
214  RealVectorValue tangent_vec(pinfo->_normal(1), -pinfo->_normal(0), 0);
215 
216  LocalDN dual_disp_x_dot(_disp_x_dot);
217  // We index the zeroth entry of the _du_dot_du member variable because there is only one
218  // degree of freedom on the node
219  Moose::derivInsert(dual_disp_x_dot.derivatives(), 0, _du_dot_du[0]);
220 
221  LocalDN dual_disp_y_dot(_disp_y_dot);
222  Moose::derivInsert(dual_disp_y_dot.derivatives(), 1, _du_dot_du[0]);
223 
224  LocalDN dual_contact_pressure(_contact_pressure);
225  Moose::derivInsert(dual_contact_pressure.derivatives(), 2, 1);
226 
227  auto v_dot_tan = VectorValue<LocalDN>(dual_disp_x_dot, dual_disp_y_dot, 0) * tangent_vec;
228 
229  // NCP part 1: requirement that either there is no slip **or** slip velocity and
230  // frictional force exerted **by** the slave side are in the same direction
231  LocalDN a;
232  if (v_dot_tan * _u_slave[_qp] < 0)
233  a = -std::abs(v_dot_tan);
234  else
235  a = std::abs(v_dot_tan);
236 
237  // NCP part 2: require that the frictional force can never exceed the frictional
238  // coefficient times the normal force.
239  auto b = _mu * dual_contact_pressure - std::abs(_u_slave[_qp]);
240 
241  LocalDN ncp_value;
242  if (_ncp_type == "fb")
243  ncp_value = a + b - std::sqrt(a * a + b * b + _epsilon);
244  else
245  ncp_value = std::min(a, b);
246 
247  if (jvar == _contact_pressure_id)
248  return ncp_value.derivatives()[2];
249  else if (jvar == _master_var.number())
250  return ncp_value.derivatives()[0];
251  else if (jvar == _disp_y_id)
252  return ncp_value.derivatives()[1];
253  }
254  }
255  return 0.;
256 }
TangentialNodalLMMechanicalContact::computeQpJacobian
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type) override
Definition: TangentialNodalLMMechanicalContact.C:154
TangentialNodalLMMechanicalContact::computeQpOffDiagJacobian
virtual Real computeQpOffDiagJacobian(Moose::ConstraintJacobianType type, unsigned jvar) override
Definition: TangentialNodalLMMechanicalContact.C:196
TangentialNodalLMMechanicalContact::computeJacobian
virtual void computeJacobian() override
Definition: TangentialNodalLMMechanicalContact.C:86
TangentialNodalLMMechanicalContact::_mu
const Real _mu
Definition: TangentialNodalLMMechanicalContact.h:47
TangentialNodalLMMechanicalContact::computeQpSlaveValue
virtual Real computeQpSlaveValue() override
Definition: TangentialNodalLMMechanicalContact.C:70
TangentialNodalLMMechanicalContact::computeResidual
virtual void computeResidual() override
Definition: TangentialNodalLMMechanicalContact.C:76
TangentialNodalLMMechanicalContact::_contact_pressure_id
const unsigned _contact_pressure_id
Definition: TangentialNodalLMMechanicalContact.h:38
TangentialNodalLMMechanicalContact::TangentialNodalLMMechanicalContact
TangentialNodalLMMechanicalContact(const InputParameters &parameters)
Definition: TangentialNodalLMMechanicalContact.C:52
TangentialNodalLMMechanicalContact.h
registerMooseObject
registerMooseObject("ContactApp", TangentialNodalLMMechanicalContact)
TangentialNodalLMMechanicalContact::_contact_pressure
const Real & _contact_pressure
Definition: TangentialNodalLMMechanicalContact.h:37
TangentialNodalLMMechanicalContact
Definition: TangentialNodalLMMechanicalContact.h:21
TangentialNodalLMMechanicalContact::_disp_y_dot
const Real & _disp_y_dot
Definition: TangentialNodalLMMechanicalContact.h:41
TangentialNodalLMMechanicalContact::computeQpResidual
virtual Real computeQpResidual(Moose::ConstraintType type) override
Definition: TangentialNodalLMMechanicalContact.C:116
TangentialNodalLMMechanicalContact::_disp_y_id
const unsigned _disp_y_id
Definition: TangentialNodalLMMechanicalContact.h:43
TangentialNodalLMMechanicalContact::_epsilon
const Real _epsilon
Definition: TangentialNodalLMMechanicalContact.h:48
TangentialNodalLMMechanicalContact::_ncp_type
const MooseEnum _ncp_type
Definition: TangentialNodalLMMechanicalContact.h:50
TangentialNodalLMMechanicalContact::_disp_x_dot
const Real & _disp_x_dot
Definition: TangentialNodalLMMechanicalContact.h:40
TangentialNodalLMMechanicalContact::computeOffDiagJacobian
virtual void computeOffDiagJacobian(unsigned jvar) override
Definition: TangentialNodalLMMechanicalContact.C:98
validParams< TangentialNodalLMMechanicalContact >
InputParameters validParams< TangentialNodalLMMechanicalContact >()
Definition: TangentialNodalLMMechanicalContact.C:22
TangentialNodalLMMechanicalContact::_du_dot_du
const VariableValue & _du_dot_du
Definition: TangentialNodalLMMechanicalContact.h:45