www.mooseframework.org
NormalNodalLMMechanicalContact.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 
18 using MetaPhysicL::DualNumber;
19 
21 
22 template <>
23 InputParameters
25 {
26  InputParameters params = validParams<NodeFaceConstraint>();
27  params.set<bool>("use_displaced_mesh") = true;
28 
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");
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 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");
41  return params;
42 }
43 
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"))
51 
52 {
53  _overwrite_slave_residual = false;
54 }
55 
56 Real
58 {
59  return _u_slave[_qp];
60 }
61 
62 void
64 {
65  DenseVector<Number> & re = _assembly.residualBlock(_var.number());
66 
67  _qp = 0;
68 
69  re(0) = computeQpResidual(Moose::Slave);
70 }
71 
72 void
74 {
75  _Kee.resize(1, 1);
76  _connected_dof_indices.clear();
77  _connected_dof_indices.push_back(_var.nodalDofIndex());
78 
79  _qp = 0;
80 
81  _Kee(0, 0) += computeQpJacobian(Moose::SlaveSlave);
82 }
83 
84 void
86 {
87  if (jvar == _var.number())
88  {
90  return;
91  }
92 
93  MooseVariableFEBase & var = _sys.getVariable(0, jvar);
94  _connected_dof_indices.clear();
95  _connected_dof_indices.push_back(var.nodalDofIndex());
96 
97  _qp = 0;
98 
99  _Kee.resize(1, 1);
100  _Kee(0, 0) += computeQpOffDiagJacobian(Moose::SlaveSlave, jvar);
101 
102  DenseMatrix<Number> & Ken =
103  _assembly.jacobianBlockNeighbor(Moose::ElementNeighbor, _var.number(), jvar);
104 
105  for (_j = 0; _j < _phi_master.size(); ++_j)
106  Ken(0, _j) += computeQpOffDiagJacobian(Moose::SlaveMaster, jvar);
107 }
108 
109 Real NormalNodalLMMechanicalContact::computeQpResidual(Moose::ConstraintType /*type*/)
110 {
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())
114  {
115  PenetrationInfo * pinfo = found->second;
116  if (pinfo != NULL)
117  {
118  Real a = -pinfo->_distance * _c;
119  mooseAssert(
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];
124 
125  if (_ncp_type == "fb")
126  return a + b - std::sqrt(a * a + b * b + _epsilon);
127  else
128  return std::min(a, b);
129  }
130  }
131  return 0;
132 }
133 
134 // Note that the Jacobians below are inexact. To really make them exact, the most algorithmically
135 // rigorous way will be to accomplish libmesh/libmesh#2121
136 
137 Real NormalNodalLMMechanicalContact::computeQpJacobian(Moose::ConstraintJacobianType /*type*/)
138 {
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())
142  {
143  PenetrationInfo * pinfo = found->second;
144  if (pinfo != NULL)
145  {
146  DualNumber<Real, Real> dual_u_slave(_u_slave[_qp]);
147  dual_u_slave.derivatives() = 1.;
148 
149  auto a = -pinfo->_distance * _c;
150  auto b = dual_u_slave;
151 
152  if (_ncp_type == "fb")
153  return (a + b - std::sqrt(a * a + b * b + _epsilon)).derivatives();
154  else
155  return std::min(a, b).derivatives();
156  }
157  }
158  return 0;
159 }
160 
161 Real
163  unsigned jvar)
164 {
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())
168  {
169  PenetrationInfo * pinfo = found->second;
170  if (pinfo != NULL)
171  {
172  DualNumber<Real, Real> gap(-pinfo->_distance);
173 
174  unsigned comp;
175  if (jvar == _master_var_num)
176  comp = 0;
177  else if (jvar == _disp_y_id)
178  comp = 1;
179  else if (jvar == _disp_z_id)
180  comp = 2;
181  else
182  return 0;
183 
184  gap.derivatives() = pinfo->_normal(comp);
185 
186  switch (type)
187  {
188  case Moose::SlaveSlave:
189  gap.derivatives() *= 1;
190  break;
191  case Moose::SlaveMaster:
192  gap.derivatives() *= -_phi_master[_j][_qp];
193  break;
194  default:
195  mooseError("LMs do not have a master contribution.");
196  }
197 
198  auto a = gap * _c;
199  auto b = _u_slave[_qp];
200 
201  if (_ncp_type == "fb")
202  return (a + b - std::sqrt(a * a + b * b + _epsilon)).derivatives();
203  else
204  return std::min(a, b).derivatives();
205  }
206  }
207  return 0.;
208 }
NormalNodalLMMechanicalContact::_disp_z_id
const unsigned _disp_z_id
Definition: NormalNodalLMMechanicalContact.h:38
NormalNodalLMMechanicalContact::computeQpOffDiagJacobian
virtual Real computeQpOffDiagJacobian(Moose::ConstraintJacobianType type, unsigned jvar) override
Definition: NormalNodalLMMechanicalContact.C:162
NormalNodalLMMechanicalContact::_epsilon
const Real _epsilon
Definition: NormalNodalLMMechanicalContact.h:40
NormalNodalLMMechanicalContact.h
NormalNodalLMMechanicalContact::NormalNodalLMMechanicalContact
NormalNodalLMMechanicalContact(const InputParameters &parameters)
Definition: NormalNodalLMMechanicalContact.C:44
NormalNodalLMMechanicalContact::computeResidual
virtual void computeResidual() override
Definition: NormalNodalLMMechanicalContact.C:63
NormalNodalLMMechanicalContact::computeJacobian
virtual void computeJacobian() override
Definition: NormalNodalLMMechanicalContact.C:73
NormalNodalLMMechanicalContact::_disp_y_id
const unsigned _disp_y_id
Definition: NormalNodalLMMechanicalContact.h:37
registerMooseObject
registerMooseObject("MooseApp", NormalNodalLMMechanicalContact)
NormalNodalLMMechanicalContact::computeQpJacobian
virtual Real computeQpJacobian(Moose::ConstraintJacobianType type) override
Definition: NormalNodalLMMechanicalContact.C:137
NormalNodalLMMechanicalContact::_ncp_type
const MooseEnum _ncp_type
Definition: NormalNodalLMMechanicalContact.h:42
NormalNodalLMMechanicalContact::computeQpSlaveValue
virtual Real computeQpSlaveValue() override
Definition: NormalNodalLMMechanicalContact.C:57
NormalNodalLMMechanicalContact::computeQpResidual
virtual Real computeQpResidual(Moose::ConstraintType type) override
Definition: NormalNodalLMMechanicalContact.C:109
NormalNodalLMMechanicalContact
Definition: NormalNodalLMMechanicalContact.h:21
NormalNodalLMMechanicalContact::computeOffDiagJacobian
virtual void computeOffDiagJacobian(unsigned jvar) override
Definition: NormalNodalLMMechanicalContact.C:85
validParams< NormalNodalLMMechanicalContact >
InputParameters validParams< NormalNodalLMMechanicalContact >()
Definition: NormalNodalLMMechanicalContact.C:24
NormalNodalLMMechanicalContact::_c
const Real _c
Definition: NormalNodalLMMechanicalContact.h:39