www.mooseframework.org
GeometricSearchData.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* DO NOT MODIFY THIS HEADER */
3 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
4 /* */
5 /* (c) 2010 Battelle Energy Alliance, LLC */
6 /* ALL RIGHTS RESERVED */
7 /* */
8 /* Prepared by Battelle Energy Alliance, LLC */
9 /* Under Contract No. DE-AC07-05ID14517 */
10 /* With the U. S. Department of Energy */
11 /* */
12 /* See COPYRIGHT for full restrictions */
13 /****************************************************************/
14 
15 #include "GeometricSearchData.h"
16 // Moose includes
17 #include "NearestNodeLocator.h"
18 #include "PenetrationLocator.h"
19 #include "ElementPairLocator.h"
20 #include "SubProblem.h"
21 #include "MooseMesh.h"
22 #include "Assembly.h"
23 
24 static const unsigned int MORTAR_BASE_ID = 2e6;
25 
27  : _subproblem(subproblem), _mesh(mesh), _first(true)
28 {
29 }
30 
32 {
33  for (auto & it : _penetration_locators)
34  delete it.second;
35 
36  for (auto & it : _nearest_node_locators)
37  delete it.second;
38 }
39 
40 void
42 {
43  if (type == ALL || type == QUADRATURE || type == NEAREST_NODE)
44  {
45  if (_first) // Only do this once
46  {
47  _first = false;
48 
49  for (const auto & it : _slave_to_qslave)
50  generateQuadratureNodes(it.first, it.second);
51 
52  // reinit on displaced mesh before update
53  for (const auto & epl_it : _element_pair_locators)
54  {
55  ElementPairLocator & epl = *(epl_it.second);
56  epl.reinit();
57  }
58  }
59 
60  // Update the position of quadrature nodes first
61  for (const auto & qbnd : _quadrature_boundaries)
63  }
64 
65  if (type == ALL || type == MORTAR)
66  if (_mortar_boundaries.size() > 0)
68 
69  if (type == ALL || type == NEAREST_NODE)
70  {
71  for (const auto & nnl_it : _nearest_node_locators)
72  {
73  NearestNodeLocator * nnl = nnl_it.second;
74  nnl->findNodes();
75  }
76  }
77 
78  if (type == ALL || type == PENETRATION)
79  {
80  for (const auto & pl_it : _penetration_locators)
81  {
82  PenetrationLocator * pl = pl_it.second;
83  pl->detectPenetration();
84  }
85  }
86 
87  if (type == ALL || type == PENETRATION)
88  {
89  for (auto & elem_pair_locator_pair : _element_pair_locators)
90  {
91  ElementPairLocator & epl = (*elem_pair_locator_pair.second);
92  epl.update();
93  }
94  }
95 }
96 
97 void
99 {
101  // Update the position of quadrature nodes first
102  for (const auto & qbnd : _quadrature_boundaries)
103  reinitQuadratureNodes(qbnd);
105 
106  for (const auto & nnl_it : _nearest_node_locators)
107  {
108  NearestNodeLocator * nnl = nnl_it.second;
109  nnl->reinit();
110  }
111 
112  for (const auto & pl_it : _penetration_locators)
113  {
114  PenetrationLocator * pl = pl_it.second;
115  pl->reinit();
116  }
117 
118  for (const auto & epl_it : _element_pair_locators)
119  {
120  ElementPairLocator & epl = *(epl_it.second);
121  epl.reinit();
122  }
123 }
124 
125 void
127 {
128  for (const auto & nnl_it : _nearest_node_locators)
129  {
130  NearestNodeLocator * nnl = nnl_it.second;
131  nnl->reinit();
132  }
133 }
134 
135 Real
137 {
138  Real max = 0.0;
139 
140  for (const auto & nnl_it : _nearest_node_locators)
141  {
142  NearestNodeLocator * nnl = nnl_it.second;
143 
144  if (nnl->_max_patch_percentage > max)
145  max = nnl->_max_patch_percentage;
146  }
147 
148  return max;
149 }
150 
152 GeometricSearchData::getPenetrationLocator(const BoundaryName & master,
153  const BoundaryName & slave,
154  Order order)
155 {
156  unsigned int master_id = _mesh.getBoundaryID(master);
157  unsigned int slave_id = _mesh.getBoundaryID(slave);
158 
159  _subproblem.addGhostedBoundary(master_id);
161 
162  PenetrationLocator * pl =
163  _penetration_locators[std::pair<unsigned int, unsigned int>(master_id, slave_id)];
164 
165  if (!pl)
166  {
168  *this,
169  _mesh,
170  master_id,
171  slave_id,
172  order,
173  getNearestNodeLocator(master_id, slave_id));
174  _penetration_locators[std::pair<unsigned int, unsigned int>(master_id, slave_id)] = pl;
175  }
176 
177  return *pl;
178 }
179 
182  const BoundaryName & slave,
183  Order order)
184 {
185  unsigned int master_id = _mesh.getBoundaryID(master);
186  unsigned int slave_id = _mesh.getBoundaryID(slave);
187 
188  _subproblem.addGhostedBoundary(master_id);
190 
191  // Generate a new boundary id
192  // TODO: Make this better!
193  unsigned int base_id = 1e6;
194  unsigned int qslave_id = slave_id + base_id;
195 
196  _slave_to_qslave[slave_id] = qslave_id;
197 
198  PenetrationLocator * pl =
199  _penetration_locators[std::pair<unsigned int, unsigned int>(master_id, qslave_id)];
200 
201  if (!pl)
202  {
204  *this,
205  _mesh,
206  master_id,
207  qslave_id,
208  order,
209  getQuadratureNearestNodeLocator(master_id, slave_id));
210  _penetration_locators[std::pair<unsigned int, unsigned int>(master_id, qslave_id)] = pl;
211  }
212 
213  return *pl;
214 }
215 
218  const BoundaryName & slave,
219  Moose::ConstraintType side_type,
220  Order order)
221 {
222  unsigned int master_id = _mesh.getBoundaryID(master);
223  unsigned int slave_id = _mesh.getBoundaryID(slave);
224 
225  // Generate a new boundary id
226  // TODO: Make this better!
227  unsigned int mortar_boundary_id, boundary_id;
228  switch (side_type)
229  {
230  case Moose::Master:
231  boundary_id = master_id;
232  mortar_boundary_id = MORTAR_BASE_ID + slave_id;
233  _boundary_to_mortarboundary[slave_id] = mortar_boundary_id;
234  break;
235 
236  case Moose::Slave:
237  boundary_id = slave_id;
238  mortar_boundary_id = MORTAR_BASE_ID + master_id;
239  _boundary_to_mortarboundary[master_id] = mortar_boundary_id;
240  break;
241  }
242 
243  PenetrationLocator * pl =
244  _penetration_locators[std::pair<unsigned int, unsigned int>(boundary_id, mortar_boundary_id)];
245  if (!pl)
246  {
248  *this,
249  _mesh,
250  boundary_id,
251  mortar_boundary_id,
252  order,
253  getMortarNearestNodeLocator(master_id, slave_id, side_type));
254  _penetration_locators[std::pair<unsigned int, unsigned int>(boundary_id, mortar_boundary_id)] =
255  pl;
256  }
257 
258  return *pl;
259 }
260 
262 GeometricSearchData::getNearestNodeLocator(const BoundaryName & master, const BoundaryName & slave)
263 {
264  unsigned int master_id = _mesh.getBoundaryID(master);
265  unsigned int slave_id = _mesh.getBoundaryID(slave);
266 
267  _subproblem.addGhostedBoundary(master_id);
269 
270  return getNearestNodeLocator(master_id, slave_id);
271 }
272 
274 GeometricSearchData::getNearestNodeLocator(const unsigned int master_id,
275  const unsigned int slave_id)
276 {
277  NearestNodeLocator * nnl =
278  _nearest_node_locators[std::pair<unsigned int, unsigned int>(master_id, slave_id)];
279 
280  _subproblem.addGhostedBoundary(master_id);
282 
283  if (!nnl)
284  {
285  nnl = new NearestNodeLocator(_subproblem, _mesh, master_id, slave_id);
286  _nearest_node_locators[std::pair<unsigned int, unsigned int>(master_id, slave_id)] = nnl;
287  }
288 
289  return *nnl;
290 }
291 
294  const BoundaryName & slave)
295 {
296  unsigned int master_id = _mesh.getBoundaryID(master);
297  unsigned int slave_id = _mesh.getBoundaryID(slave);
298 
299  _subproblem.addGhostedBoundary(master_id);
301 
302  return getQuadratureNearestNodeLocator(master_id, slave_id);
303 }
304 
307  const unsigned int slave_id)
308 {
309  // TODO: Make this better!
310  unsigned int base_id = 1e6;
311  unsigned int qslave_id = slave_id + base_id;
312 
313  _slave_to_qslave[slave_id] = qslave_id;
314 
315  return getNearestNodeLocator(master_id, qslave_id);
316 }
317 
318 void
319 GeometricSearchData::generateQuadratureNodes(unsigned int slave_id, unsigned int qslave_id)
320 {
321  // Have we already generated quadrature nodes for this boundary id?
322  if (_quadrature_boundaries.find(slave_id) != _quadrature_boundaries.end())
323  return;
324 
325  _quadrature_boundaries.insert(slave_id);
326 
327  const MooseArray<Point> & points_face = _subproblem.assembly(0).qPointsFace();
328 
330  for (const auto & belem : range)
331  {
332  const Elem * elem = belem->_elem;
333  unsigned short int side = belem->_side;
334  BoundaryID boundary_id = belem->_bnd_id;
335 
336  if (elem->processor_id() == _subproblem.processor_id())
337  {
338  if (boundary_id == (BoundaryID)slave_id)
339  {
341  _subproblem.prepare(elem, 0);
342  _subproblem.reinitElemFace(elem, side, boundary_id, 0);
343 
344  for (unsigned int qp = 0; qp < points_face.size(); qp++)
345  _mesh.addQuadratureNode(elem, side, qp, qslave_id, points_face[qp]);
346  }
347  }
348  }
349 }
350 
353  const BoundaryName & slave,
354  Moose::ConstraintType side_type)
355 {
356  unsigned int master_id = _mesh.getBoundaryID(master);
357  unsigned int slave_id = _mesh.getBoundaryID(slave);
358 
359  return getMortarNearestNodeLocator(master_id, slave_id, side_type);
360 }
361 
364  const unsigned int slave_id,
365  Moose::ConstraintType side_type)
366 {
367  unsigned int mortarboundary_id, boundary;
368 
369  switch (side_type)
370  {
371  case Moose::Master:
372  boundary = master_id;
373  mortarboundary_id = MORTAR_BASE_ID + slave_id;
374  _boundary_to_mortarboundary[slave_id] = mortarboundary_id;
375  break;
376 
377  case Moose::Slave:
378  boundary = slave_id;
379  mortarboundary_id = MORTAR_BASE_ID + master_id;
380  _boundary_to_mortarboundary[master_id] = mortarboundary_id;
381  break;
382  }
383 
384  generateMortarNodes(master_id, slave_id, 1001);
385 
386  return getNearestNodeLocator(boundary, 1001);
387 }
388 
389 void
390 GeometricSearchData::addElementPairLocator(const unsigned int & interface_id,
391  std::shared_ptr<ElementPairLocator> epl)
392 {
393  _element_pair_locators[interface_id] = epl;
394 }
395 
396 void
398  unsigned int slave_id,
399  unsigned int qslave_id)
400 {
401  // Have we already generated quadrature nodes for this boundary id?
402  if (_mortar_boundaries.find(std::pair<unsigned int, unsigned int>(master_id, slave_id)) !=
403  _mortar_boundaries.end())
404  return;
405 
406  _mortar_boundaries.insert(std::pair<unsigned int, unsigned int>(master_id, slave_id));
407 
408  MooseMesh::MortarInterface * iface = _mesh.getMortarInterface(master_id, slave_id);
409 
410  const MooseArray<Point> & qpoints = _subproblem.assembly(0).qPoints();
411  for (const auto & elem : iface->_elems)
412  {
414  _subproblem.assembly(0).reinit(elem);
415 
416  for (unsigned int qp = 0; qp < qpoints.size(); qp++)
417  _mesh.addQuadratureNode(elem, 0, qp, qslave_id, qpoints[qp]);
418  }
419 }
420 
421 void
423 {
424  const MooseArray<Point> & points_face = _subproblem.assembly(0).qPointsFace();
425 
427  for (const auto & belem : range)
428  {
429  const Elem * elem = belem->_elem;
430  unsigned short int side = belem->_side;
431  BoundaryID boundary_id = belem->_bnd_id;
432 
433  if (elem->processor_id() == _subproblem.processor_id())
434  {
435  if (boundary_id == (BoundaryID)slave_id)
436  {
438  _subproblem.prepare(elem, 0);
439  _subproblem.reinitElemFace(elem, side, boundary_id, 0);
440 
441  for (unsigned int qp = 0; qp < points_face.size(); qp++)
442  (*_mesh.getQuadratureNode(elem, side, qp)) = points_face[qp];
443  }
444  }
445  }
446 }
447 
448 void
450 {
451  // Regenerate the quadrature nodes
452  for (const auto & it : _slave_to_qslave)
453  generateQuadratureNodes(it.first, it.second);
454 }
455 
456 void
458 {
459  const MooseArray<Point> & qpoints = _subproblem.assembly(0).qPoints();
460 
461  auto & ifaces = _mesh.getMortarInterfaces();
462  for (const auto & iface : ifaces)
463  for (const auto & elem : iface->_elems)
464  {
466  _subproblem.assembly(0).reinit(elem);
467 
468  for (unsigned int qp = 0; qp < qpoints.size(); qp++)
469  (*_mesh.getQuadratureNode(elem, 0, qp)) = qpoints[qp];
470  }
471 }
472 
473 void
475 {
476  _mortar_boundaries.clear();
477  // Regenerate the quadrature nodes for mortar spaces
478  auto & ifaces = _mesh.getMortarInterfaces();
479  for (const auto & iface : ifaces)
480  {
481  unsigned int master_id = _mesh.getBoundaryID(iface->_master);
482  unsigned int slave_id = _mesh.getBoundaryID(iface->_slave);
483  generateMortarNodes(master_id, slave_id, 0);
484  }
485 }
Node * addQuadratureNode(const Elem *elem, const unsigned short int side, const unsigned int qp, BoundaryID bid, const Point &point)
Adds a fictitious "QuadratureNode".
Definition: MooseMesh.C:847
std::set< unsigned int > _quadrature_boundaries
These are real boundaries that have quadrature nodes on them.
void findNodes()
This is the main method that is going to start the search.
ConstraintType
Definition: MooseTypes.h:198
virtual void reinit()
const MooseArray< Point > & qPointsFace()
Returns the reference to the current quadrature being used.
Definition: Assembly.h:171
static const unsigned int MORTAR_BASE_ID
virtual void update()
bool _first
Denotes whether this is the first time the geometric search objects have been updated.
PenetrationLocator & getQuadraturePenetrationLocator(const BoundaryName &master, const BoundaryName &slave, Order order=FIRST)
Finds the nearest node to each node in boundary1 to each node in boundary2 and the other way around...
PenetrationLocator & getPenetrationLocator(const BoundaryName &master, const BoundaryName &slave, Order order=FIRST)
void addElementPairLocator(const unsigned int &interface_id, std::shared_ptr< ElementPairLocator > epl)
StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > ConstBndElemRange
Definition: MooseMesh.h:1185
virtual Assembly & assembly(THREAD_ID tid)=0
void updateMortarNodes()
Update the positions of the quadrature nodes for mortar interfaces.
virtual void setCurrentSubdomainID(const Elem *elem, THREAD_ID tid)=0
virtual void reinitElemFace(const Elem *elem, unsigned int side, BoundaryID bnd_id, THREAD_ID tid)=0
std::vector< Elem * > _elems
List of elements on this interface.
Definition: MooseMesh.h:767
void reinit()
Completely redo the search from scratch.
void updateQuadratureNodes(unsigned int slave_id)
Update the positions of the quadrature nodes.
const MooseArray< Point > & qPoints()
Returns the reference to the quadrature points.
Definition: Assembly.h:135
std::map< unsigned int, unsigned int > _slave_to_qslave
A mapping of the real boundary id to the slave boundary ids.
NearestNodeLocator & getMortarNearestNodeLocator(const BoundaryName &domain, const BoundaryName &slave, Moose::ConstraintType side_type)
MooseMesh::MortarInterface * getMortarInterface(BoundaryID master, BoundaryID slave)
Definition: MooseMesh.C:2494
void reinit(const Elem *elem)
Reinitialize objects (JxW, q_points, ...) for an elements.
Definition: Assembly.C:650
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
Definition: MooseMesh.C:929
NearestNodeLocator & getNearestNodeLocator(const BoundaryName &master, const BoundaryName &slave)
std::vector< std::unique_ptr< MooseMesh::MortarInterface > > & getMortarInterfaces()
Definition: MooseMesh.h:777
Real maxPatchPercentage()
Maximum percentage through the search patch that any NearestNodeLocator had to look.
NearestNodeLocator & getQuadratureNearestNodeLocator(const BoundaryName &master, const BoundaryName &slave)
void clearQuadratureNodes()
Clear out any existing quadrature nodes.
Definition: MooseMesh.C:917
virtual void prepare(const Elem *elem, THREAD_ID tid)=0
void reinitQuadratureNodes(unsigned int slave_id)
Completely redo quadrature nodes.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:74
std::map< unsigned int, std::shared_ptr< ElementPairLocator > > _element_pair_locators
void reinit()
Completely redo all geometric search objects.
This is the ElementPairLocator class.
void reinitMortarNodes()
Completely redo quadrature nodes for mortar interfaces.
GeometricSearchType
Used to select groups of geometric search objects to update.
Node * getQuadratureNode(const Elem *elem, const unsigned short int side, const unsigned int qp)
Get a specified quadrature node.
Definition: MooseMesh.C:899
std::map< std::pair< unsigned int, unsigned int >, PenetrationLocator * > _penetration_locators
std::map< unsigned int, unsigned int > _boundary_to_mortarboundary
A mapping of the real boundary id to the slave boundary ids for mortar spaces.
MatType type
std::set< std::pair< unsigned int, unsigned int > > _mortar_boundaries
These are real boundaries that have quadrature nodes on them.
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:53
unsigned int size() const
The number of elements that can currently be stored in the array.
Definition: MooseArray.h:250
std::map< std::pair< unsigned int, unsigned int >, NearestNodeLocator * > _nearest_node_locators
virtual void addGhostedBoundary(BoundaryID boundary_id)=0
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
void update(GeometricSearchType type=ALL)
Update all of the search objects.
void generateMortarNodes(unsigned int master_id, unsigned int slave_id, unsigned int qslave_id)
Add Quadrature Nodes to the Mesh in support of mortar based penetration location and nearest node sea...
StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
Definition: MooseMesh.C:734
void reinit()
Completely redo the search from scratch.
PenetrationLocator & getMortarPenetrationLocator(const BoundaryName &master, const BoundaryName &slave, Moose::ConstraintType side_type, Order order=FIRST)
void clearNearestNodeLocators()
Clear out the Penetration Locators so they will redo the search.
boundary_id_type BoundaryID
Definition: MooseTypes.h:75
void generateQuadratureNodes(unsigned int slave_id, unsigned int qslave_id)
Add Quadrature Nodes to the Mesh in support of Quadrature based penetration location and nearest node...
GeometricSearchData(SubProblem &subproblem, MooseMesh &mesh)