https://mooseframework.inl.gov
Loading...
Searching...
No Matches
GeometricSearchData.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 "GeometricSearchData.h"
11// Moose includes
12#include "NearestNodeLocator.h"
13#include "PenetrationLocator.h"
14#include "ElementPairLocator.h"
15#include "SubProblem.h"
16#include "MooseMesh.h"
17#include "Assembly.h"
18
19#include "libmesh/elem.h"
20#include "libmesh/node.h"
21#include "libmesh/int_range.h"
22
24 : _subproblem(subproblem), _mesh(mesh), _first(true), _search_using_point_locator(false)
25{
26 // do a check on the boundary IDs to see if any conflict will rise from computing QP node set IDs
27 const auto & nodeset_ids = _mesh.meshNodesetIds();
28 for (const auto id : nodeset_ids)
29 if (nodeset_ids.find(-id - 1) != nodeset_ids.end())
30 mooseError("Your mesh contains nodesets with negative IDs that interfere with QP nodeset IDs "
31 "potentially generated by the GeometricSearch system.");
32}
33
35{
36 for (auto & it : _penetration_locators)
37 delete it.second;
38
39 for (auto & it : _nearest_node_locators)
40 delete it.second;
41}
42
43void
45{
46 if (type == ALL || type == QUADRATURE || type == NEAREST_NODE)
47 {
48 if (_first) // Only do this once
49 {
50 _first = false;
51
52 for (const auto & it : _secondary_to_qsecondary)
53 generateQuadratureNodes(it.first, it.second);
54
55 // reinit on displaced mesh before update
56 for (const auto & epl_it : _element_pair_locators)
57 {
58 ElementPairLocator & epl = *(epl_it.second);
59 epl.reinit();
60 }
61 }
62
63 // Update the position of quadrature nodes first
64 for (const auto & qbnd : _quadrature_boundaries)
66 }
67
68 if (type == ALL || type == NEAREST_NODE)
69 {
70 for (const auto & nnl_it : _nearest_node_locators)
71 {
72 NearestNodeLocator * nnl = nnl_it.second;
73 nnl->findNodes();
74 }
75 }
76
77 if (type == ALL || type == PENETRATION)
78 {
79 for (const auto & pl_it : _penetration_locators)
80 {
81 PenetrationLocator * pl = pl_it.second;
83 }
84 }
85
86 if (type == ALL || type == PENETRATION)
87 {
88 for (auto & elem_pair_locator_pair : _element_pair_locators)
89 {
90 ElementPairLocator & epl = (*elem_pair_locator_pair.second);
91 epl.update();
92 }
93 }
94}
95
96void
98{
100 // Update the position of quadrature nodes first
101 for (const auto & qbnd : _quadrature_boundaries)
103
104 for (const auto & nnl_it : _nearest_node_locators)
105 {
106 NearestNodeLocator * nnl = nnl_it.second;
107 nnl->reinit();
108 }
109
110 for (const auto & pl_it : _penetration_locators)
111 {
112 PenetrationLocator * pl = pl_it.second;
113 pl->reinit();
114 }
115
116 for (const auto & epl_it : _element_pair_locators)
117 {
118 ElementPairLocator & epl = *(epl_it.second);
119 epl.reinit();
120 }
121}
122
123void
125{
126 for (const auto & [boundary_pair, pl] : _penetration_locators)
127 _penetration_locator_backups[boundary_pair] = pl->backup();
128}
129
130void
132{
133 for (const auto & [boundary_pair, pl] : _penetration_locators)
134 pl->restore(libmesh_map_find(_penetration_locator_backups, boundary_pair));
135}
136
137void
139{
140 for (const auto & nnl_it : _nearest_node_locators)
141 {
142 NearestNodeLocator * nnl = nnl_it.second;
143 nnl->reinit();
144 }
145}
146
147Real
149{
150 Real max = 0.0;
151
152 for (const auto & nnl_it : _nearest_node_locators)
153 {
154 NearestNodeLocator * nnl = nnl_it.second;
155
156 if (nnl->_max_patch_percentage > max)
157 max = nnl->_max_patch_percentage;
158 }
159
160 return max;
161}
162
165 const BoundaryName & secondary,
166 Order order)
167{
168 auto primary_id = _mesh.getBoundaryID(primary);
169 auto secondary_id = _mesh.getBoundaryID(secondary);
170
172 _subproblem.addGhostedBoundary(secondary_id);
173
174 PenetrationLocator * pl =
175 _penetration_locators[std::pair<BoundaryID, BoundaryID>(primary_id, secondary_id)];
176
177 if (!pl)
178 {
180 *this,
181 _mesh,
182 primary_id,
183 secondary_id,
184 order,
185 getNearestNodeLocator(primary_id, secondary_id));
186
188 pl->setUsePointLocator(true);
189
190 _penetration_locators[std::pair<BoundaryID, BoundaryID>(primary_id, secondary_id)] = pl;
191 }
192
193 return *pl;
194}
195
198 const BoundaryName & secondary,
199 Order order)
200{
201 const auto primary_id = _mesh.getBoundaryID(primary);
202 const auto secondary_id = _mesh.getBoundaryID(secondary);
203
205 _subproblem.addGhostedBoundary(secondary_id);
206
207 // Generate a new boundary id (we use the negative numbers and subtract 1 to disambiguate id=0)
208 const auto qsecondary_id = -secondary_id - 1;
209
210 _secondary_to_qsecondary[secondary_id] = qsecondary_id;
211
212 PenetrationLocator * pl =
213 _penetration_locators[std::pair<BoundaryID, BoundaryID>(primary_id, qsecondary_id)];
214
215 if (!pl)
216 {
218 *this,
219 _mesh,
220 primary_id,
221 qsecondary_id,
222 order,
223 getQuadratureNearestNodeLocator(primary_id, secondary_id));
224
226 pl->setUsePointLocator(true);
227
228 _penetration_locators[std::pair<BoundaryID, BoundaryID>(primary_id, qsecondary_id)] = pl;
229 }
230
231 return *pl;
232}
233
236 const BoundaryName & secondary)
237{
238 const auto primary_id = _mesh.getBoundaryID(primary);
239 const auto secondary_id = _mesh.getBoundaryID(secondary);
240
242 _subproblem.addGhostedBoundary(secondary_id);
243
244 return getNearestNodeLocator(primary_id, secondary_id);
245}
246
249 const BoundaryID secondary_id)
250{
251 NearestNodeLocator * nnl =
252 _nearest_node_locators[std::pair<BoundaryID, BoundaryID>(primary_id, secondary_id)];
253
255 _subproblem.addGhostedBoundary(secondary_id);
256
257 if (!nnl)
258 {
259 nnl = new NearestNodeLocator(_subproblem, _mesh, primary_id, secondary_id);
260 _nearest_node_locators[std::pair<BoundaryID, BoundaryID>(primary_id, secondary_id)] = nnl;
261 }
262
263 return *nnl;
264}
265
268 const BoundaryName & secondary)
269{
270 const auto primary_id = _mesh.getBoundaryID(primary);
271 const auto secondary_id = _mesh.getBoundaryID(secondary);
272
274 _subproblem.addGhostedBoundary(secondary_id);
275
276 return getQuadratureNearestNodeLocator(primary_id, secondary_id);
277}
278
281 const BoundaryID secondary_id)
282{
283 // Generate a new boundary id (we use the negative numbers and subtract 1 to disambiguate id=0)
284 const auto qsecondary_id = -secondary_id - 1;
285
286 _secondary_to_qsecondary[secondary_id] = qsecondary_id;
287 return getNearestNodeLocator(primary_id, qsecondary_id);
288}
289
290void
292 const BoundaryID qsecondary_id,
293 bool reiniting)
294{
295 // Have we already generated quadrature nodes for this boundary id?
296 if (_quadrature_boundaries.find(secondary_id) != _quadrature_boundaries.end())
297 {
298 if (!reiniting)
299 return;
300 }
301 else
302 _quadrature_boundaries.insert(secondary_id);
303
304 const MooseArray<Point> & points_face = _subproblem.assembly(0, 0).qPointsFace();
305
307 for (const auto & belem : range)
308 {
309 const Elem * elem = belem->_elem;
310 const auto side = belem->_side;
311 const auto boundary_id = belem->_bnd_id;
312
313 if (elem->processor_id() == _subproblem.processor_id())
314 {
315 if (boundary_id == (BoundaryID)secondary_id)
316 {
317 // All we should need to do here is reinit the underlying libMesh::FE object because that
318 // will get us the correct points for the current element and side
320 _subproblem.assembly(0, 0).reinit(elem, side);
321
322 for (const auto qp : index_range(points_face))
323 _mesh.addQuadratureNode(elem, side, qp, qsecondary_id, points_face[qp]);
324 }
325 }
326 }
327}
328
329void
331 std::shared_ptr<ElementPairLocator> epl)
332{
333 _element_pair_locators[interface_id] = epl;
334}
335
336void
338{
339 if (state != _search_using_point_locator)
340 {
341 for (auto & [key, val] : _penetration_locators)
342 {
343 libmesh_ignore(key);
344 if (val)
345 val->setUsePointLocator(state);
346 }
347 }
348
350}
351
352void
354{
355 const MooseArray<Point> & points_face = _subproblem.assembly(0, 0).qPointsFace();
356
358 for (const auto & belem : range)
359 {
360 const Elem * elem = belem->_elem;
361 const auto side = belem->_side;
362 const auto boundary_id = belem->_bnd_id;
363
364 if (elem->processor_id() == _subproblem.processor_id())
365 {
366 if (boundary_id == (BoundaryID)secondary_id)
367 {
368 // All we should need to do here is reinit the underlying libMesh::FE object because that
369 // will get us the correct points for the current element and side
371 _subproblem.assembly(0, 0).reinit(elem, side);
372
373 for (const auto qp : index_range(points_face))
374 (*_mesh.getQuadratureNode(elem, side, qp)) = points_face[qp];
375 }
376 }
377 }
378}
379
380void
382{
383 // Regenerate the quadrature nodes
384 for (const auto & it : _secondary_to_qsecondary)
385 generateQuadratureNodes(it.first, it.second, /*reiniting=*/true);
386}
387
388void
390{
391 for (const auto & nnl_it : _nearest_node_locators)
392 {
393 NearestNodeLocator * nnl = nnl_it.second;
394 nnl->updateGhostedElems();
395 }
396}
boundary_id_type BoundaryID
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
void reinit(const Elem *elem)
Reinitialize objects (JxW, q_points, ...) for an elements.
Definition Assembly.C:1856
const MooseArray< Point > & qPointsFace() const
Returns the reference to the current quadrature being used.
Definition Assembly.h:336
This is the ElementPairLocator class.
void reinit()
Completely redo all geometric search objects.
void restore()
Restore the PenetrationLocators' state captured by the most recent backup().
NearestNodeLocator & getNearestNodeLocator(const BoundaryName &primary, const BoundaryName &secondary)
GeometricSearchType
Used to select groups of geometric search objects to update.
void addElementPairLocator(BoundaryID interface_id, std::shared_ptr< ElementPairLocator > epl)
bool _first
Denotes whether this is the first time the geometric search objects have been updated.
void reinitQuadratureNodes(const BoundaryID secondary_id)
Completely redo quadrature nodes.
std::map< std::pair< BoundaryID, BoundaryID >, NearestNodeLocator * > _nearest_node_locators
void clearNearestNodeLocators()
Clear out the Penetration Locators so they will redo the search.
std::map< BoundaryID, std::shared_ptr< ElementPairLocator > > _element_pair_locators
std::set< BoundaryID > _quadrature_boundaries
These are real boundaries that have quadrature nodes on them.
void updateGhostedElems()
Updates the list of ghosted elements at the start of each time step for the nonlinear iteration patch...
std::map< std::pair< BoundaryID, BoundaryID >, PenetrationLocator * > _penetration_locators
bool _search_using_point_locator
Denotes whether the PenetrationLocator objects should use a point locator rather than cheaper node-to...
NearestNodeLocator & getQuadratureNearestNodeLocator(const BoundaryName &primary, const BoundaryName &secondary)
std::map< std::pair< BoundaryID, BoundaryID >, std::string > _penetration_locator_backups
Per-locator PenetrationLocator::backup() snapshots taken by backup(), keyed the same way as _penetrat...
void updateQuadratureNodes(const BoundaryID secondary_id)
Update the positions of the quadrature nodes.
GeometricSearchData(SubProblem &subproblem, MooseMesh &mesh)
void update(GeometricSearchType type=ALL)
Update all of the search objects.
void backup()
Snapshot the PenetrationLocators' restartable state (the same state used for restart/recover),...
PenetrationLocator & getPenetrationLocator(const BoundaryName &primary, const BoundaryName &secondary, libMesh::Order order=libMesh::FIRST)
std::map< BoundaryID, BoundaryID > _secondary_to_qsecondary
A mapping of the real boundary id to the secondary boundary ids.
Real maxPatchPercentage()
Maximum percentage through the search patch that any NearestNodeLocator had to look.
void generateQuadratureNodes(const BoundaryID secondary_id, const BoundaryID qsecondary_id, bool reiniting=false)
Add Quadrature Nodes to the Mesh in support of Quadrature based penetration location and nearest node...
void setSearchUsingPointLocator(bool state)
PenetrationLocator & getQuadraturePenetrationLocator(const BoundaryName &primary, const BoundaryName &secondary, libMesh::Order order=libMesh::FIRST)
forward declarations
Definition MooseArray.h:18
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
Node * getQuadratureNode(const Elem *elem, const unsigned short int side, const unsigned int qp)
Get a specified quadrature node.
Definition MooseMesh.C:1607
void clearQuadratureNodes()
Clear out any existing quadrature nodes.
Definition MooseMesh.C:1625
const std::set< BoundaryID > & meshNodesetIds() const
Returns a read-only reference to the set of nodesets currently present in the Mesh.
Definition MooseMesh.C:3253
BoundaryID getBoundaryID(const BoundaryName &boundary_name) const
Get the associated BoundaryID for the boundary name.
Definition MooseMesh.C:1639
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:1558
libMesh::StoredRange< MooseMesh::const_bnd_elem_iterator, const BndElement * > * getBoundaryElementRange()
Definition MooseMesh.C:1303
Finds the nearest node to each node in boundary1 to each node in boundary2 and the other way around.
void reinit()
Completely redo the search from scratch.
void findNodes()
This is the main method that is going to start the search.
void updateGhostedElems()
Updates the ghosted elements at the start of the time step for iteration patch update strategy.
void setUsePointLocator(bool state)
void reinit()
Completely redo the search from scratch.
Generic class for solving transient nonlinear problems.
Definition SubProblem.h:79
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid)=0
virtual void addGhostedBoundary(BoundaryID boundary_id)=0
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num)=0
processor_id_type processor_id() const
MeshBase & mesh