www.mooseframework.org
MultiDContactConstraint.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 
10 // MOOSE includes
12 #include "SystemBase.h"
13 #include "PenetrationLocator.h"
14 #include "MooseMesh.h"
15 #include "ContactAction.h"
16 
17 #include "libmesh/string_to_enum.h"
18 #include "libmesh/sparse_matrix.h"
19 
21 
22 template <>
23 InputParameters
25 {
26  InputParameters params = validParams<NodeFaceConstraint>();
27  params.set<bool>("use_displaced_mesh") = true;
28  params.addParam<bool>("jacobian_update",
29  false,
30  "Whether or not to update the 'in contact' list "
31  "every jacobian evaluation (by default it will "
32  "happen once per timestep");
33 
34  params.addRequiredParam<unsigned int>("component",
35  "An integer corresponding to the direction "
36  "the variable this kernel acts in. (0 for x, "
37  "1 for y, 2 for z)");
38  params.addCoupledVar("disp_x", "The x displacement");
39  params.addCoupledVar("disp_y", "The y displacement");
40  params.addCoupledVar("disp_z", "The z displacement");
41 
42  params.addCoupledVar(
43  "displacements",
44  "The displacements appropriate for the simulation geometry and coordinate system");
45 
46  params.addParam<MooseEnum>("model", ContactAction::getModelEnum(), "The contact model to use");
47  params.addParam<Real>(
48  "penalty",
49  1e8,
50  "The penalty to apply. This can vary depending on the stiffness of your materials");
51 
52  // TODO: Reenable this
53  // params.addParam<std::string>("order", "FIRST", "The finite element order");
54 
55  return params;
56 }
57 
58 MultiDContactConstraint::MultiDContactConstraint(const InputParameters & parameters)
59  : NodeFaceConstraint(parameters),
60  _residual_copy(_sys.residualGhosted()),
61  _jacobian_update(getParam<bool>("jacobian_update")),
62  _component(getParam<unsigned int>("component")),
63  _model(getParam<MooseEnum>("model").getEnum<ContactModel>()),
64  _penalty(getParam<Real>("penalty")),
65  _mesh_dimension(_mesh.dimension()),
66  _vars(3, libMesh::invalid_uint)
67 {
68  _overwrite_slave_residual = false;
69 
70  if (isParamValid("displacements"))
71  {
72  // modern parameter scheme for displacements
73  for (unsigned int i = 0; i < coupledComponents("displacements"); ++i)
74  _vars[i] = coupled("displacements", i);
75  }
76  else
77  {
78  // Legacy parameter scheme for displacements
79  if (isParamValid("disp_x"))
80  _vars[0] = coupled("disp_x");
81  if (isParamValid("disp_y"))
82  _vars[1] = coupled("disp_y");
83  if (isParamValid("disp_z"))
84  _vars[2] = coupled("disp_z");
85 
86  mooseDeprecated("use the `displacements` parameter rather than the `disp_*` parameters (those "
87  "will go away with the deprecation of the Solid Mechanics module).");
88  }
89 }
90 
91 void
93 {
94  if (_component == 0)
96 }
97 
98 void
100 {
101  if (_component == 0)
103 }
104 
105 void
107 {
108  auto & has_penetrated = _penetration_locator._has_penetrated;
109 
110  for (auto & pinfo_pair : _penetration_locator._penetration_info)
111  {
112  PenetrationInfo * pinfo = pinfo_pair.second;
113 
114  // Skip this pinfo if there are no DOFs on this node.
115  if (!pinfo || pinfo->_node->n_comp(_sys.number(), _vars[_component]) < 1)
116  continue;
117 
118  const Node * node = pinfo->_node;
119 
120  dof_id_type slave_node_num = pinfo_pair.first;
121  auto hpit = has_penetrated.find(slave_node_num);
122 
123  RealVectorValue res_vec;
124  // Build up residual vector
125  for (unsigned int i = 0; i < _mesh_dimension; ++i)
126  {
127  dof_id_type dof_number = node->dof_number(0, _vars[i], 0);
128  res_vec(i) = _residual_copy(dof_number);
129  }
130 
131  // Real resid = 0;
132  switch (_model)
133  {
135  // resid = pinfo->_normal * res_vec;
136  break;
137 
138  case ContactModel::GLUED:
139  // resid = pinfo->_normal * res_vec;
140  break;
141 
142  default:
143  mooseError("Invalid or unavailable contact model");
144  break;
145  }
146 
147  // if (hpit != has_penetrated.end() && resid < 0)
148  // Moose::err << resid << std::endl;
149  //
150  // if (hpit != has_penetrated.end() && resid < -.15)
151  // {
152  // Moose::err << std::endl
153  // << "Unlocking node " << node->id()
154  // << " because resid:
155  // "<<resid<<std::endl<<std::endl;
156  //
157  // has_penetrated.erase(hpit);
158  // unlocked_this_step[slave_node_num] = true;
159  // }
160  // else
161 
162  if (pinfo->_distance > 0 &&
163  hpit == has_penetrated.end()) // && !unlocked_this_step[slave_node_num])
164  {
165  // Moose::err << std::endl
166  // << "Locking node " << node->id() << " because distance:" << pinfo->_distance
167  // << std::endl
168  // << std::endl;
169 
170  has_penetrated.insert(slave_node_num);
171  }
172  }
173 }
174 
175 bool
177 {
178  std::set<dof_id_type>::iterator hpit =
179  _penetration_locator._has_penetrated.find(_current_node->id());
180  return (hpit != _penetration_locator._has_penetrated.end());
181 }
182 
183 Real
185 {
186  PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()];
187 
188  // Moose::err << std::endl
189  // << "Popping out node: " << _current_node->id() << std::endl
190  // << "Closest Point " << _component << ": " << pinfo->_closest_point(_component)
191  // << std::endl
192  // << "Current Node " << _component << ": " << (*_current_node)(_component) <<
193  // std::endl
194  // << "Current Value: " << _u_slave[_qp] << std::endl
195  // << "New Value: "
196  // << pinfo->_closest_point(_component) - ((*_current_node)(_component)-_u_slave[_qp])
197  // << std::endl
198  // << "Change: "
199  // << _u_slave[_qp] - (pinfo->_closest_point(_component) -
200  // ((*_current_node)(_component)-_u_slave[_qp]))
201  // << std::endl
202  // << std::endl;
203 
204  return pinfo->_closest_point(_component) - ((*_current_node)(_component)-_u_slave[_qp]);
205 }
206 
207 Real
209 {
210  PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()];
211  const Node * node = pinfo->_node;
212 
213  RealVectorValue res_vec;
214  // Build up residual vector
215  for (unsigned int i = 0; i < _mesh_dimension; ++i)
216  {
217  dof_id_type dof_number = node->dof_number(0, _vars[i], 0);
218  res_vec(i) = _residual_copy(dof_number);
219  }
220 
221  const RealVectorValue distance_vec(_mesh.nodeRef(node->id()) - pinfo->_closest_point);
222  const RealVectorValue pen_force(_penalty * distance_vec);
223  Real resid = 0.0;
224 
225  switch (type)
226  {
227  case Moose::Slave:
228  switch (_model)
229  {
231  resid = pinfo->_normal(_component) * (pinfo->_normal * (pen_force - res_vec));
232  break;
233 
234  case ContactModel::GLUED:
235  resid = pen_force(_component) - res_vec(_component);
236  break;
237 
238  default:
239  mooseError("Invalid or unavailable contact model");
240  break;
241  }
242  return _test_slave[_i][_qp] * resid;
243  case Moose::Master:
244  switch (_model)
245  {
247  resid = pinfo->_normal(_component) * (pinfo->_normal * res_vec);
248  break;
249 
250  case ContactModel::GLUED:
251  resid = res_vec(_component);
252  break;
253 
254  default:
255  mooseError("Invalid or unavailable contact model");
256  break;
257  }
258  return _test_master[_i][_qp] * resid;
259  }
260  return 0.0;
261 }
262 
263 Real
264 MultiDContactConstraint::computeQpJacobian(Moose::ConstraintJacobianType type)
265 {
266  PenetrationInfo * pinfo = _penetration_locator._penetration_info[_current_node->id()];
267 
268  Real slave_jac = 0.0;
269  switch (type)
270  {
271  case Moose::SlaveSlave:
272  switch (_model)
273  {
275 
276  slave_jac = pinfo->_normal(_component) * pinfo->_normal(_component) *
277  (_penalty * _phi_slave[_j][_qp] -
278  (*_jacobian)(_current_node->dof_number(0, _var.number(), 0),
279  _connected_dof_indices[_j]));
280  break;
281 
282  case ContactModel::GLUED:
283  // resid = pen_force(_component) - res_vec(_component);
284  break;
285 
286  default:
287  mooseError("Invalid or unavailable contact model");
288  break;
289  }
290  return _test_slave[_i][_qp] * slave_jac;
291 
292  case Moose::SlaveMaster:
293  switch (_model)
294  {
296 
297  slave_jac = pinfo->_normal(_component) * pinfo->_normal(_component) *
298  (-_penalty * _phi_master[_j][_qp]);
299  break;
300 
301  case ContactModel::GLUED:
302  /*
303  resid = pen_force(_component)
304  - res_vec(_component)
305  ;
306  */
307  break;
308 
309  default:
310  mooseError("Invalid or unavailable contact model");
311  break;
312  }
313  return _test_slave[_i][_qp] * slave_jac;
314 
315  case Moose::MasterSlave:
316  slave_jac =
317  (*_jacobian)(_current_node->dof_number(0, _var.number(), 0), _connected_dof_indices[_j]);
318  return slave_jac * _test_master[_i][_qp];
319 
320  case Moose::MasterMaster:
321  return 0.0;
322 
323  default:
324  mooseError("Unhandled ConstraintJacobianType");
325  }
326  return 0.0;
327 }
ContactModel
ContactModel
Definition: ContactAction.h:16
MultiDContactConstraint::computeQpJacobian
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type)
Definition: MultiDContactConstraint.C:264
validParams< MultiDContactConstraint >
InputParameters validParams< MultiDContactConstraint >()
Definition: MultiDContactConstraint.C:24
MultiDContactConstraint::MultiDContactConstraint
MultiDContactConstraint(const InputParameters &parameters)
Definition: MultiDContactConstraint.C:58
MultiDContactConstraint::_component
const unsigned int _component
Definition: MultiDContactConstraint.h:51
MultiDContactConstraint::timestepSetup
virtual void timestepSetup()
Definition: MultiDContactConstraint.C:92
libMesh
Definition: RANFSNormalMechanicalContact.h:24
MultiDContactConstraint::shouldApply
bool shouldApply()
Definition: MultiDContactConstraint.C:176
MultiDContactConstraint::computeQpSlaveValue
virtual Real computeQpSlaveValue()
Definition: MultiDContactConstraint.C:184
MultiDContactConstraint::_residual_copy
NumericVector< Number > & _residual_copy
Definition: MultiDContactConstraint.h:47
registerMooseObject
registerMooseObject("ContactApp", MultiDContactConstraint)
ContactModel::GLUED
MultiDContactConstraint
A MultiDContactConstraint forces the value of a variable to be the same on both sides of an interface...
Definition: MultiDContactConstraint.h:27
MultiDContactConstraint::_penalty
Real _penalty
Definition: MultiDContactConstraint.h:55
MultiDContactConstraint::_model
const ContactModel _model
Definition: MultiDContactConstraint.h:53
MultiDContactConstraint::computeQpResidual
virtual Real computeQpResidual(Moose::ConstraintType type)
Definition: MultiDContactConstraint.C:208
MultiDContactConstraint::jacobianSetup
virtual void jacobianSetup()
Definition: MultiDContactConstraint.C:99
ContactModel::FRICTIONLESS
MultiDContactConstraint::updateContactSet
virtual void updateContactSet()
Definition: MultiDContactConstraint.C:106
MultiDContactConstraint.h
ContactAction::getModelEnum
static MooseEnum getModelEnum()
Definition: ContactAction.C:417
MultiDContactConstraint::_vars
std::vector< unsigned int > _vars
Definition: MultiDContactConstraint.h:63
MultiDContactConstraint::_mesh_dimension
const unsigned int _mesh_dimension
Definition: MultiDContactConstraint.h:61
ContactAction.h