Line data Source code
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 : #pragma once
11 :
12 : #ifdef MOOSE_KOKKOS_ENABLED
13 : #include "KokkosMesh.h"
14 : #endif
15 :
16 : #include "MooseObject.h"
17 : #include "BndNode.h"
18 : #include "BndElement.h"
19 : #include "Restartable.h"
20 : #include "MooseEnum.h"
21 : #include "PerfGraphInterface.h"
22 : #include "MooseHashing.h"
23 : #include "MooseApp.h"
24 : #include "FaceInfo.h"
25 : #include "ElemInfo.h"
26 :
27 : #include <memory> //std::unique_ptr
28 : #include <unordered_map>
29 : #include <unordered_set>
30 :
31 : // libMesh
32 : #include "libmesh/elem_range.h"
33 : #include "libmesh/mesh_base.h"
34 : #include "libmesh/replicated_mesh.h"
35 : #include "libmesh/distributed_mesh.h"
36 : #include "libmesh/node_range.h"
37 : #include "libmesh/nanoflann.hpp"
38 : #include "libmesh/vector_value.h"
39 : #include "libmesh/point.h"
40 : #include "libmesh/partitioner.h"
41 :
42 : class Assembly;
43 : class RelationshipManager;
44 : class MooseVariableBase;
45 : class MooseAppCoordTransform;
46 : class MooseUnits;
47 :
48 : // libMesh forward declarations
49 : namespace libMesh
50 : {
51 : class ExodusII_IO;
52 : class QBase;
53 : class PeriodicBoundaries;
54 : class Partitioner;
55 : class GhostingFunctor;
56 : class BoundingBox;
57 : }
58 : // Useful typedefs
59 : typedef libMesh::StoredRange<std::set<Node *>::iterator, Node *> SemiLocalNodeRange;
60 :
61 : // List of supported geometrical elements
62 : const std::string LIST_GEOM_ELEM = "EDGE EDGE2 EDGE3 EDGE4 "
63 : "QUAD QUAD4 QUAD8 QUAD9 "
64 : "TRI TRI3 TRI6 TRI7 "
65 : "HEX HEX8 HEX20 HEX27 "
66 : "TET TET4 TET10 TET14 "
67 : "PRISM PRISM6 PRISM15 PRISM18 "
68 : "PYRAMID PYRAMID5 PYRAMID13 PYRAMID14";
69 :
70 : /**
71 : * Helper object for holding qp mapping info.
72 : */
73 : class QpMap
74 : {
75 : public:
76 65270 : QpMap() : _distance(std::numeric_limits<Real>::max()) {}
77 :
78 : /// The qp to map from
79 : unsigned int _from;
80 :
81 : /// The qp to map to
82 : unsigned int _to;
83 :
84 : /// The distance between them
85 : Real _distance;
86 : };
87 :
88 : /**
89 : * MooseMesh wraps a libMesh::Mesh object and enhances its capabilities
90 : * by caching additional data and storing more state.
91 : */
92 : class MooseMesh : public MooseObject, public Restartable, public PerfGraphInterface
93 : {
94 : public:
95 : /**
96 : * Typical "Moose-style" constructor and copy constructor.
97 : */
98 : static InputParameters validParams();
99 :
100 : MooseMesh(const InputParameters & parameters);
101 : MooseMesh(const MooseMesh & other_mesh);
102 : MooseMesh() = delete;
103 : MooseMesh & operator=(const MooseMesh & other_mesh) = delete;
104 :
105 : virtual ~MooseMesh();
106 :
107 : // The type of libMesh::MeshBase that will be used
108 : enum class ParallelType
109 : {
110 : DEFAULT,
111 : REPLICATED,
112 : DISTRIBUTED
113 : };
114 :
115 : /**
116 : * Clone method. Allocates memory you are responsible to clean up.
117 : */
118 : virtual MooseMesh & clone() const;
119 :
120 : /**
121 : * A safer version of the clone() method that hands back an
122 : * allocated object wrapped in a smart pointer. This makes it much
123 : * less likely that the caller will leak the memory in question.
124 : */
125 : virtual std::unique_ptr<MooseMesh> safeClone() const = 0;
126 :
127 : /**
128 : * Determine whether to use a distributed mesh. Should be called during construction
129 : */
130 : void determineUseDistributedMesh();
131 :
132 : /**
133 : * Method to construct a libMesh::MeshBase object that is normally set and used by the MooseMesh
134 : * object during the "init()" phase. If the parameter \p dim is not
135 : * provided, then its value will be taken from the input file mesh block.
136 : */
137 : std::unique_ptr<MeshBase> buildMeshBaseObject(unsigned int dim = libMesh::invalid_uint);
138 :
139 : /**
140 : * Shortcut method to construct a unique pointer to a libMesh mesh instance. The created
141 : * derived-from-MeshBase object will have its \p allow_remote_element_removal flag set to whatever
142 : * our value is. We will also attach any geometric \p RelationshipManagers that have been
143 : * requested by our simulation objects to the \p MeshBase object. If the parameter \p dim is not
144 : * provided, then its value will be taken from the input file mesh block.
145 : */
146 : template <typename T>
147 : std::unique_ptr<T> buildTypedMesh(unsigned int dim = libMesh::invalid_uint);
148 :
149 : /**
150 : * Method to set the mesh_base object. If this method is NOT called prior to calling init(), a
151 : * MeshBase object will be automatically constructed and set.
152 : */
153 : void setMeshBase(std::unique_ptr<MeshBase> mesh_base);
154 :
155 : /// returns MooseMesh partitioning options so other classes can use it
156 : static MooseEnum partitioning();
157 :
158 : /// returns MooseMesh element type options
159 : static MooseEnum elemTypes();
160 :
161 : /**
162 : * Initialize the Mesh object. Most of the time this will turn around
163 : * and call build_mesh so the child class can build the Mesh object.
164 : *
165 : * However, during Recovery this will read the CPA file...
166 : */
167 : virtual void init();
168 :
169 : /**
170 : * Must be overridden by child classes.
171 : *
172 : * This is where the Mesh object is actually created and filled in.
173 : */
174 : virtual void buildMesh() = 0;
175 :
176 : /**
177 : * Returns MeshBase::mesh_dimension(), (not
178 : * MeshBase::spatial_dimension()!) of the underlying libMesh mesh
179 : * object.
180 : */
181 : virtual unsigned int dimension() const;
182 :
183 : /**
184 : * Returns MeshBase::spatial_dimension
185 : */
186 56185 : virtual unsigned int spatialDimension() const { return _mesh->spatial_dimension(); }
187 :
188 : /**
189 : * Returns the effective spatial dimension determined by the coordinates actually used by the
190 : * mesh. This means that a 1D mesh that has non-zero z or y coordinates is actually a 2D or 3D
191 : * mesh, respectively. Likewise a 2D mesh that has non-zero z coordinates is actually 3D mesh.
192 : */
193 : virtual unsigned int effectiveSpatialDimension() const;
194 :
195 : /**
196 : * Returns the maximum element dimension on the given blocks
197 : */
198 : unsigned int getBlocksMaxDimension(const std::vector<SubdomainName> & blocks) const;
199 :
200 : /**
201 : * Returns a vector of boundary IDs for the requested element on the
202 : * requested side.
203 : */
204 : std::vector<BoundaryID> getBoundaryIDs(const Elem * const elem,
205 : const unsigned short int side) const;
206 :
207 : /**
208 : * Returns a const pointer to a lower dimensional element that
209 : * corresponds to a side of a higher dimensional element. This
210 : * relationship is established through an internal_parent; if there is
211 : * no lowerDElem, nullptr is returned.
212 : */
213 : const Elem * getLowerDElem(const Elem *, unsigned short int) const;
214 :
215 : /**
216 : * Returns the local side ID of the interior parent aligned with the lower dimensional element.
217 : */
218 : unsigned int getHigherDSide(const Elem * elem) const;
219 :
220 : /**
221 : * Returns a const reference to a set of all user-specified
222 : * boundary IDs. On a distributed mesh this will *only* include
223 : * boundary IDs which exist on local or ghosted elements; a copy and
224 : * a call to _communicator.set_union() will be necessary to get the
225 : * global ID set.
226 : */
227 : const std::set<BoundaryID> & getBoundaryIDs() const;
228 :
229 : /**
230 : * Calls BoundaryInfo::build_node_list()/build_side_list() and *makes separate copies* of
231 : * Nodes/Elems in those lists.
232 : *
233 : * Allocates memory which is cleaned up in the freeBndNodes()/freeBndElems() functions.
234 : */
235 : void buildNodeList();
236 : void buildBndElemList();
237 :
238 : /**
239 : * If not already created, creates a map from every node to all
240 : * elements to which they are connected.
241 : */
242 : const std::map<dof_id_type, std::vector<dof_id_type>> & nodeToElemMap();
243 :
244 : /**
245 : * If not already created, creates a map from every node to all
246 : * _active_ _semilocal_ elements to which they are connected.
247 : * Semilocal elements include local elements and elements that share at least
248 : * one node with a local element.
249 : * \note Extra ghosted elements are not included in this map!
250 : */
251 : const std::map<dof_id_type, std::vector<dof_id_type>> & nodeToActiveSemilocalElemMap();
252 :
253 : /**
254 : * These structs are required so that the bndNodes{Begin,End} and
255 : * bndElems{Begin,End} functions work...
256 : */
257 : struct bnd_node_iterator;
258 : struct const_bnd_node_iterator;
259 :
260 : struct bnd_elem_iterator;
261 : struct const_bnd_elem_iterator;
262 :
263 : /**
264 : * Return iterators to the beginning/end of the boundary nodes list.
265 : */
266 : virtual bnd_node_iterator bndNodesBegin();
267 : virtual bnd_node_iterator bndNodesEnd();
268 :
269 : /**
270 : * Return iterators to the beginning/end of the boundary elements list.
271 : */
272 : virtual bnd_elem_iterator bndElemsBegin();
273 : virtual bnd_elem_iterator bndElemsEnd();
274 :
275 : /**
276 : * Calls BoundaryInfo::build_node_list_from_side_list().
277 : */
278 : void buildNodeListFromSideList();
279 :
280 : /**
281 : * Calls BoundaryInfo::build_side_list().
282 : * Fills in the three passed vectors with list logical (element, side, id) tuples.
283 : * This function will eventually be deprecated in favor of the one below, which
284 : * returns a single std::vector of (elem-id, side-id, bc-id) tuples instead.
285 : */
286 : void buildSideList(std::vector<dof_id_type> & el,
287 : std::vector<unsigned short int> & sl,
288 : std::vector<boundary_id_type> & il);
289 : /**
290 : * As above, but uses the non-deprecated std::tuple interface.
291 : */
292 : std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>> buildSideList();
293 :
294 : /**
295 : * Calls BoundaryInfo::build_active_side_list
296 : * @return A container of active (element, side, id) tuples.
297 : */
298 : std::vector<std::tuple<dof_id_type, unsigned short int, boundary_id_type>>
299 : buildActiveSideList() const;
300 :
301 : /**
302 : * Calls BoundaryInfo::side_with_boundary_id().
303 : */
304 : unsigned int sideWithBoundaryID(const Elem * const elem, const BoundaryID boundary_id) const;
305 :
306 : /**
307 : * Calls local_nodes_begin/end() on the underlying libMesh mesh object.
308 : */
309 : MeshBase::node_iterator localNodesBegin();
310 : MeshBase::node_iterator localNodesEnd();
311 : MeshBase::const_node_iterator localNodesBegin() const;
312 : MeshBase::const_node_iterator localNodesEnd() const;
313 :
314 : /**
315 : * Calls active_local_nodes_begin/end() on the underlying libMesh mesh object.
316 : */
317 : MeshBase::element_iterator activeLocalElementsBegin();
318 : const MeshBase::element_iterator activeLocalElementsEnd();
319 : MeshBase::const_element_iterator activeLocalElementsBegin() const;
320 : const MeshBase::const_element_iterator activeLocalElementsEnd() const;
321 :
322 : /**
323 : * Calls n_nodes/elem() on the underlying libMesh mesh object.
324 : */
325 : virtual dof_id_type nNodes() const;
326 : virtual dof_id_type nElem() const;
327 :
328 25842 : virtual dof_id_type nLocalNodes() const { return _mesh->n_local_nodes(); }
329 56548 : virtual dof_id_type nActiveElem() const { return _mesh->n_active_elem(); }
330 27228 : virtual dof_id_type nActiveLocalElem() const { return _mesh->n_active_local_elem(); }
331 58264 : virtual SubdomainID nSubdomains() const { return _mesh->n_subdomains(); }
332 25668 : virtual unsigned int nPartitions() const { return _mesh->n_partitions(); }
333 25668 : virtual bool skipPartitioning() const { return _mesh->skip_partitioning(); }
334 : virtual bool skipNoncriticalPartitioning() const;
335 :
336 : /**
337 : * Calls max_node/elem_id() on the underlying libMesh mesh object.
338 : * This may be larger than n_nodes/elem() in cases where the id
339 : * numbering is not contiguous.
340 : */
341 : virtual dof_id_type maxNodeId() const;
342 : virtual dof_id_type maxElemId() const;
343 :
344 : /**
345 : * Various accessors (pointers/references) for Node "i".
346 : *
347 : * If the requested node is a remote node on a distributed mesh,
348 : * only the query accessors are valid to call, and they return NULL.
349 : */
350 : virtual const Node & node(const dof_id_type i) const;
351 : virtual Node & node(const dof_id_type i);
352 : virtual const Node & nodeRef(const dof_id_type i) const;
353 : virtual Node & nodeRef(const dof_id_type i);
354 : virtual const Node * nodePtr(const dof_id_type i) const;
355 : virtual Node * nodePtr(const dof_id_type i);
356 : virtual const Node * queryNodePtr(const dof_id_type i) const;
357 : virtual Node * queryNodePtr(const dof_id_type i);
358 :
359 : /**
360 : * Various accessors (pointers/references) for Elem "i".
361 : *
362 : * If the requested elem is a remote element on a distributed mesh,
363 : * only the query accessors are valid to call, and they return NULL.
364 : */
365 : virtual Elem * elem(const dof_id_type i);
366 : virtual const Elem * elem(const dof_id_type i) const;
367 : virtual Elem * elemPtr(const dof_id_type i);
368 : virtual const Elem * elemPtr(const dof_id_type i) const;
369 : virtual Elem * queryElemPtr(const dof_id_type i);
370 : virtual const Elem * queryElemPtr(const dof_id_type i) const;
371 :
372 : /**
373 : * Setter/getter for whether the mesh is prepared
374 : */
375 : bool prepared() const;
376 : virtual void prepared(bool state);
377 :
378 : /**
379 : * If this method is called, we will call libMesh's prepare_for_use method when we
380 : * call Moose's prepare method. This should only be set when the mesh structure is changed
381 : * by MeshGenerators (i.e. Element deletion).
382 : */
383 : void needsPrepareForUse();
384 :
385 : /**
386 : * Declares that the MooseMesh has changed, invalidates cached data
387 : * and rebuilds caches. Sets a flag so that clients of the
388 : * MooseMesh also know when it has changed.
389 : */
390 : void meshChanged();
391 :
392 : /**
393 : * Declares a callback function that is executed at the conclusion
394 : * of meshChanged(). Ther user can implement actions required after
395 : * changing the mesh here.
396 : **/
397 : virtual void onMeshChanged();
398 :
399 : /**
400 : * Cache information about what elements were refined and coarsened in the previous step.
401 : */
402 : void cacheChangedLists();
403 :
404 : /**
405 : * Return a range that is suitable for threaded execution over elements that were just refined.
406 : *
407 : * @return The _Parent_ elements that are now set to be INACTIVE. Their _children_ are the new
408 : * elements.
409 : */
410 : ConstElemPointerRange * refinedElementRange() const;
411 :
412 : /**
413 : * Return a range that is suitable for threaded execution over elements that were just coarsened.
414 : * Note that these are the _Parent_ elements that are now set to be INACTIVE. Their _children_
415 : * are the elements that were just removed. Use coarsenedElementChildren() to get the element
416 : * IDs for the children that were just removed for a particular parent element.
417 : */
418 : ConstElemPointerRange * coarsenedElementRange() const;
419 :
420 : /**
421 : * Get the newly removed children element ids for an element that was just coarsened.
422 : *
423 : * @param elem Pointer to the parent element that was coarsened to.
424 : * @return The child element ids in Elem::child() order.
425 : */
426 : const std::vector<const Elem *> & coarsenedElementChildren(const Elem * elem) const;
427 :
428 : /**
429 : * Clears the "semi-local" node list and rebuilds it. Semi-local nodes
430 : * consist of all nodes that belong to local and ghost elements.
431 : */
432 : void updateActiveSemiLocalNodeRange(std::set<dof_id_type> & ghosted_elems);
433 :
434 : /**
435 : * Returns true if the node is semi-local
436 : * @param node Node pointer
437 : * @return true is the node is semi-local, false otherwise
438 : */
439 : bool isSemiLocal(Node * const node) const;
440 :
441 : ///@{
442 : /**
443 : * Return pointers to range objects for various types of ranges
444 : * (local nodes, boundary elems, etc.).
445 : */
446 : libMesh::ConstElemRange * getActiveLocalElementRange();
447 : libMesh::NodeRange * getActiveNodeRange();
448 : SemiLocalNodeRange * getActiveSemiLocalNodeRange() const;
449 : libMesh::ConstNodeRange * getLocalNodeRange();
450 : libMesh::StoredRange<MooseMesh::const_bnd_node_iterator, const BndNode *> *
451 : getBoundaryNodeRange();
452 : libMesh::StoredRange<MooseMesh::const_bnd_elem_iterator, const BndElement *> *
453 : getBoundaryElementRange();
454 : ///@}
455 :
456 : /**
457 : * Returns a map of boundaries to ids of elements on the boundary.
458 : */
459 : const std::unordered_map<boundary_id_type, std::unordered_set<dof_id_type>> &
460 : getBoundariesToElems() const;
461 :
462 : /**
463 : * Returns a map of boundaries to ids of elements on the boundary.
464 : */
465 : const std::unordered_map<boundary_id_type, std::unordered_set<dof_id_type>> &
466 : getBoundariesToActiveSemiLocalElemIds() const;
467 :
468 : /**
469 : * Return all ids of elements which have a side which is part of a sideset.
470 : * Note that boundaries are sided.
471 : * @param bid the id of the sideset of interest
472 : */
473 : std::unordered_set<dof_id_type> getBoundaryActiveSemiLocalElemIds(BoundaryID bid) const;
474 :
475 : /**
476 : * Return all ids of neighbors of elements which have a side which is part of a sideset.
477 : * Note that boundaries are sided, this is on the neighbor side. For the sideset side, use
478 : * getBoundariesActiveLocalElemIds.
479 : * Note that while the element is local and active, the neighbor is not guaranteed to be local,
480 : * it could be ghosted.
481 : * Note that if the neighbor is not ghosted, is a remote_elem, then it will not be included
482 : * @param bid the id of the sideset of interest
483 : */
484 : std::unordered_set<dof_id_type> getBoundaryActiveNeighborElemIds(BoundaryID bid) const;
485 :
486 : /**
487 : * Returns whether a boundary (given by its id) is not crossing through a group of blocks,
488 : * by which we mean that elements on both sides of the boundary are in those blocks
489 : * @param bid the id of the boundary of interest
490 : * @param blk_group the group of blocks potentially traversed
491 : * @return whether the boundary does not cross between the subdomains in the group
492 : */
493 : bool isBoundaryFullyExternalToSubdomains(BoundaryID bid,
494 : const std::set<SubdomainID> & blk_group) const;
495 :
496 : /**
497 : * Returns a read-only reference to the set of subdomains currently
498 : * present in the Mesh.
499 : */
500 : const std::set<SubdomainID> & meshSubdomains() const;
501 :
502 : /**
503 : * Returns a read-only reference to the set of boundary IDs currently
504 : * present in the Mesh.
505 : */
506 : const std::set<BoundaryID> & meshBoundaryIds() const;
507 :
508 : /**
509 : * Returns a read-only reference to the set of sidesets currently
510 : * present in the Mesh.
511 : */
512 : const std::set<BoundaryID> & meshSidesetIds() const;
513 :
514 : /**
515 : * Returns a read-only reference to the set of nodesets currently
516 : * present in the Mesh.
517 : */
518 : const std::set<BoundaryID> & meshNodesetIds() const;
519 :
520 : /**
521 : * Sets the mapping between BoundaryID and normal vector
522 : * Is called by AddAllSideSetsByNormals
523 : */
524 : void setBoundaryToNormalMap(std::unique_ptr<std::map<BoundaryID, RealVectorValue>> boundary_map);
525 :
526 : // DEPRECATED METHOD
527 : void setBoundaryToNormalMap(std::map<BoundaryID, RealVectorValue> * boundary_map);
528 :
529 : /**
530 : * Sets the set of BoundaryIDs
531 : * Is called by AddAllSideSetsByNormals
532 : */
533 : void setMeshBoundaryIDs(std::set<BoundaryID> boundary_IDs);
534 :
535 : /**
536 : * Returns the normal vector associated with a given BoundaryID.
537 : * It's only valid to call this when AddAllSideSetsByNormals is active.
538 : */
539 : const RealVectorValue & getNormalByBoundaryID(BoundaryID id) const;
540 :
541 : /**
542 : * Calls prepare_for_use() if the underlying MeshBase object isn't prepared, then communicates
543 : * various boundary information on parallel meshes. Also calls update() internally. Instead of
544 : * calling \p prepare_for_use on the currently held \p MeshBase object, a \p mesh_to_clone can be
545 : * provided. If it is provided (e.g. this method is given a non-null argument), then \p _mesh will
546 : * be assigned a clone of the \p mesh_to_clone. The provided \p mesh_to_clone must already be
547 : * prepared
548 : * @param mesh_to_clone If nonnull, we will clone this mesh instead of preparing our current one
549 : * @return Whether the libMesh mesh was prepared. This should really only be relevant in MOOSE
550 : * framework contexts where we need to make a decision about what to do with the displaced mesh.
551 : * If the reference mesh base object has \p prepare_for_use called (e.g. this method returns \p
552 : * true when called for the reference mesh), then we must pass the reference mesh base object into
553 : * this method when we call this for the displaced mesh. This is because the displaced mesh \emph
554 : * must be an exact clone of the reference mesh. We have seen that \p prepare_for_use called on
555 : * two previously identical meshes can result in two different meshes even with Metis partitioning
556 : */
557 : bool prepare(const MeshBase * mesh_to_clone);
558 :
559 : /**
560 : * Calls buildNodeListFromSideList(), buildNodeList(), and buildBndElemList().
561 : */
562 : void update();
563 :
564 : /**
565 : * Returns the level of uniform refinement requested (zero if AMR is disabled).
566 : */
567 : unsigned int uniformRefineLevel() const;
568 :
569 : /**
570 : * Set uniform refinement level
571 : */
572 : void setUniformRefineLevel(unsigned int, bool deletion = true);
573 :
574 : /**
575 : * Return a flag indicating whether or not we should skip remote deletion
576 : * and repartition after uniform refinements. If the flag is true, uniform
577 : * refinements will run more efficiently, but at the same time, there might
578 : * be extra ghosting elements. The number of layers of additional ghosting
579 : * elements depends on the number of uniform refinement levels. This flag
580 : * should be used only when you have a "fine enough" coarse mesh and want
581 : * to refine the mesh by a few levels. Otherwise, it might introduce an
582 : * unbalanced workload and too large ghosting domain.
583 : */
584 : bool skipDeletionRepartitionAfterRefine() const;
585 :
586 : /**
587 : * Whether or not skip uniform refinements when using a pre-split mesh
588 : */
589 294 : bool skipRefineWhenUseSplit() const { return _skip_refine_when_use_split; }
590 :
591 : /**
592 : * This will add the boundary ids to be ghosted to this processor
593 : */
594 : void addGhostedBoundary(BoundaryID boundary_id);
595 :
596 : /**
597 : * This sets the inflation amount for the bounding box for each partition for use in
598 : * ghosting boundaries
599 : */
600 : void setGhostedBoundaryInflation(const std::vector<Real> & inflation);
601 :
602 : /**
603 : * Return a writable reference to the set of ghosted boundary IDs.
604 : */
605 : const std::set<unsigned int> & getGhostedBoundaries() const;
606 :
607 : /**
608 : * Return a writable reference to the _ghosted_boundaries_inflation vector.
609 : */
610 : const std::vector<Real> & getGhostedBoundaryInflation() const;
611 :
612 : /**
613 : * Actually do the ghosting of boundaries that need to be ghosted to this processor.
614 : */
615 : void ghostGhostedBoundaries();
616 :
617 : /**
618 : * Whether or not we want to ghost ghosted boundaries
619 : */
620 879 : void needGhostGhostedBoundaries(bool needghost) { _need_ghost_ghosted_boundaries = needghost; }
621 :
622 : /**
623 : * Getter for the patch_size parameter.
624 : */
625 : unsigned int getPatchSize() const;
626 :
627 : /**
628 : * Getter for the ghosting_patch_size parameter.
629 : */
630 9442 : unsigned int getGhostingPatchSize() const { return _ghosting_patch_size; }
631 :
632 : /**
633 : * Getter for the maximum leaf size parameter.
634 : */
635 68972 : unsigned int getMaxLeafSize() const { return _max_leaf_size; }
636 :
637 : /**
638 : * Set the patch size update strategy
639 : */
640 : void setPatchUpdateStrategy(Moose::PatchUpdateType patch_update_strategy);
641 :
642 : /**
643 : * Get the current patch update strategy.
644 : */
645 : const Moose::PatchUpdateType & getPatchUpdateStrategy() const;
646 :
647 : /**
648 : * Get a (slightly inflated) processor bounding box.
649 : *
650 : * @param inflation_multiplier This amount will be multiplied by the length of the diagonal of the
651 : * bounding box to find the amount to inflate the bounding box by in all directions.
652 : */
653 : libMesh::BoundingBox getInflatedProcessorBoundingBox(Real inflation_multiplier = 0.01) const;
654 :
655 : /**
656 : * Implicit conversion operator from MooseMesh -> libMesh::MeshBase.
657 : */
658 : operator libMesh::MeshBase &();
659 : operator const libMesh::MeshBase &() const;
660 :
661 : /**
662 : * Accessor for the underlying libMesh Mesh object.
663 : */
664 : MeshBase & getMesh();
665 : MeshBase & getMesh(const std::string & name);
666 : const MeshBase & getMesh() const;
667 : const MeshBase & getMesh(const std::string & name) const;
668 : const MeshBase * getMeshPtr() const;
669 :
670 : /**
671 : * Accessor for Kokkos mesh object.
672 : */
673 : #ifdef MOOSE_KOKKOS_ENABLED
674 55917 : const Moose::Kokkos::Mesh * getKokkosMesh() const { return _kokkos_mesh.get(); }
675 : #endif
676 :
677 : /**
678 : * Calls print_info() on the underlying Mesh.
679 : */
680 : void printInfo(std::ostream & os = libMesh::out, const unsigned int verbosity = 0) const;
681 :
682 : /**
683 : * Return list of blocks to which the given node belongs.
684 : */
685 : const std::set<SubdomainID> & getNodeBlockIds(const Node & node) const;
686 :
687 : /**
688 : * Return a writable reference to a vector of node IDs that belong
689 : * to nodeset_id.
690 : */
691 : const std::vector<dof_id_type> & getNodeList(boundary_id_type nodeset_id) const;
692 :
693 : /**
694 : * Add a new node to the mesh. If there is already a node located at the point passed
695 : * then the node will not be added. In either case a reference to the node at that location
696 : * will be returned
697 : */
698 : const Node * addUniqueNode(const Point & p, Real tol = 1e-6);
699 :
700 : /**
701 : * Adds a fictitious "QuadratureNode". This doesn't actually add it to the libMesh mesh...
702 : * we just keep track of these here in MooseMesh.
703 : *
704 : * QuadratureNodes are fictitious "Nodes" that are located at quadrature points. This is useful
705 : * for using the geometric search system to do searches based on quadrature point locations....
706 : *
707 : * @param elem The element
708 : * @param side The side number on which we want to add a quadrature node
709 : * @param qp The number of the quadrature point
710 : * @param bid The boundary ID for the point to be added with
711 : * @param point The physical location of the point
712 : */
713 : Node * addQuadratureNode(const Elem * elem,
714 : const unsigned short int side,
715 : const unsigned int qp,
716 : BoundaryID bid,
717 : const Point & point);
718 :
719 : /**
720 : * Get a specified quadrature node.
721 : *
722 : * @param elem The element the quadrature point is on
723 : * @param side The side the quadrature point is on
724 : * @param qp The quadrature point number associated with the point
725 : */
726 : Node * getQuadratureNode(const Elem * elem, const unsigned short int side, const unsigned int qp);
727 :
728 : /**
729 : * Clear out any existing quadrature nodes.
730 : * Most likely called before re-adding them.
731 : */
732 : void clearQuadratureNodes();
733 :
734 : /**
735 : * Get the associated BoundaryID for the boundary name.
736 : *
737 : * @return param boundary_name The name of the boundary.
738 : * @return the boundary id from the passed boundary name.
739 : */
740 : BoundaryID getBoundaryID(const BoundaryName & boundary_name) const;
741 :
742 : /**
743 : * Get the associated BoundaryID for the boundary names that are passed in.
744 : *
745 : * @return param boundary_name The names of the boundaries.
746 : * @return the boundary ids from the passed boundary names.
747 : */
748 : std::vector<BoundaryID> getBoundaryIDs(const std::vector<BoundaryName> & boundary_name,
749 : bool generate_unknown = false) const;
750 :
751 : /**
752 : * Get the associated subdomain ID for the subdomain name.
753 : *
754 : * @param subdomain_name The name of the subdomain
755 : * @return The subdomain id from the passed subdomain name.
756 : */
757 : SubdomainID getSubdomainID(const SubdomainName & subdomain_name) const;
758 :
759 : /**
760 : * Get the associated subdomainIDs for the subdomain names that are passed in.
761 : *
762 : * @param subdomain_names The names of the subdomains
763 : * @return The subdomain ids from the passed subdomain names.
764 : */
765 : std::vector<SubdomainID>
766 : getSubdomainIDs(const std::vector<SubdomainName> & subdomain_names) const;
767 : std::set<SubdomainID> getSubdomainIDs(const std::set<SubdomainName> & subdomain_names) const;
768 :
769 : /**
770 : * This method sets the name for \p subdomain_id to \p name
771 : */
772 : void setSubdomainName(SubdomainID subdomain_id, const SubdomainName & name);
773 :
774 : /**
775 : * This method sets the name for \p subdomain_id on the provided \p mesh to \p name
776 : */
777 : static void
778 : setSubdomainName(MeshBase & mesh, SubdomainID subdomain_id, const SubdomainName & name);
779 :
780 : /**
781 : * Return the name of a block given an id.
782 : */
783 : const std::string & getSubdomainName(SubdomainID subdomain_id) const;
784 :
785 : /**
786 : * Get the associated subdomainNames for the subdomain ids that are passed in.
787 : *
788 : * @param subdomain_ids The ids of the subdomains
789 : * @return The subdomain names from the passed subdomain ids.
790 : */
791 : std::vector<SubdomainName>
792 : getSubdomainNames(const std::vector<SubdomainID> & subdomain_ids) const;
793 :
794 : /**
795 : * This method sets the boundary name of the boundary based on the id parameter
796 : */
797 : void setBoundaryName(BoundaryID boundary_id, BoundaryName name);
798 :
799 : /**
800 : * Return the name of the boundary given the id.
801 : */
802 : const std::string & getBoundaryName(BoundaryID boundary_id);
803 :
804 : /**
805 : * This routine builds a multimap of boundary ids to matching boundary ids across all periodic
806 : * boundaries
807 : * in the system.
808 : */
809 : void buildPeriodicNodeMap(std::multimap<dof_id_type, dof_id_type> & periodic_node_map,
810 : unsigned int var_number,
811 : libMesh::PeriodicBoundaries * pbs) const;
812 :
813 : /**
814 : * This routine builds a datastructure of node ids organized by periodic boundary ids
815 : */
816 : void buildPeriodicNodeSets(std::map<BoundaryID, std::set<dof_id_type>> & periodic_node_sets,
817 : unsigned int var_number,
818 : libMesh::PeriodicBoundaries * pbs) const;
819 :
820 : /**
821 : * Returns the width of the requested dimension
822 : */
823 : Real dimensionWidth(unsigned int component) const;
824 :
825 : ///@{
826 : /**
827 : * Returns the min or max of the requested dimension respectively
828 : */
829 : virtual Real getMinInDimension(unsigned int component) const;
830 : virtual Real getMaxInDimension(unsigned int component) const;
831 : ///@}
832 :
833 : /**
834 : * This routine determines whether the Mesh is a regular orthogonal mesh (i.e. square in 2D, cubic
835 : * in 3D). If it is, then we can use a number of convenience functions when periodic boundary
836 : * conditions are applied. This routine populates the _range vector which is necessary for these
837 : * convenience functions.
838 : *
839 : * Note: This routine can potentially identify meshes with concave faces that still "fit" in the
840 : * convex hull of the corresponding regular orthogonal mesh. This case is highly unlikely in
841 : * practice and if a user does this, well.... release the kicker!
842 : */
843 : bool detectOrthogonalDimRanges(Real tol = 1e-6);
844 :
845 : /**
846 : * For "regular orthogonal" meshes, determine if variable var_num is periodic with respect to the
847 : * primary and secondary BoundaryIDs, record this fact in the _periodic_dim data structure.
848 : */
849 : void addPeriodicVariable(unsigned int var_num, BoundaryID primary, BoundaryID secondary);
850 :
851 : /**
852 : * Returns whether this generated mesh is periodic in the given dimension for the given variable.
853 : * @param nonlinear_var_num - The nonlinear variable number
854 : * @param component - An integer representing the desired component (dimension)
855 : */
856 : bool isTranslatedPeriodic(unsigned int nonlinear_var_num, unsigned int component) const;
857 :
858 : /**
859 : * This function returns the minimum vector between two points on the mesh taking into account
860 : * periodicity for the given variable number.
861 : * @param nonlinear_var_num - The nonlinear variable number
862 : * @param p, q - The points between which to compute a minimum vector
863 : * @return RealVectorValue - The vector pointing from p to q
864 : */
865 : RealVectorValue minPeriodicVector(unsigned int nonlinear_var_num, Point p, Point q) const;
866 :
867 : /**
868 : * This function returns the distance between two points on the mesh taking into account
869 : * periodicity for the given variable number.
870 : * @param nonlinear_var_num - The nonlinear variable number
871 : * @param p, q - The points for which to compute a minimum distance
872 : * @return Real - The L2 distance between p and q
873 : */
874 : Real minPeriodicDistance(unsigned int nonlinear_var_num, Point p, Point q) const;
875 :
876 : /**
877 : * This function attempts to return the paired boundary ids for the given component. For example,
878 : * in a generated 2D mesh, passing 0 for the "x" component will return (3, 1).
879 : * @param component - An integer representing the desired component (dimension)
880 : * @return std::pair pointer - The matching boundary pairs for the passed component
881 : */
882 : const std::pair<BoundaryID, BoundaryID> * getPairedBoundaryMapping(unsigned int component);
883 :
884 : /**
885 : * Create the refinement and coarsening maps necessary for projection of stateful material
886 : * properties when using adaptivity.
887 : *
888 : * @param assembly Pointer to the Assembly object for this Mesh.
889 : */
890 : void buildRefinementAndCoarseningMaps(Assembly * assembly);
891 :
892 : /**
893 : * Get the refinement map for a given element type. This will tell you what quadrature points
894 : * to copy from and to for stateful material properties on newly created elements from Adaptivity.
895 : *
896 : * @param elem The element that represents the element type you need the refinement map for.
897 : * @param parent_side The side of the parent to map (-1 if not mapping parent sides)
898 : * @param child The child number (-1 if not mapping child internal sides)
899 : * @param child_side The side number of the child (-1 if not mapping sides)
900 : */
901 : const std::vector<std::vector<QpMap>> &
902 : getRefinementMap(const Elem & elem, int parent_side, int child, int child_side);
903 :
904 : /**
905 : * Get the coarsening map for a given element type. This will tell you what quadrature points
906 : * to copy from and to for stateful material properties on newly created elements from Adaptivity.
907 : *
908 : * @param elem The element that represents the element type you need the coarsening map for.
909 : * @param input_side The side to map
910 : */
911 : const std::vector<std::pair<unsigned int, QpMap>> & getCoarseningMap(const Elem & elem,
912 : int input_side);
913 :
914 : /**
915 : * Change all the boundary IDs for a given side from old_id to new_id. If delete_prev is true,
916 : * also actually remove the side with old_id from the BoundaryInfo object.
917 : */
918 : void
919 : changeBoundaryId(const boundary_id_type old_id, const boundary_id_type new_id, bool delete_prev);
920 :
921 : /**
922 : * Change all the boundary IDs for a given side from old_id to new_id for the given \p mesh. If
923 : * delete_prev is true, also actually remove the side with old_id from the BoundaryInfo object.
924 : */
925 : static void changeBoundaryId(MeshBase & mesh,
926 : const boundary_id_type old_id,
927 : const boundary_id_type new_id,
928 : bool delete_prev);
929 :
930 : /**
931 : * Get the list of boundary ids associated with the given subdomain id.
932 : *
933 : * @param subdomain_id The subdomain ID you want to get the boundary ids for.
934 : * @return All boundary IDs connected to elements in the give
935 : */
936 : const std::set<BoundaryID> & getSubdomainBoundaryIds(const SubdomainID subdomain_id) const;
937 :
938 : /**
939 : * Get the list of boundaries that contact the given subdomain.
940 : *
941 : * @param subdomain_id The subdomain ID you want to get the boundary ids for.
942 : * @return All boundary IDs connected to elements in the given subdomain
943 : */
944 : std::set<BoundaryID> getSubdomainInterfaceBoundaryIds(const SubdomainID subdomain_id) const;
945 :
946 : /**
947 : * Get the list of subdomains associated with the given boundary.
948 : *
949 : * @param bid The boundary ID you want to get the subdomain IDs for.
950 : * @return All subdomain IDs associated with given boundary ID
951 : */
952 : std::set<SubdomainID> getBoundaryConnectedBlocks(const BoundaryID bid) const;
953 :
954 : /**
955 : * Get the list of subdomains associated with the given boundary of its secondary side.
956 : *
957 : * @param bid The boundary ID you want to get the subdomain IDs for.
958 : * @return All subdomain IDs associated with given boundary ID
959 : */
960 : std::set<SubdomainID> getBoundaryConnectedSecondaryBlocks(const BoundaryID bid) const;
961 :
962 : /**
963 : * Get the list of subdomains contacting the given boundary.
964 : *
965 : * @param bid The boundary ID you want to get the subdomain IDs for.
966 : * @return All subdomain IDs contacting given boundary ID
967 : */
968 : std::set<SubdomainID> getInterfaceConnectedBlocks(const BoundaryID bid) const;
969 :
970 : /**
971 : * Get the list of subdomains neighboring a given subdomain.
972 : *
973 : * @param subdomain_id The boundary ID you want to get the subdomain IDs for.
974 : * @return All subdomain IDs neighboring a given subdomain
975 : */
976 : const std::set<SubdomainID> & getBlockConnectedBlocks(const SubdomainID subdomain_id) const;
977 :
978 : /**
979 : * Returns true if the requested node is in the list of boundary nodes, false otherwise.
980 : */
981 : bool isBoundaryNode(dof_id_type node_id) const;
982 :
983 : /**
984 : * Returns true if the requested node is in the list of boundary nodes for the specified boundary,
985 : * false otherwise.
986 : */
987 : bool isBoundaryNode(dof_id_type node_id, BoundaryID bnd_id) const;
988 :
989 : /**
990 : * Returns true if the requested element is in the list of boundary elements, false otherwise.
991 : */
992 : bool isBoundaryElem(dof_id_type elem_id) const;
993 :
994 : /**
995 : * Returns true if the requested element is in the list of boundary elements for the specified
996 : * boundary, false otherwise.
997 : */
998 : bool isBoundaryElem(dof_id_type elem_id, BoundaryID bnd_id) const;
999 :
1000 : /**
1001 : * Generate a unified error message if the underlying libMesh mesh is a DistributedMesh. Clients
1002 : * of MooseMesh can use this function to throw an error if they know they don't work with
1003 : * DistributedMesh.
1004 : *
1005 : * See, for example, the NodalVariableValue class.
1006 : */
1007 : void errorIfDistributedMesh(std::string name) const;
1008 :
1009 : /**
1010 : * Returns the final Mesh distribution type.
1011 : */
1012 67158 : virtual bool isDistributedMesh() const { return _use_distributed_mesh; }
1013 :
1014 : /**
1015 : * Tell the user if the distribution was overriden for any reason
1016 : */
1017 56185 : bool isParallelTypeForced() const { return _parallel_type_overridden; }
1018 :
1019 : /**
1020 : * Allow to change parallel type
1021 : */
1022 : void setParallelType(ParallelType parallel_type);
1023 :
1024 : /**
1025 : * @return The parallel type
1026 : */
1027 1242 : ParallelType getParallelType() const { return _parallel_type; }
1028 :
1029 : /*
1030 : * Set/Get the partitioner name
1031 : */
1032 25668 : const MooseEnum & partitionerName() const { return _partitioner_name; }
1033 :
1034 : /**
1035 : * Tell the user if the partitioner was overriden for any reason
1036 : */
1037 25668 : bool isPartitionerForced() const { return _partitioner_overridden; }
1038 :
1039 : /**
1040 : * Set whether or not this mesh is allowed to read a recovery file.
1041 : */
1042 11 : void allowRecovery(bool allow) { _allow_recovery = allow; }
1043 :
1044 : /**
1045 : * Method for setting the partitioner on the passed in mesh_base object.
1046 : */
1047 : static void setPartitioner(MeshBase & mesh_base,
1048 : MooseEnum & partitioner,
1049 : bool use_distributed_mesh,
1050 : const InputParameters & params,
1051 : MooseObject & context_obj);
1052 :
1053 : /**
1054 : * Setter for custom partitioner
1055 : */
1056 : void setCustomPartitioner(libMesh::Partitioner * partitioner);
1057 :
1058 : ///@{
1059 : /**
1060 : * Setter and getter for _custom_partitioner_requested
1061 : */
1062 : bool isCustomPartitionerRequested() const;
1063 : void setIsCustomPartitionerRequested(bool cpr);
1064 : ///@}
1065 :
1066 : /// Getter to query if the mesh was detected to be regular and orthogonal
1067 1212 : bool isRegularOrthogonal() { return _regular_orthogonal_mesh; }
1068 :
1069 : /// check if the mesh has SECOND order elements
1070 : bool hasSecondOrderElements();
1071 :
1072 : /**
1073 : * Proxy function to get a (sub)PointLocator from either the underlying libMesh mesh (default), or
1074 : * to allow derived meshes to return a custom point locator.
1075 : */
1076 : virtual std::unique_ptr<libMesh::PointLocatorBase> getPointLocator() const;
1077 :
1078 : /**
1079 : * Returns the name of the mesh file read to produce this mesh if any or an empty string
1080 : * otherwise.
1081 : */
1082 522 : virtual std::string getFileName() const { return ""; }
1083 :
1084 : /// Helper type for building periodic node maps
1085 : using PeriodicNodeInfo = std::pair<const Node *, BoundaryID>;
1086 :
1087 : /**
1088 : * Set whether we need to delete remote elements
1089 : */
1090 27 : void needsRemoteElemDeletion(bool need_delete) { _need_delete = need_delete; }
1091 :
1092 : /**
1093 : * Whether we need to delete remote elements
1094 : */
1095 66992 : bool needsRemoteElemDeletion() const { return _need_delete; }
1096 :
1097 : /**
1098 : * Set whether to allow remote element removal
1099 : */
1100 : void allowRemoteElementRemoval(bool allow_removal);
1101 :
1102 : /**
1103 : * Whether we are allow remote element removal
1104 : */
1105 29121 : bool allowRemoteElementRemoval() const { return _allow_remote_element_removal; }
1106 :
1107 : /**
1108 : * Delete remote elements
1109 : */
1110 : void deleteRemoteElements();
1111 :
1112 : /**
1113 : * Whether mesh base object was constructed or not
1114 : */
1115 91571 : bool hasMeshBase() const { return _mesh.get() != nullptr; }
1116 :
1117 : /**
1118 : * Whether mesh has an extra element integer with a given name
1119 : */
1120 : bool hasElementID(const std::string & id_name) const;
1121 :
1122 : /**
1123 : * Return the accessing integer for an extra element integer with its name
1124 : */
1125 : unsigned int getElementIDIndex(const std::string & id_name) const;
1126 :
1127 : /**
1128 : * Return the maximum element ID for an extra element integer with its accessing index
1129 : */
1130 : dof_id_type maxElementID(unsigned int elem_id_index) const { return _max_ids[elem_id_index]; }
1131 :
1132 : /**
1133 : * Return the minimum element ID for an extra element integer with its accessing index
1134 : */
1135 : dof_id_type minElementID(unsigned int elem_id_index) const { return _min_ids[elem_id_index]; }
1136 :
1137 : /**
1138 : * Whether or not two extra element integers are identical
1139 : */
1140 : bool areElemIDsIdentical(const std::string & id_name1, const std::string & id_name2) const;
1141 :
1142 : /**
1143 : * Return all the unique element IDs for an extra element integer with its index
1144 : */
1145 : std::set<dof_id_type> getAllElemIDs(unsigned int elem_id_index) const;
1146 :
1147 : /**
1148 : * Return all the unique element IDs for an extra element integer with its index on a set of
1149 : * subdomains
1150 : */
1151 : std::set<dof_id_type> getElemIDsOnBlocks(unsigned int elem_id_index,
1152 : const std::set<SubdomainID> & blks) const;
1153 :
1154 : /**
1155 : * Get the maximum number of sides per element
1156 : */
1157 4170 : unsigned int getMaxSidesPerElem() const { return _max_sides_per_elem; }
1158 :
1159 : /**
1160 : * Get the maximum number of nodes per element
1161 : */
1162 1392 : unsigned int getMaxNodesPerElem() const { return _max_nodes_per_elem; }
1163 :
1164 : /**
1165 : * Get the maximum number of nodes per side
1166 : */
1167 1392 : unsigned int getMaxNodesPerSide() const { return _max_nodes_per_side; }
1168 :
1169 : std::unordered_map<dof_id_type, std::set<dof_id_type>>
1170 : getElemIDMapping(const std::string & from_id_name, const std::string & to_id_name) const;
1171 :
1172 : ///@{ accessors for the FaceInfo objects
1173 : unsigned int nFace() const { return _face_info.size(); }
1174 :
1175 : /// Accessor for local \p FaceInfo objects.
1176 : const std::vector<const FaceInfo *> & faceInfo() const;
1177 :
1178 : /// Need to declare these iterators here to make sure the iterators below work
1179 : struct face_info_iterator;
1180 : struct const_face_info_iterator;
1181 :
1182 : /// Iterators to owned faceInfo objects. These faceInfo-s are required for the
1183 : /// face loops and to filter out the faceInfo-s that are not owned by this processor
1184 : /// in case we have a distributed mesh and we included FaceInfo objects that
1185 : /// are on processor boundaries
1186 : face_info_iterator ownedFaceInfoBegin();
1187 : face_info_iterator ownedFaceInfoEnd();
1188 :
1189 : /// Need to declare these iterators here to make sure the iterators below work
1190 : struct elem_info_iterator;
1191 : struct const_elem_info_iterator;
1192 :
1193 : /// Iterators to owned faceInfo objects. These faceInfo-s are required for the
1194 : /// face loops and to filter out the faceInfo-s that are not owned by this processor
1195 : /// in case we have a distributed mesh and we included FaceInfo objects that
1196 : /// are on processor boundaries
1197 : elem_info_iterator ownedElemInfoBegin();
1198 : elem_info_iterator ownedElemInfoEnd();
1199 :
1200 : /// Accessor for the local FaceInfo object on the side of one element. Returns null if ghosted.
1201 : const FaceInfo * faceInfo(const Elem * elem, unsigned int side) const;
1202 :
1203 : /// Accessor for the elemInfo object for a given element ID
1204 : const ElemInfo & elemInfo(const dof_id_type id) const;
1205 :
1206 : /// Accessor for the element info objects owned by this process
1207 24 : const std::vector<const ElemInfo *> & elemInfoVector() const { return _elem_info; }
1208 :
1209 : /// Accessor for all \p FaceInfo objects.
1210 : const std::vector<FaceInfo> & allFaceInfo() const;
1211 : ///@}
1212 :
1213 : /**
1214 : * Cache if variables live on the elements connected by the FaceInfo objects
1215 : */
1216 : void cacheFaceInfoVariableOwnership() const;
1217 :
1218 : /**
1219 : * Cache the DoF indices for FV variables on each element. These indices are used to speed up the
1220 : * setup loops of finite volume systems.
1221 : */
1222 : void cacheFVElementalDoFs() const;
1223 :
1224 : /**
1225 : * Compute the face coordinate value for all \p FaceInfo and \p ElemInfo objects. 'Coordinate'
1226 : * here means a coordinate value associated with the coordinate system. For Cartesian coordinate
1227 : * systems, 'coordinate' is simply '1'; in RZ, '2*pi*r', and in spherical, '4*pi*r^2'
1228 : */
1229 : void computeFiniteVolumeCoords() const;
1230 :
1231 : /**
1232 : * Set whether this mesh is a displaced mesh
1233 : */
1234 2257 : void isDisplaced(bool is_displaced) { _is_displaced = is_displaced; }
1235 :
1236 : /**
1237 : * whether this mesh is a displaced mesh
1238 : */
1239 : bool isDisplaced() const { return _is_displaced; }
1240 :
1241 : /**
1242 : * @return A map from nodeset ids to the vector of node ids in the nodeset
1243 : */
1244 : const std::map<boundary_id_type, std::vector<dof_id_type>> & nodeSetNodes() const;
1245 :
1246 : /**
1247 : * Get the coordinate system type, e.g. xyz, rz, or r-spherical, for the provided subdomain id \p
1248 : * sid
1249 : */
1250 : Moose::CoordinateSystemType getCoordSystem(SubdomainID sid) const;
1251 :
1252 : /**
1253 : * Get the coordinate system from the mesh, it must be the same in all subdomains otherwise this
1254 : * will error
1255 : */
1256 : Moose::CoordinateSystemType getUniqueCoordSystem() const;
1257 :
1258 : /**
1259 : * Get the map from subdomain ID to coordinate system type, e.g. xyz, rz, or r-spherical
1260 : */
1261 : const std::map<SubdomainID, Moose::CoordinateSystemType> & getCoordSystem() const;
1262 :
1263 : /**
1264 : * Set the coordinate system for the provided blocks to \p coord_sys
1265 : */
1266 : void setCoordSystem(const std::vector<SubdomainName> & blocks, const MultiMooseEnum & coord_sys);
1267 :
1268 : /**
1269 : * For axisymmetric simulations, set the symmetry coordinate axis. For r in the x-direction, z in
1270 : * the y-direction the coordinate axis would be y
1271 : */
1272 : void setAxisymmetricCoordAxis(const MooseEnum & rz_coord_axis);
1273 :
1274 : /**
1275 : * Sets the general coordinate axes for axisymmetric blocks.
1276 : *
1277 : * This method must be used if any of the following are true:
1278 : * - There are multiple axisymmetric coordinate systems
1279 : * - Any axisymmetric coordinate system axis/direction is not the +X or +Y axis
1280 : * - Any axisymmetric coordinate system does not start at (0,0,0)
1281 : *
1282 : * @param[in] blocks Subdomain names
1283 : * @param[in] axes Pair of values defining the axisymmetric coordinate axis
1284 : * for each subdomain. The first value is the point on the axis
1285 : * corresponding to the origin. The second value is the direction
1286 : * vector of the axis (normalization not necessary).
1287 : */
1288 : void setGeneralAxisymmetricCoordAxes(const std::vector<SubdomainName> & blocks,
1289 : const std::vector<std::pair<Point, RealVectorValue>> & axes);
1290 :
1291 : /**
1292 : * Gets the general axisymmetric coordinate axis for a block.
1293 : *
1294 : * @param[in] subdomain_id Subdomain ID for which to get axisymmetric coordinate axis
1295 : */
1296 : const std::pair<Point, RealVectorValue> &
1297 : getGeneralAxisymmetricCoordAxis(SubdomainID subdomain_id) const;
1298 :
1299 : /**
1300 : * Returns true if general axisymmetric coordinate axes are being used
1301 : */
1302 : bool usingGeneralAxisymmetricCoordAxes() const;
1303 :
1304 : /**
1305 : * Returns the desired radial direction for RZ coordinate transformation
1306 : * @return The coordinate direction for the radial direction
1307 : */
1308 : unsigned int getAxisymmetricRadialCoord() const;
1309 :
1310 : /**
1311 : * Performs a sanity check for every element in the mesh. If an element dimension is 3 and the
1312 : * corresponding coordinate system is RZ, then this will error. If an element dimension is greater
1313 : * than 1 and the corresponding system is RPSHERICAL then this will error
1314 : */
1315 : void checkCoordinateSystems();
1316 :
1317 : /**
1318 : * Set the coordinate system data to that of \p other_mesh
1319 : */
1320 : void setCoordData(const MooseMesh & other_mesh);
1321 :
1322 : /**
1323 : * Mark the finite volume information as dirty
1324 : */
1325 3971 : void markFiniteVolumeInfoDirty() { _finite_volume_info_dirty = true; }
1326 :
1327 : /**
1328 : * @return whether the finite volume information is dirty
1329 : */
1330 1256 : bool isFiniteVolumeInfoDirty() const { return _finite_volume_info_dirty; }
1331 :
1332 : /**
1333 : * @return the coordinate transformation object that describes how to transform this problem's
1334 : * coordinate system into the canonical/reference coordinate system
1335 : */
1336 : MooseAppCoordTransform & coordTransform();
1337 :
1338 : /**
1339 : * @return the length unit of this mesh provided through the coordinate transformation object
1340 : */
1341 : const MooseUnits & lengthUnit() const;
1342 :
1343 : /**
1344 : * This function attempts to return the map from a high-order element side to its corresponding
1345 : * lower-d element
1346 : */
1347 : const std::unordered_map<std::pair<const Elem *, unsigned short int>, const Elem *> &
1348 : getLowerDElemMap() const;
1349 :
1350 : /**
1351 : * @return Whether or not this mesh comes from a split mesh
1352 : */
1353 188813 : bool isSplit() const { return _is_split; }
1354 :
1355 : /**
1356 : * Builds the face and elem info vectors that store meta-data needed for looping over and doing
1357 : * calculations based on mesh faces and elements in a finite volume setting. This should only
1358 : * be called when finite volume variables are used in the problem or when the face and elem info
1359 : * objects are necessary for functor-based evaluations.
1360 : */
1361 : void buildFiniteVolumeInfo() const;
1362 :
1363 : /**
1364 : * Sets up the additional data needed for finite volume computations.
1365 : * This involves building FaceInfo and ElemInfo objects, caching variable associations
1366 : * and elemental DoF indices for FV variables.
1367 : */
1368 : void setupFiniteVolumeMeshData() const;
1369 :
1370 : /**
1371 : * Indicate whether the kind of adaptivity we're doing is p-refinement
1372 : */
1373 221 : void doingPRefinement(bool doing_p_refinement) { _doing_p_refinement = doing_p_refinement; }
1374 :
1375 : /**
1376 : * Query whether we have p-refinement
1377 : */
1378 406818691 : [[nodiscard]] bool doingPRefinement() const { return _doing_p_refinement; }
1379 :
1380 : /**
1381 : * Returns the maximum p-refinement level of all elements
1382 : */
1383 56590 : unsigned int maxPLevel() const { return _max_p_level; }
1384 :
1385 : /**
1386 : * Returns the maximum h-refinement level of all elements
1387 : */
1388 62941 : unsigned int maxHLevel() const { return _max_h_level; }
1389 :
1390 : /**
1391 : * Get the map describing for each volumetric quadrature point (qp) on the refined level which qp
1392 : * on the previous coarser level the fine qp is closest to
1393 : */
1394 : const std::vector<QpMap> & getPRefinementMap(const Elem & elem) const;
1395 : /**
1396 : * Get the map describing for each side quadrature point (qp) on the refined level which qp
1397 : * on the previous coarser level the fine qp is closest to
1398 : */
1399 : const std::vector<QpMap> & getPRefinementSideMap(const Elem & elem) const;
1400 : /**
1401 : * Get the map describing for each volumetric quadrature point (qp) on the coarse level which qp
1402 : * on the previous finer level the coarse qp is closest to
1403 : */
1404 : const std::vector<QpMap> & getPCoarseningMap(const Elem & elem) const;
1405 : /**
1406 : * Get the map describing for each side quadrature point (qp) on the coarse level which qp
1407 : * on the previous finer level the coarse qp is closest to
1408 : */
1409 : const std::vector<QpMap> & getPCoarseningSideMap(const Elem & elem) const;
1410 :
1411 : void buildPRefinementAndCoarseningMaps(Assembly * assembly);
1412 :
1413 : /**
1414 : * @return Whether the subdomain indicated by \p subdomain_id is a lower-dimensional manifold of
1415 : * some higher-dimensional subdomain, or in implementation speak, whether the elements of this
1416 : * subdomain have non-null interior parents
1417 : */
1418 : bool isLowerD(const SubdomainID subdomain_id) const;
1419 :
1420 : /**
1421 : * @return Whether there are any lower-dimensional blocks that are manifolds of higher-dimensional
1422 : * block faces
1423 : */
1424 34418 : bool hasLowerD() const { return _has_lower_d; }
1425 :
1426 : /**
1427 : * @return The set of lower-dimensional blocks for interior sides
1428 : */
1429 436981905 : const std::set<SubdomainID> & interiorLowerDBlocks() const { return _lower_d_interior_blocks; }
1430 : /**
1431 : * @return The set of lower-dimensional blocks for boundary sides
1432 : */
1433 435776360 : const std::set<SubdomainID> & boundaryLowerDBlocks() const { return _lower_d_boundary_blocks; }
1434 : /// Return construct node list from side list boolean
1435 141 : bool getConstructNodeListFromSideList() { return _construct_node_list_from_side_list; }
1436 :
1437 : protected:
1438 : /// Deprecated (DO NOT USE)
1439 : std::vector<std::unique_ptr<libMesh::GhostingFunctor>> _ghosting_functors;
1440 :
1441 : /// The list of active geometric relationship managers (bound to the underlying MeshBase object).
1442 : std::vector<std::shared_ptr<RelationshipManager>> _relationship_managers;
1443 :
1444 : /// Whether or not this mesh was built from another mesh
1445 : bool _built_from_other_mesh = false;
1446 :
1447 : /// Can be set to DISTRIBUTED, REPLICATED, or DEFAULT. Determines whether
1448 : /// the underlying libMesh mesh is a ReplicatedMesh or DistributedMesh.
1449 : ParallelType _parallel_type;
1450 :
1451 : /// False by default. Final value is determined by several factors
1452 : /// including the 'distribution' setting in the input file, and whether
1453 : /// or not the Mesh file is a Nemesis file.
1454 : bool _use_distributed_mesh;
1455 : bool _distribution_overridden;
1456 : bool _parallel_type_overridden;
1457 :
1458 : /// Pointer to underlying libMesh mesh object
1459 : std::unique_ptr<libMesh::MeshBase> _mesh;
1460 :
1461 : /// Pointer to Kokkos mesh object
1462 : #ifdef MOOSE_KOKKOS_ENABLED
1463 : std::unique_ptr<Moose::Kokkos::Mesh> _kokkos_mesh;
1464 : #endif
1465 :
1466 : /// The partitioner used on this mesh
1467 : MooseEnum _partitioner_name;
1468 : bool _partitioner_overridden;
1469 :
1470 : /// The custom partitioner
1471 : std::unique_ptr<libMesh::Partitioner> _custom_partitioner;
1472 : bool _custom_partitioner_requested;
1473 :
1474 : /// Convenience enums
1475 : enum
1476 : {
1477 : X = 0,
1478 : Y,
1479 : Z
1480 : };
1481 : enum
1482 : {
1483 : MIN = 0,
1484 : MAX
1485 : };
1486 :
1487 : /// The level of uniform refinement requested (set to zero if AMR is disabled)
1488 : unsigned int _uniform_refine_level;
1489 :
1490 : /// Whether or not to skip uniform refinements when using a pre-split mesh
1491 : bool _skip_refine_when_use_split;
1492 :
1493 : /// Whether or not skip remote deletion and repartition after uniform refinements
1494 : bool _skip_deletion_repartition_after_refine;
1495 :
1496 : /// true if mesh is changed (i.e. after adaptivity step)
1497 : bool _is_changed;
1498 :
1499 : /// True if a Nemesis Mesh was read in
1500 : bool _is_nemesis;
1501 :
1502 : /// True if prepare has been called on the mesh
1503 : bool _moose_mesh_prepared = false;
1504 :
1505 : /// The elements that were just refined.
1506 : std::unique_ptr<ConstElemPointerRange> _refined_elements;
1507 :
1508 : /// The elements that were just coarsened.
1509 : std::unique_ptr<ConstElemPointerRange> _coarsened_elements;
1510 :
1511 : /**
1512 : * Map of Parent elements to child elements for elements that were just coarsened.
1513 : *
1514 : * NOTE: the child element pointers ARE PROBABLY INVALID. Only use them for indexing!
1515 : */
1516 : std::map<const Elem *, std::vector<const Elem *>> _coarsened_element_children;
1517 :
1518 : /// Used for generating the semilocal node range
1519 : std::set<Node *> _semilocal_node_list;
1520 :
1521 : /**
1522 : * A range for use with threading. We do this so that it doesn't have
1523 : * to get rebuilt all the time (which takes time).
1524 : */
1525 : std::unique_ptr<libMesh::ConstElemRange> _active_local_elem_range;
1526 :
1527 : std::unique_ptr<SemiLocalNodeRange> _active_semilocal_node_range;
1528 : std::unique_ptr<libMesh::NodeRange> _active_node_range;
1529 : std::unique_ptr<libMesh::ConstNodeRange> _local_node_range;
1530 : std::unique_ptr<libMesh::StoredRange<MooseMesh::const_bnd_node_iterator, const BndNode *>>
1531 : _bnd_node_range;
1532 : std::unique_ptr<libMesh::StoredRange<MooseMesh::const_bnd_elem_iterator, const BndElement *>>
1533 : _bnd_elem_range;
1534 :
1535 : /// A map of all of the current nodes to the elements that they are connected to.
1536 : std::map<dof_id_type, std::vector<dof_id_type>> _node_to_elem_map;
1537 : bool _node_to_elem_map_built;
1538 :
1539 : /// A map of all of the current nodes to the active elements that they are connected to.
1540 : std::map<dof_id_type, std::vector<dof_id_type>> _node_to_active_semilocal_elem_map;
1541 : bool _node_to_active_semilocal_elem_map_built;
1542 :
1543 : /**
1544 : * A set of subdomain IDs currently present in the mesh. For parallel meshes, includes subdomains
1545 : * defined on other processors as well.
1546 : */
1547 : std::set<SubdomainID> _mesh_subdomains;
1548 :
1549 : ///@{
1550 : /**
1551 : * A set of boundary IDs currently present in the mesh. In serial, this is equivalent to the
1552 : * values returned by _mesh.get_boundary_info().get_boundary_ids(). In parallel, it will contain
1553 : * off-processor boundary IDs as well.
1554 : */
1555 : std::set<BoundaryID> _mesh_boundary_ids;
1556 : std::set<BoundaryID> _mesh_sideset_ids;
1557 : std::set<BoundaryID> _mesh_nodeset_ids;
1558 : ///@}
1559 :
1560 : /// The boundary to normal map - valid only when AddAllSideSetsByNormals is active
1561 : std::unique_ptr<std::map<BoundaryID, RealVectorValue>> _boundary_to_normal_map;
1562 :
1563 : /// array of boundary nodes
1564 : std::vector<BndNode *> _bnd_nodes;
1565 : typedef std::vector<BndNode *>::iterator bnd_node_iterator_imp;
1566 : typedef std::vector<BndNode *>::const_iterator const_bnd_node_iterator_imp;
1567 : /// Map of sets of node IDs in each boundary
1568 : std::map<boundary_id_type, std::set<dof_id_type>> _bnd_node_ids;
1569 :
1570 : /// array of boundary elems
1571 : std::vector<BndElement *> _bnd_elems;
1572 : typedef std::vector<BndElement *>::iterator bnd_elem_iterator_imp;
1573 : typedef std::vector<BndElement *>::const_iterator const_bnd_elem_iterator_imp;
1574 :
1575 : /// Map of set of elem IDs connected to each boundary
1576 : std::unordered_map<boundary_id_type, std::unordered_set<dof_id_type>> _bnd_elem_ids;
1577 :
1578 : std::map<dof_id_type, Node *> _quadrature_nodes;
1579 : std::map<dof_id_type, std::map<unsigned int, std::map<dof_id_type, Node *>>>
1580 : _elem_to_side_to_qp_to_quadrature_nodes;
1581 : std::vector<BndNode> _extra_bnd_nodes;
1582 :
1583 : /// list of nodes that belongs to a specified block (domain)
1584 : std::map<dof_id_type, std::set<SubdomainID>> _block_node_list;
1585 :
1586 : /// list of nodes that belongs to a specified nodeset: indexing [nodeset_id] -> [array of node ids]
1587 : std::map<boundary_id_type, std::vector<dof_id_type>> _node_set_nodes;
1588 :
1589 : std::set<unsigned int> _ghosted_boundaries;
1590 : std::vector<Real> _ghosted_boundaries_inflation;
1591 :
1592 : /// The number of nodes to consider in the NearestNode neighborhood.
1593 : unsigned int _patch_size;
1594 :
1595 : /// The number of nearest neighbors to consider for ghosting purposes when iteration patch update strategy is used.
1596 : unsigned int _ghosting_patch_size;
1597 :
1598 : // The maximum number of points in each leaf of the KDTree used in the nearest neighbor search.
1599 : unsigned int _max_leaf_size;
1600 :
1601 : /// The patch update strategy
1602 : Moose::PatchUpdateType _patch_update_strategy;
1603 :
1604 : /// Vector of all the Nodes in the mesh for determining when to add a new point
1605 : std::vector<Node *> _node_map;
1606 :
1607 : /// Boolean indicating whether this mesh was detected to be regular and orthogonal
1608 : bool _regular_orthogonal_mesh;
1609 :
1610 : /// The bounds in each dimension of the mesh for regular orthogonal meshes
1611 : std::vector<std::vector<Real>> _bounds;
1612 :
1613 : /// A vector holding the paired boundaries for a regular orthogonal mesh
1614 : std::vector<std::pair<BoundaryID, BoundaryID>> _paired_boundary;
1615 :
1616 : /// Whether or not we are using a (pre-)split mesh (automatically DistributedMesh)
1617 : const bool _is_split;
1618 :
1619 : void cacheInfo();
1620 : void freeBndNodes();
1621 : void freeBndElems();
1622 : void setPartitionerHelper(MeshBase * mesh = nullptr);
1623 :
1624 : private:
1625 : /// Map connecting elems with their corresponding ElemInfo, we use the element ID as
1626 : /// the key
1627 : mutable std::unordered_map<dof_id_type, ElemInfo> _elem_to_elem_info;
1628 :
1629 : /// Holds only those \p ElemInfo objects that have \p processor_id equal to this process's id,
1630 : /// e.g. the local \p ElemInfo objects
1631 : mutable std::vector<const ElemInfo *> _elem_info;
1632 :
1633 : /// FaceInfo object storing information for face based loops. This container holds all the \p
1634 : /// FaceInfo objects accessible from this process
1635 : mutable std::vector<FaceInfo> _all_face_info;
1636 :
1637 : /// Holds only those \p FaceInfo objects that have \p processor_id equal to this process's id,
1638 : /// e.g. the local \p FaceInfo objects
1639 : mutable std::vector<const FaceInfo *> _face_info;
1640 :
1641 : /// Map from elem-side pair to FaceInfo
1642 : mutable std::unordered_map<std::pair<const Elem *, unsigned int>, FaceInfo *>
1643 : _elem_side_to_face_info;
1644 :
1645 : // true if the _face_info member needs to be rebuilt/updated.
1646 : mutable bool _finite_volume_info_dirty = true;
1647 :
1648 : // True if we have cached elemental dofs ids for the linear finite volume variables.
1649 : // This happens in the first system which has a linear finite volume variable, considering
1650 : // that currently we only support one variable per linear system.
1651 : mutable bool _linear_finite_volume_dofs_cached = false;
1652 :
1653 : /**
1654 : * A map of vectors indicating which dimensions are periodic in a regular orthogonal mesh for
1655 : * the specified variable numbers. This data structure is populated by addPeriodicVariable.
1656 : */
1657 : std::map<unsigned int, std::vector<bool>> _periodic_dim;
1658 :
1659 : /**
1660 : * A convenience vector used to hold values in each dimension representing half of the range.
1661 : */
1662 : RealVectorValue _half_range;
1663 :
1664 : /// A vector containing the nodes at the corners of a regular orthogonal mesh
1665 : std::vector<Node *> _extreme_nodes;
1666 :
1667 : /**
1668 : * This routine detects paired sidesets of a regular orthogonal mesh (.i.e. parallel sidesets
1669 : * "across" from one and other).
1670 : * The _paired_boundary datastructure is populated with this information.
1671 : */
1672 : void detectPairedSidesets();
1673 :
1674 : /**
1675 : * Build the refinement map for a given element type. This will tell you what quadrature points
1676 : * to copy from and to for stateful material properties on newly created elements from Adaptivity.
1677 : *
1678 : * @param elem The element that represents the element type you need the refinement map for.
1679 : * @param qrule The quadrature rule in use.
1680 : * @param qrule_face The current face quadrature rule
1681 : * @param parent_side The side of the parent to map (-1 if not mapping parent sides)
1682 : * @param child The child number (-1 if not mapping child internal sides)
1683 : * @param child_side The side number of the child (-1 if not mapping sides)
1684 : */
1685 : void buildRefinementMap(const Elem & elem,
1686 : libMesh::QBase & qrule,
1687 : libMesh::QBase & qrule_face,
1688 : int parent_side,
1689 : int child,
1690 : int child_side);
1691 :
1692 : /**
1693 : * Build the coarsening map for a given element type. This will tell you what quadrature points
1694 : * to copy from and to for stateful material properties on newly created elements from Adaptivity.
1695 : *
1696 : * @param elem The element that represents the element type you need the coarsening map for.
1697 : * @param qrule The quadrature rule in use.
1698 : * @param qrule_face The current face quadrature rule
1699 : * @param input_side The side to map
1700 : */
1701 : void buildCoarseningMap(const Elem & elem,
1702 : libMesh::QBase & qrule,
1703 : libMesh::QBase & qrule_face,
1704 : int input_side);
1705 :
1706 : /**
1707 : * Find the closest points that map "from" to "to" and fill up "qp_map".
1708 : * Essentially, for each point in "from" find the closest point in "to".
1709 : *
1710 : * @param from The reference positions in the parent of the the points we're mapping _from_
1711 : * @param to The reference positions in the parent of the the points we're mapping _to_
1712 : * @param qp_map This will be filled with QpMap objects holding the mappings.
1713 : */
1714 : void mapPoints(const std::vector<Point> & from,
1715 : const std::vector<Point> & to,
1716 : std::vector<QpMap> & qp_map);
1717 :
1718 : /**
1719 : * Given an elem type, get maps that tell us what qp's are closest to each other between a parent
1720 : * and it's children.
1721 : * This is mainly used for mapping stateful material properties during adaptivity.
1722 : *
1723 : * There are 3 cases here:
1724 : *
1725 : * 1. Volume to volume (parent_side = -1, child = -1, child_side = -1)
1726 : * 2. Parent side to child side (parent_side = 0+, child = -1, child_side = 0+)
1727 : * 3. Child side to parent volume (parent_side = -1, child = 0+, child_side = 0+)
1728 : *
1729 : * Case 3 only happens under refinement (need to invent data at internal child sides).
1730 : *
1731 : * @param template_elem An element of the type that we need to find the maps for
1732 : * @param qrule The quadrature rule that we need to find the maps for
1733 : * @param qrule_face The face quadrature rule that we need to find the maps for
1734 : * @param refinement_map The map to use when an element gets split
1735 : * @param coarsen_map The map to use when an element is coarsened.
1736 : * @param parent_side - the id of the parent's side
1737 : * @param child - the id of the child element
1738 : * @param child_side - The id of the child's side
1739 : */
1740 : void findAdaptivityQpMaps(const Elem * template_elem,
1741 : libMesh::QBase & qrule,
1742 : libMesh::QBase & qrule_face,
1743 : std::vector<std::vector<QpMap>> & refinement_map,
1744 : std::vector<std::pair<unsigned int, QpMap>> & coarsen_map,
1745 : int parent_side,
1746 : int child,
1747 : int child_side);
1748 :
1749 : void buildHRefinementAndCoarseningMaps(Assembly * assembly);
1750 :
1751 : const std::vector<QpMap> & getPRefinementMapHelper(
1752 : const Elem & elem,
1753 : const std::map<std::pair<libMesh::ElemType, unsigned int>, std::vector<QpMap>> &) const;
1754 : const std::vector<QpMap> & getPCoarseningMapHelper(
1755 : const Elem & elem,
1756 : const std::map<std::pair<libMesh::ElemType, unsigned int>, std::vector<QpMap>> &) const;
1757 :
1758 : /**
1759 : * Update the coordinate transformation object based on our coordinate system data. The coordinate
1760 : * transformation will be created if it hasn't been already
1761 : */
1762 : void updateCoordTransform();
1763 :
1764 : /**
1765 : * Loop through all subdomain IDs and check if there is name duplication used for the subdomains
1766 : * with same ID. Throw out an error if any name duplication is found.
1767 : */
1768 : void checkDuplicateSubdomainNames();
1769 :
1770 : /// Holds mappings for volume to volume and parent side to child side
1771 : /// Map key:
1772 : /// - first member corresponds to element side. It's -1 for volume quadrature points
1773 : /// - second member correponds to the element type
1774 : /// Map value:
1775 : /// - Outermost index is the child element index
1776 : /// - Once we have indexed by the child element index, we have a std::vector of QpMaps. This
1777 : /// vector is sized by the number of reference points in the child element. Then for each
1778 : /// reference point in the child element we have a QpMap whose \p _from index corresponds to
1779 : /// the child element reference point, a \p _to index which corresponds to the reference point
1780 : /// on the parent element that the child element reference point is closest to, and a
1781 : /// \p _distance member which is the distance between the mapped child and parent reference
1782 : /// quadrature points
1783 : std::map<std::pair<int, libMesh::ElemType>, std::vector<std::vector<QpMap>>>
1784 : _elem_type_to_refinement_map;
1785 :
1786 : std::map<std::pair<libMesh::ElemType, unsigned int>, std::vector<QpMap>>
1787 : _elem_type_to_p_refinement_map;
1788 : std::map<std::pair<libMesh::ElemType, unsigned int>, std::vector<QpMap>>
1789 : _elem_type_to_p_refinement_side_map;
1790 :
1791 : /// Holds mappings for "internal" child sides to parent volume. The second key is (child, child_side).
1792 : std::map<libMesh::ElemType, std::map<std::pair<int, int>, std::vector<std::vector<QpMap>>>>
1793 : _elem_type_to_child_side_refinement_map;
1794 :
1795 : /// Holds mappings for volume to volume and parent side to child side
1796 : /// Map key:
1797 : /// - first member corresponds to element side. It's -1 for volume quadrature points
1798 : /// - second member correponds to the element type
1799 : /// Map value:
1800 : /// - Vector is sized based on the number of quadrature points in the parent (e.g. coarser)
1801 : /// element.
1802 : /// - For each parent quadrature point we store a pair
1803 : /// - The first member of the pair identifies which child holds the closest refined-level
1804 : /// quadrature point
1805 : /// - The second member of the pair is the QpMap. The \p _from data member will correspond to
1806 : /// the parent quadrature point index. The \p _to data member will correspond to which child
1807 : /// element quadrature point is closest to the parent quadrature point. And \p _distance is
1808 : /// the distance between the two
1809 : std::map<std::pair<int, libMesh::ElemType>, std::vector<std::pair<unsigned int, QpMap>>>
1810 : _elem_type_to_coarsening_map;
1811 :
1812 : std::map<std::pair<libMesh::ElemType, unsigned int>, std::vector<QpMap>>
1813 : _elem_type_to_p_coarsening_map;
1814 : std::map<std::pair<libMesh::ElemType, unsigned int>, std::vector<QpMap>>
1815 : _elem_type_to_p_coarsening_side_map;
1816 :
1817 : struct SubdomainData
1818 : {
1819 : /// Neighboring subdomain ids
1820 : std::set<SubdomainID> neighbor_subs;
1821 :
1822 : /// The boundary ids that are attached. This set will include any sideset boundary ID that
1823 : /// is a side of any part of the subdomain
1824 : std::set<BoundaryID> boundary_ids;
1825 :
1826 : /// Whether this subdomain is a lower-dimensional manifold of a higher-dimensional subdomain
1827 : bool is_lower_d;
1828 : };
1829 :
1830 : /// Holds a map from subdomain ids to associated data
1831 : std::unordered_map<SubdomainID, SubdomainData> _sub_to_data;
1832 :
1833 : /// Holds a map from neighbor subomdain ids to the boundary ids that are attached to it
1834 : std::unordered_map<SubdomainID, std::set<BoundaryID>> _neighbor_subdomain_boundary_ids;
1835 :
1836 : /// Mesh blocks for interior lower-d elements in different types
1837 : std::set<SubdomainID> _lower_d_interior_blocks;
1838 : /// Mesh blocks for boundary lower-d elements in different types
1839 : std::set<SubdomainID> _lower_d_boundary_blocks;
1840 : /// Holds a map from a high-order element side to its corresponding lower-d element
1841 : std::unordered_map<std::pair<const Elem *, unsigned short int>, const Elem *>
1842 : _higher_d_elem_side_to_lower_d_elem;
1843 : std::unordered_map<const Elem *, unsigned short int> _lower_d_elem_to_higher_d_elem_side;
1844 :
1845 : /// Whether there are any lower-dimensional blocks that are manifolds of higher-dimensional block
1846 : /// faces
1847 : bool _has_lower_d;
1848 :
1849 : /// Whether or not this Mesh is allowed to read a recovery file
1850 : bool _allow_recovery;
1851 :
1852 : /// Whether or not to allow generation of nodesets from sidesets
1853 : bool _construct_node_list_from_side_list;
1854 :
1855 : /// Whether we need to delete remote elements after init'ing the EquationSystems
1856 : bool _need_delete;
1857 :
1858 : /// Whether to allow removal of remote elements
1859 : bool _allow_remote_element_removal;
1860 :
1861 : /// Set of elements ghosted by ghostGhostedBoundaries
1862 : std::set<Elem *> _ghost_elems_from_ghost_boundaries;
1863 :
1864 : /// A parallel mesh generator such as DistributedRectilinearMeshGenerator
1865 : /// already make everything ready. We do not need to gather all boundaries to
1866 : /// every single processor. In general, we should avoid using ghostGhostedBoundaries
1867 : /// when possible since it is not scalable
1868 : bool _need_ghost_ghosted_boundaries;
1869 :
1870 : /// Unique element integer IDs for each subdomain and each extra element integers
1871 : std::vector<std::unordered_map<SubdomainID, std::set<dof_id_type>>> _block_id_mapping;
1872 : /// Maximum integer ID for each extra element integer
1873 : std::vector<dof_id_type> _max_ids;
1874 : /// Minimum integer ID for each extra element integer
1875 : std::vector<dof_id_type> _min_ids;
1876 : /// Flags to indicate whether or not any two extra element integers are the same
1877 : std::vector<std::vector<bool>> _id_identical_flag;
1878 :
1879 : /// The maximum number of sides per element
1880 : unsigned int _max_sides_per_elem;
1881 :
1882 : /// The maximum number of nodes per element
1883 : unsigned int _max_nodes_per_elem;
1884 :
1885 : /// The maximum number of nodes per side
1886 : unsigned int _max_nodes_per_side;
1887 :
1888 : /// Compute the maximum numbers per element and side
1889 : void computeMaxPerElemAndSide();
1890 :
1891 : /// Whether this mesh is displaced
1892 : bool _is_displaced;
1893 :
1894 : /// Build extra data for faster access to the information of extra element integers
1895 : void buildElemIDInfo();
1896 :
1897 : /// Build lower-d mesh for all sides
1898 : void buildLowerDMesh();
1899 :
1900 : /// Type of coordinate system per subdomain
1901 : std::map<SubdomainID, Moose::CoordinateSystemType> & _coord_sys;
1902 :
1903 : /// Storage for RZ axis selection
1904 : unsigned int _rz_coord_axis;
1905 :
1906 : /// Map of subdomain ID to general axisymmetric axis
1907 : std::unordered_map<SubdomainID, std::pair<Point, RealVectorValue>> _subdomain_id_to_rz_coord_axis;
1908 :
1909 : /// A coordinate transformation object that describes how to transform this problem's coordinate
1910 : /// system into the canonical/reference coordinate system
1911 : std::unique_ptr<MooseAppCoordTransform> _coord_transform;
1912 :
1913 : /// Whether the coordinate system has been set
1914 : bool _coord_system_set;
1915 :
1916 : /// Set for holding user-provided coordinate system type block names
1917 : std::vector<SubdomainName> _provided_coord_blocks;
1918 :
1919 : /// Whether we have p-refinement (as opposed to h-refinement)
1920 : bool _doing_p_refinement;
1921 : /// Maximum p-refinement level of all elements
1922 : unsigned int _max_p_level;
1923 : /// Maximum h-refinement level of all elements
1924 : unsigned int _max_h_level;
1925 :
1926 : template <typename T>
1927 : struct MeshType;
1928 : };
1929 :
1930 : inline MooseAppCoordTransform &
1931 167172 : MooseMesh::coordTransform()
1932 : {
1933 : mooseAssert(_coord_transform, "The coordinate transformation object is null.");
1934 167172 : return *_coord_transform;
1935 : }
1936 :
1937 : template <>
1938 : struct MooseMesh::MeshType<libMesh::ReplicatedMesh>
1939 : {
1940 : static const ParallelType value = ParallelType::REPLICATED;
1941 : };
1942 :
1943 : template <>
1944 : struct MooseMesh::MeshType<libMesh::DistributedMesh>
1945 : {
1946 : static const ParallelType value = ParallelType::DISTRIBUTED;
1947 : };
1948 :
1949 : /**
1950 : * The definition of the face_info_iterator struct.
1951 : */
1952 : struct MooseMesh::face_info_iterator
1953 : : variant_filter_iterator<MeshBase::Predicate, const FaceInfo *>
1954 : {
1955 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
1956 : template <typename PredType, typename IterType>
1957 414090 : face_info_iterator(const IterType & d, const IterType & e, const PredType & p)
1958 414090 : : variant_filter_iterator<MeshBase::Predicate, const FaceInfo *>(d, e, p)
1959 : {
1960 414090 : }
1961 : };
1962 :
1963 : /**
1964 : * The definition of the const_face_info_iterator struct. It is similar to the
1965 : * iterator above, but also provides an additional conversion-to-const ctor.
1966 : */
1967 : struct MooseMesh::const_face_info_iterator : variant_filter_iterator<MeshBase::Predicate,
1968 : const FaceInfo * const,
1969 : const FaceInfo * const &,
1970 : const FaceInfo * const *>
1971 : {
1972 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
1973 : template <typename PredType, typename IterType>
1974 : const_face_info_iterator(const IterType & d, const IterType & e, const PredType & p)
1975 : : variant_filter_iterator<MeshBase::Predicate,
1976 : const FaceInfo * const,
1977 : const FaceInfo * const &,
1978 : const FaceInfo * const *>(d, e, p)
1979 : {
1980 : }
1981 :
1982 : // The conversion-to-const ctor. Takes a regular iterator and calls the appropriate
1983 : // variant_filter_iterator copy constructor. Note that this one is *not* templated!
1984 414090 : const_face_info_iterator(const MooseMesh::face_info_iterator & rhs)
1985 414090 : : variant_filter_iterator<MeshBase::Predicate,
1986 : const FaceInfo * const,
1987 : const FaceInfo * const &,
1988 414090 : const FaceInfo * const *>(rhs)
1989 : {
1990 414090 : }
1991 : };
1992 :
1993 : /**
1994 : * The definition of the elem_info_iterator struct.
1995 : */
1996 : struct MooseMesh::elem_info_iterator
1997 : : variant_filter_iterator<MeshBase::Predicate, const ElemInfo *>
1998 : {
1999 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2000 : template <typename PredType, typename IterType>
2001 44656 : elem_info_iterator(const IterType & d, const IterType & e, const PredType & p)
2002 44656 : : variant_filter_iterator<MeshBase::Predicate, const ElemInfo *>(d, e, p)
2003 : {
2004 44656 : }
2005 : };
2006 :
2007 : /**
2008 : * The definition of the const_elem_info_iterator struct. It is similar to the
2009 : * iterator above, but also provides an additional conversion-to-const ctor.
2010 : */
2011 : struct MooseMesh::const_elem_info_iterator : variant_filter_iterator<MeshBase::Predicate,
2012 : const ElemInfo * const,
2013 : const ElemInfo * const &,
2014 : const ElemInfo * const *>
2015 : {
2016 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2017 : template <typename PredType, typename IterType>
2018 : const_elem_info_iterator(const IterType & d, const IterType & e, const PredType & p)
2019 : : variant_filter_iterator<MeshBase::Predicate,
2020 : const ElemInfo * const,
2021 : const ElemInfo * const &,
2022 : const ElemInfo * const *>(d, e, p)
2023 : {
2024 : }
2025 :
2026 : // The conversion-to-const ctor. Takes a regular iterator and calls the appropriate
2027 : // variant_filter_iterator copy constructor. Note that this one is *not* templated!
2028 44656 : const_elem_info_iterator(const MooseMesh::elem_info_iterator & rhs)
2029 44656 : : variant_filter_iterator<MeshBase::Predicate,
2030 : const ElemInfo * const,
2031 : const ElemInfo * const &,
2032 44656 : const ElemInfo * const *>(rhs)
2033 : {
2034 44656 : }
2035 : };
2036 :
2037 : /**
2038 : * The definition of the bnd_node_iterator struct.
2039 : */
2040 : struct MooseMesh::bnd_node_iterator : variant_filter_iterator<MeshBase::Predicate, BndNode *>
2041 : {
2042 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2043 : template <typename PredType, typename IterType>
2044 176394 : bnd_node_iterator(const IterType & d, const IterType & e, const PredType & p)
2045 176394 : : variant_filter_iterator<MeshBase::Predicate, BndNode *>(d, e, p)
2046 : {
2047 176394 : }
2048 : };
2049 :
2050 : /**
2051 : * The definition of the const_bnd_node_iterator struct. It is similar to the
2052 : * iterator above, but also provides an additional conversion-to-const ctor.
2053 : */
2054 : struct MooseMesh::const_bnd_node_iterator : variant_filter_iterator<MeshBase::Predicate,
2055 : BndNode * const,
2056 : BndNode * const &,
2057 : BndNode * const *>
2058 : {
2059 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2060 : template <typename PredType, typename IterType>
2061 4382 : const_bnd_node_iterator(const IterType & d, const IterType & e, const PredType & p)
2062 : : variant_filter_iterator<MeshBase::Predicate,
2063 : BndNode * const,
2064 : BndNode * const &,
2065 4382 : BndNode * const *>(d, e, p)
2066 : {
2067 4382 : }
2068 :
2069 : // The conversion-to-const ctor. Takes a regular iterator and calls the appropriate
2070 : // variant_filter_iterator copy constructor. Note that this one is *not* templated!
2071 176394 : const_bnd_node_iterator(const MooseMesh::bnd_node_iterator & rhs)
2072 176394 : : variant_filter_iterator<MeshBase::Predicate,
2073 : BndNode * const,
2074 : BndNode * const &,
2075 176394 : BndNode * const *>(rhs)
2076 : {
2077 176394 : }
2078 : };
2079 :
2080 : /**
2081 : * The definition of the bnd_elem_iterator struct.
2082 : */
2083 : struct MooseMesh::bnd_elem_iterator : variant_filter_iterator<MeshBase::Predicate, BndElement *>
2084 : {
2085 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2086 : template <typename PredType, typename IterType>
2087 176392 : bnd_elem_iterator(const IterType & d, const IterType & e, const PredType & p)
2088 176392 : : variant_filter_iterator<MeshBase::Predicate, BndElement *>(d, e, p)
2089 : {
2090 176392 : }
2091 : };
2092 :
2093 : /**
2094 : * The definition of the const_bnd_elem_iterator struct. It is similar to the regular
2095 : * iterator above, but also provides an additional conversion-to-const ctor.
2096 : */
2097 : struct MooseMesh::const_bnd_elem_iterator : variant_filter_iterator<MeshBase::Predicate,
2098 : BndElement * const,
2099 : BndElement * const &,
2100 : BndElement * const *>
2101 : {
2102 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2103 : template <typename PredType, typename IterType>
2104 : const_bnd_elem_iterator(const IterType & d, const IterType & e, const PredType & p)
2105 : : variant_filter_iterator<MeshBase::Predicate,
2106 : BndElement * const,
2107 : BndElement * const &,
2108 : BndElement * const *>(d, e, p)
2109 : {
2110 : }
2111 :
2112 : // The conversion-to-const ctor. Takes a regular iterator and calls the appropriate
2113 : // variant_filter_iterator copy constructor. Note that this one is *not* templated!
2114 176052 : const_bnd_elem_iterator(const bnd_elem_iterator & rhs)
2115 176052 : : variant_filter_iterator<MeshBase::Predicate,
2116 : BndElement * const,
2117 : BndElement * const &,
2118 176052 : BndElement * const *>(rhs)
2119 : {
2120 176052 : }
2121 : };
2122 :
2123 : /**
2124 : * Some useful StoredRange typedefs. These are defined *outside* the
2125 : * MooseMesh class to mimic the Const{Node,Elem}Range classes in libmesh.
2126 : */
2127 : typedef libMesh::StoredRange<MooseMesh::const_bnd_node_iterator, const BndNode *> ConstBndNodeRange;
2128 : typedef libMesh::StoredRange<MooseMesh::const_bnd_elem_iterator, const BndElement *>
2129 : ConstBndElemRange;
2130 :
2131 : template <typename T>
2132 : std::unique_ptr<T>
2133 71915 : MooseMesh::buildTypedMesh(unsigned int dim)
2134 : {
2135 : // If the requested mesh type to build doesn't match our current value for _use_distributed_mesh,
2136 : // then we need to make sure to make our state consistent because other objects, like the periodic
2137 : // boundary condition action, will be querying isDistributedMesh()
2138 71915 : if (_use_distributed_mesh != std::is_same<T, libMesh::DistributedMesh>::value)
2139 : {
2140 835 : if (getMeshPtr())
2141 0 : mooseError("A MooseMesh object is being asked to build a libMesh mesh that is a different "
2142 : "parallel type than the libMesh mesh that it wraps. This is not allowed. Please "
2143 : "create another MooseMesh object to wrap the new libMesh mesh");
2144 835 : setParallelType(MeshType<T>::value);
2145 : }
2146 :
2147 71915 : if (dim == libMesh::invalid_uint)
2148 : {
2149 151821 : if (isParamValid("dim"))
2150 124644 : dim = getParam<MooseEnum>("dim");
2151 : else
2152 : // Legacy selection of the default for the 'dim' parameter
2153 9059 : dim = 1;
2154 : }
2155 :
2156 71915 : auto mesh = std::make_unique<T>(_communicator, dim);
2157 :
2158 215745 : if (!getParam<bool>("allow_renumbering"))
2159 1720 : mesh->allow_renumbering(false);
2160 :
2161 71915 : mesh->allow_remote_element_removal(_allow_remote_element_removal);
2162 71915 : _app.attachRelationshipManagers(*mesh, *this);
2163 :
2164 71915 : if (_custom_partitioner_requested)
2165 : {
2166 : // Check of partitioner is supplied (not allowed if custom partitioner is used)
2167 5160 : if (!parameters().isParamSetByAddParam("partitioner"))
2168 0 : mooseError("If partitioner block is provided, partitioner keyword cannot be used!");
2169 : // Set custom partitioner
2170 1720 : if (!_custom_partitioner.get())
2171 0 : mooseError("Custom partitioner requested but not set!");
2172 1720 : mesh->partitioner() = _custom_partitioner->clone();
2173 : }
2174 : else
2175 70195 : setPartitionerHelper(mesh.get());
2176 :
2177 71915 : return mesh;
2178 0 : }
2179 :
2180 : inline bool
2181 5152 : MooseMesh::skipDeletionRepartitionAfterRefine() const
2182 : {
2183 5152 : return _skip_deletion_repartition_after_refine;
2184 : }
2185 :
2186 : inline void
2187 902 : MooseMesh::setParallelType(ParallelType parallel_type)
2188 : {
2189 902 : _parallel_type = parallel_type;
2190 902 : determineUseDistributedMesh();
2191 902 : }
2192 :
2193 : inline bool
2194 : MooseMesh::hasElementID(const std::string & id_name) const
2195 : {
2196 : return getMesh().has_elem_integer(id_name);
2197 : }
2198 :
2199 : inline unsigned int
2200 : MooseMesh::getElementIDIndex(const std::string & id_name) const
2201 : {
2202 : if (!hasElementID(id_name))
2203 : mooseError("Mesh does not have element ID for ", id_name);
2204 : return getMesh().get_elem_integer_index(id_name);
2205 : }
2206 :
2207 : inline bool
2208 : MooseMesh::areElemIDsIdentical(const std::string & id_name1, const std::string & id_name2) const
2209 : {
2210 : auto id1 = getElementIDIndex(id_name1);
2211 : auto id2 = getElementIDIndex(id_name2);
2212 : return _id_identical_flag[id1][id2];
2213 : }
2214 :
2215 : inline const std::vector<const FaceInfo *> &
2216 43 : MooseMesh::faceInfo() const
2217 : {
2218 43 : return _face_info;
2219 : }
2220 :
2221 : inline const std::vector<FaceInfo> &
2222 4 : MooseMesh::allFaceInfo() const
2223 : {
2224 4 : return _all_face_info;
2225 : }
2226 :
2227 : inline const std::map<boundary_id_type, std::vector<dof_id_type>> &
2228 : MooseMesh::nodeSetNodes() const
2229 : {
2230 : return _node_set_nodes;
2231 : }
2232 :
2233 : inline const std::unordered_map<std::pair<const Elem *, unsigned short int>, const Elem *> &
2234 : MooseMesh::getLowerDElemMap() const
2235 : {
2236 : return _higher_d_elem_side_to_lower_d_elem;
2237 : }
2238 :
2239 : inline bool
2240 506085 : MooseMesh::isLowerD(const SubdomainID subdomain_id) const
2241 : {
2242 506085 : return libmesh_map_find(_sub_to_data, subdomain_id).is_lower_d;
2243 : }
|