https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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");
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{
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())
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
81void
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
108Real
109ContactSlipDamper::computeDamping(const NumericVector<Number> & solution,
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
121 _num_sticking = 0;
122 _num_slipping = 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)
149 else if (info._mech_status == PenetrationInfo::MS_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) &&
166 info._mech_status == PenetrationInfo::MS_SLIPPING_FRICTION)
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
226bool
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}
registerMooseObject("ContactApp", ContactSlipDamper)
const NumericVector< Number > *const & currentSolution() const override
const ConsoleStream _console
Simple constant damper.
MooseSharedPointer< DisplacedProblem > _displaced_problem
virtual void timestepSetup()
static InputParameters validParams()
virtual Real computeDamping(const NumericVector< Number > &solution, const NumericVector< Number > &update)
Compute the amount of damping.
bool operateOnThisInteraction(const PenetrationLocator &pen_loc)
Determine whether the damper should operate on the interaction corresponding to the supplied Penetrat...
std::set< std::pair< int, int > > _interactions
AuxiliarySystem & _aux_sys
ContactSlipDamper(const InputParameters &parameters)
SystemBase & _sys
SubProblem & _subproblem
static InputParameters validParams()
std::map< std::pair< BoundaryID, BoundaryID >, PenetrationLocator * > _penetration_locators
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
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)
void mooseError(Args &&... args) const
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
std::vector< dof_id_type > _secondary_nodes
BoundaryID _secondary_boundary
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
BoundaryID _primary_boundary
NearestNodeLocator & _nearest_node
virtual MooseMesh & mesh()=0
unsigned int number() const
void min(const T &r, T &o, Request &req) const
const Parallel::Communicator & _communicator
processor_id_type processor_id() const