https://mooseframework.inl.gov
ContactSlipDamper.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
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 #include "ContactSlipDamper.h"
11 #include "FEProblem.h"
12 #include "DisplacedProblem.h"
13 #include "AuxiliarySystem.h"
14 #include "PenetrationLocator.h"
15 #include "NearestNodeLocator.h"
16 
18 
21 {
23  params.addParam<std::vector<BoundaryName>>(
24  "primary", "IDs of the primary surfaces for which slip reversals should be damped");
25  params.addParam<std::vector<BoundaryName>>(
26  "secondary", "IDs of the secondary surfaces for which slip reversals should be damped");
27  params.addParam<Real>(
28  "max_iterative_slip", std::numeric_limits<Real>::max(), "Maximum iterative slip");
29  params.addRangeCheckedParam<Real>("min_damping_factor",
30  0.0,
31  "min_damping_factor < 1.0",
32  "Minimum permissible value for damping factor");
33  params.addParam<Real>("damping_threshold_factor",
34  1.0e3,
35  "If previous iterations's slip is below the slip tolerance, "
36  "only damp a slip reversal if the slip magnitude is greater "
37  "than than this factor times the old slip.");
38  params.addParam<bool>("debug_output", false, "Output detailed debugging information");
39  params.addClassDescription(
40  "Damp the iterative solution to minimize oscillations in frictional contact "
41  "constriants between nonlinear iterations");
42  return params;
43 }
44 
46  : GeneralDamper(parameters),
47  _aux_sys(parameters.get<FEProblemBase *>("_fe_problem_base")->getAuxiliarySystem()),
48  _displaced_problem(parameters.get<FEProblemBase *>("_fe_problem_base")->getDisplacedProblem()),
49  _num_contact_nodes(0),
50  _num_sticking(0),
51  _num_slipping(0),
52  _num_slipping_friction(0),
53  _num_stick_locked(0),
54  _num_slip_reversed(0),
55  _max_iterative_slip(parameters.get<Real>("max_iterative_slip")),
56  _min_damping_factor(parameters.get<Real>("min_damping_factor")),
57  _damping_threshold_factor(parameters.get<Real>("damping_threshold_factor")),
58  _debug_output(parameters.get<bool>("debug_output"))
59 {
60  if (!_displaced_problem)
61  mooseError("Must have displaced problem to use ContactSlipDamper");
62 
63  std::vector<BoundaryName> primary = getParam<std::vector<BoundaryName>>("primary");
64  std::vector<BoundaryName> secondary = getParam<std::vector<BoundaryName>>("secondary");
65 
66  unsigned int num_interactions = primary.size();
67  if (num_interactions != secondary.size())
68  mooseError(
69  "Sizes of primary surface and secondary surface lists must match in ContactSlipDamper");
70  if (num_interactions == 0)
71  mooseError("Must define at least one primary/secondary pair in ContactSlipDamper");
72 
73  for (unsigned int i = 0; i < primary.size(); ++i)
74  {
75  std::pair<int, int> ms_pair(_subproblem.mesh().getBoundaryID(primary[i]),
76  _subproblem.mesh().getBoundaryID(secondary[i]));
77  _interactions.insert(ms_pair);
78  }
79 }
80 
81 void
83 {
84  GeometricSearchData & displaced_geom_search_data = _displaced_problem->geomSearchData();
85  const auto & penetration_locators = displaced_geom_search_data._penetration_locators;
86 
87  for (const auto & pl : penetration_locators)
88  {
89  PenetrationLocator & pen_loc = *pl.second;
90 
91  if (operateOnThisInteraction(pen_loc))
92  {
93  for (const auto & secondary_node_num : pen_loc._nearest_node._secondary_nodes)
94  if (pen_loc._penetration_info[secondary_node_num])
95  {
96  PenetrationInfo & info = *pen_loc._penetration_info[secondary_node_num];
97  const Node & node = _displaced_problem->mesh().nodeRef(secondary_node_num);
98 
99  if (node.processor_id() == processor_id())
100  // && info.isCaptured()) //TODO maybe just set this
101  // everywhere?
102  info._slip_reversed = false;
103  }
104  }
105  }
106 }
107 
108 Real
110  const NumericVector<Number> & /*update*/)
111 {
112  std::map<unsigned int, const NumericVector<Number> *> nl_soln;
113  nl_soln.emplace(_sys.number(), &solution);
114 
115  // Do new contact search to update positions of slipped nodes
116  _displaced_problem->updateMesh(nl_soln, *_aux_sys.currentSolution());
117 
118  Real damping = 1.0;
119 
120  _num_contact_nodes = 0;
121  _num_sticking = 0;
122  _num_slipping = 0;
124  _num_stick_locked = 0;
125  _num_slip_reversed = 0;
126 
127  GeometricSearchData & displaced_geom_search_data = _displaced_problem->geomSearchData();
128  const auto & penetration_locators = displaced_geom_search_data._penetration_locators;
129 
130  for (const auto & pl : penetration_locators)
131  {
132  PenetrationLocator & pen_loc = *pl.second;
133 
134  if (operateOnThisInteraction(pen_loc))
135  {
136  for (const auto & secondary_node_num : pen_loc._nearest_node._secondary_nodes)
137  if (pen_loc._penetration_info[secondary_node_num])
138  {
139  PenetrationInfo & info = *pen_loc._penetration_info[secondary_node_num];
140  const Node & node = _displaced_problem->mesh().nodeRef(secondary_node_num);
141 
142  if (node.processor_id() == processor_id())
143  {
144  if (info.isCaptured())
145  {
147  if (info._mech_status == PenetrationInfo::MS_STICKING)
148  _num_sticking++;
149  else if (info._mech_status == PenetrationInfo::MS_SLIPPING)
150  _num_slipping++;
151  else if (info._mech_status == PenetrationInfo::MS_SLIPPING_FRICTION)
153  if (info._stick_locked_this_step >= 2) // TODO get from contact interaction
155 
156  RealVectorValue tangential_inc_slip_prev_iter =
157  info._incremental_slip_prev_iter -
158  (info._incremental_slip_prev_iter * info._normal) * info._normal;
159  RealVectorValue tangential_inc_slip =
160  info._incremental_slip - (info._incremental_slip * info._normal) * info._normal;
161 
162  RealVectorValue tangential_it_slip =
163  tangential_inc_slip - tangential_inc_slip_prev_iter;
164  Real node_damping_factor = 1.0;
165  if ((tangential_inc_slip_prev_iter * tangential_inc_slip < 0.0) &&
167  {
168  info._slip_reversed = true;
170  Real prev_iter_slip_mag = tangential_inc_slip_prev_iter.norm();
171  RealVectorValue prev_iter_slip_dir =
172  tangential_inc_slip_prev_iter / prev_iter_slip_mag;
173  Real cur_it_slip_in_old_dir = tangential_it_slip * prev_iter_slip_dir;
174 
175  if (prev_iter_slip_mag > info._slip_tol ||
176  cur_it_slip_in_old_dir > -_damping_threshold_factor * prev_iter_slip_mag)
177  node_damping_factor =
178  1.0 - (cur_it_slip_in_old_dir + prev_iter_slip_mag) / cur_it_slip_in_old_dir;
179 
180  if (node_damping_factor < 0.0)
181  mooseError("Damping factor can't be negative");
182 
183  if (node_damping_factor < _min_damping_factor)
184  node_damping_factor = _min_damping_factor;
185  }
186 
187  if (tangential_it_slip.norm() > _max_iterative_slip)
188  node_damping_factor =
189  (tangential_it_slip.norm() - _max_iterative_slip) / tangential_it_slip.norm();
190 
191  if (_debug_output && node_damping_factor < 1.0)
192  _console << "Damping node: " << node.id()
193  << " prev iter slip: " << info._incremental_slip_prev_iter
194  << " curr iter slip: " << info._incremental_slip
195  << " slip_tol: " << info._slip_tol
196  << " damping factor: " << node_damping_factor << std::endl;
197 
198  if (node_damping_factor < damping)
199  damping = node_damping_factor;
200  }
201  }
202  }
203  }
204  }
205  _console << std::flush;
212  _communicator.min(damping);
213 
214  _console << " ContactSlipDamper: Damping #Cont #Stick #Slip #SlipFric #StickLock "
215  "#SlipRev\n";
216 
217  _console << std::right << std::setw(29) << damping << std::setw(10) << _num_contact_nodes
218  << std::setw(10) << _num_sticking << std::setw(10) << _num_slipping << std::setw(10)
219  << _num_slipping_friction << std::setw(11) << _num_stick_locked << std::setw(10)
220  << _num_slip_reversed << "\n\n";
221  _console << std::flush;
222 
223  return damping;
224 }
225 
226 bool
228 {
229  bool operate_on_this_interaction = false;
230  std::set<std::pair<int, int>>::iterator ipit;
231  std::pair<int, int> ms_pair(pen_loc._primary_boundary, pen_loc._secondary_boundary);
232  ipit = _interactions.find(ms_pair);
233  if (ipit != _interactions.end())
234  operate_on_this_interaction = true;
235  return operate_on_this_interaction;
236 }
virtual MooseMesh & mesh()=0
virtual Real computeDamping(const NumericVector< Number > &solution, const NumericVector< Number > &update)
Compute the amount of damping.
std::map< std::pair< BoundaryID, BoundaryID >, PenetrationLocator *> _penetration_locators
std::set< std::pair< int, int > > _interactions
auto norm() const -> decltype(std::norm(Real()))
static InputParameters validParams()
virtual void timestepSetup()
BoundaryID _secondary_boundary
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
MPI_Info info
static InputParameters validParams()
const NumericVector< Number > *const & currentSolution() const override
registerMooseObject("ContactApp", ContactSlipDamper)
const Parallel::Communicator & _communicator
Simple constant damper.
std::map< dof_id_type, PenetrationInfo *> & _penetration_info
std::vector< dof_id_type > _secondary_nodes
void min(const T &r, T &o, Request &req) const
MooseSharedPointer< DisplacedProblem > _displaced_problem
unsigned int number() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
ContactSlipDamper(const InputParameters &parameters)
const ConsoleStream _console
AuxiliarySystem & _aux_sys
SubProblem & _subproblem
processor_id_type processor_id() const
bool operateOnThisInteraction(const PenetrationLocator &pen_loc)
Determine whether the damper should operate on the interaction corresponding to the supplied Penetrat...
SystemBase & _sys
const Elem & get(const ElemType type_in)
BoundaryID _primary_boundary
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
NearestNodeLocator & _nearest_node