Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 :
20 : #ifndef LIBMESH_MESH_BASE_H
21 : #define LIBMESH_MESH_BASE_H
22 :
23 : // Local Includes
24 : #include "libmesh/dof_object.h" // for invalid_processor_id
25 : #include "libmesh/enum_order.h"
26 : #include "libmesh/int_range.h"
27 : #include "libmesh/libmesh_common.h"
28 : #include "libmesh/multi_predicates.h"
29 : #include "libmesh/point_locator_base.h"
30 : #include "libmesh/variant_filter_iterator.h"
31 : #include "libmesh/parallel_object.h"
32 : #include "libmesh/simple_range.h"
33 :
34 : // C++ Includes
35 : #include <cstddef>
36 : #include <string>
37 : #include <memory>
38 :
39 : #include "libmesh/vector_value.h"
40 :
41 : namespace libMesh
42 : {
43 : // Forward declarations
44 : class BoundaryInfo;
45 : class Elem;
46 : class GhostingFunctor;
47 : class Node;
48 : class Point;
49 : class Partitioner;
50 : class PeriodicBoundary;
51 : class PeriodicBoundaries;
52 :
53 : template <typename T>
54 : class SparseMatrix;
55 :
56 : enum ElemType : int;
57 : enum ElemMappingType : unsigned char;
58 :
59 : template <class MT>
60 : class MeshInput;
61 :
62 : template <typename iterator_type, typename object_type>
63 : class StoredRange;
64 :
65 : /**
66 : * This is the \p MeshBase class. This class provides all the data necessary
67 : * to describe a geometric entity. It allows for the description of a
68 : * \p dim dimensional object that lives in \p LIBMESH_DIM-dimensional space.
69 : * \par
70 : * A mesh is made of nodes and elements, and this class provides data
71 : * structures to store and access both. A mesh may be partitioned into a
72 : * number of subdomains, and this class provides that functionality.
73 : * Furthermore, this class provides functions for reading and writing a
74 : * mesh to disk in various formats.
75 : *
76 : * \author Benjamin S. Kirk
77 : * \date 2002
78 : * \brief Base class for Mesh.
79 : */
80 : class MeshBase : public ParallelObject
81 : {
82 : public:
83 :
84 : /**
85 : * Constructor. Takes \p dim, the dimension of the mesh.
86 : * The mesh dimension can be changed (and may automatically be
87 : * changed by mesh generation/loading) later.
88 : */
89 : MeshBase (const Parallel::Communicator & comm_in,
90 : unsigned char dim=1);
91 :
92 : /**
93 : * Copy-constructor.
94 : */
95 : MeshBase (const MeshBase & other_mesh);
96 :
97 : /**
98 : * Move-constructor - deleted because after a theoretical move-construction
99 : * and then destruction of the moved-from object, the moved \p BoundaryInfo
100 : * would hold an invalid reference to the moved-from mesh
101 : */
102 : MeshBase(MeshBase &&) = delete;
103 :
104 : /**
105 : * Copy and move assignment are not allowed because MeshBase
106 : * subclasses manually manage memory (Elems and Nodes) and therefore
107 : * the default versions of these operators would leak memory. Since
108 : * we don't want to maintain non-default copy and move assignment
109 : * operators at this time, the safest and most self-documenting
110 : * approach is to delete them.
111 : *
112 : * If you need to copy a Mesh, use the clone() method.
113 : */
114 : MeshBase & operator= (const MeshBase &) = delete;
115 : MeshBase & operator= (MeshBase && other_mesh);
116 :
117 : /**
118 : * Shim to allow operator = (&&) to behave like a virtual function
119 : * without having to be one.
120 : */
121 : virtual MeshBase & assign(MeshBase && other_mesh) = 0;
122 :
123 : /**
124 : * This tests for exactly-equal data in all the senses that a
125 : * mathematician would care about (element connectivity, nodal
126 : * coordinates), but in the senses a programmer would care about it
127 : * allows for non-equal equivalence in some ways (we accept
128 : * different Elem/Node addresses in memory) but not others (we do
129 : * not accept different subclass types, nor even different Elem/Node
130 : * ids).
131 : *
132 : * Though this method is non-virtual, its implementation calls the
133 : * virtual function \p subclass_first_difference_from() to test for
134 : * equality of subclass-specific data as well.
135 : */
136 : bool operator== (const MeshBase & other_mesh) const;
137 :
138 : bool operator!= (const MeshBase & other_mesh) const
139 : {
140 : return !(*this == other_mesh);
141 : }
142 :
143 : /**
144 : * This behaves like libmesh_assert(*this == other_mesh), but gives
145 : * a more useful accounting of the first difference found, if the
146 : * assertion fails.
147 : */
148 : void assert_equal_to (const MeshBase & other_mesh,
149 : std::string_view failure_context) const;
150 :
151 : /**
152 : * This behaves the same as operator==, but only for the local and
153 : * ghosted aspects of the mesh; i.e. operator== is true iff local
154 : * equality is true on every rank.
155 : */
156 : bool locally_equals (const MeshBase & other_mesh) const;
157 :
158 : /**
159 : * Virtual "copy constructor". The copy will be of the same
160 : * subclass as \p this, and will satisfy "copy == this" when it is
161 : * created.
162 : */
163 : virtual std::unique_ptr<MeshBase> clone() const = 0;
164 :
165 : /**
166 : * Destructor.
167 : */
168 : virtual ~MeshBase ();
169 :
170 : /**
171 : * A partitioner to use at each partitioning
172 : */
173 482206 : virtual std::unique_ptr<Partitioner> & partitioner() { return _partitioner; }
174 :
175 : /**
176 : * The information about boundary ids on the mesh
177 : */
178 780786 : const BoundaryInfo & get_boundary_info() const { return *boundary_info; }
179 :
180 : /**
181 : * Writable information about boundary ids on the mesh
182 : */
183 1386597 : BoundaryInfo & get_boundary_info() { return *boundary_info; }
184 :
185 : /**
186 : * Deletes all the element and node data that is currently stored.
187 : *
188 : * elem and node extra_integer data is nevertheless *retained* here,
189 : * for better compatibility between that feature and older code's
190 : * use of MeshBase::clear()
191 : */
192 : virtual void clear ();
193 :
194 : /**
195 : * Deletes all the element data that is currently stored.
196 : *
197 : * No Node is removed from the mesh, however even NodeElem elements
198 : * are deleted, so the remaining Nodes will be considered "unused"
199 : * and cleared unless they are reconnected to new elements before
200 : * the next preparation step.
201 : *
202 : * This does not affect BoundaryInfo data; any boundary information
203 : * associated elements should already be cleared.
204 : */
205 : virtual void clear_elems () = 0;
206 :
207 : /**
208 : * \returns \p true if the mesh is marked as having undergone all of
209 : * the preparation done in a call to \p prepare_for_use, \p false
210 : * otherwise.
211 : */
212 : bool is_prepared () const;
213 :
214 : /**
215 : * \returns the \p Preparation structure with details about in what
216 : * ways \p this mesh is currently prepared or unprepared. This
217 : * structure may change in the future when cache designs change.
218 : */
219 : struct Preparation;
220 :
221 7170 : Preparation preparation () const
222 96918 : { return _preparation; }
223 :
224 : #ifdef LIBMESH_ENABLE_DEPRECATED
225 : /**
226 : * Tells this we have done some operation where we should no longer
227 : * consider ourself prepared. This is a very coarse setting; it is
228 : * generally more efficient to mark finer-grained settings instead.
229 : *
230 : * This method name is now deprecated, in part to match the less
231 : * awkward unset_has_ names of the more fine-grained methods, in
232 : * part as a way to prompt older user codes to use the more
233 : * fine-grained methods where they can, to speed up the
234 : * complete_preparation() calls afterward.
235 : */
236 : void set_isnt_prepared()
237 : { libmesh_deprecated(); _preparation = false; }
238 : #endif // LIBMESH_ENABLE_DEPRECATED
239 :
240 : /**
241 : * Tells this we have done some operation where we should no longer
242 : * consider ourself prepared. This is a very coarse setting; it is
243 : * generally more efficient to mark finer-grained settings instead.
244 : */
245 : void unset_is_prepared();
246 :
247 : /**
248 : * Tells this we have done some operation creating unpartitioned
249 : * elements.
250 : *
251 : * User code which adds elements to this mesh must either partition
252 : * them too or call this method.
253 : */
254 0 : void unset_is_partitioned()
255 0 : { _preparation.is_partitioned = false; }
256 :
257 : /**
258 : * Tells this we have done some operation (e.g. adding objects to a
259 : * distributed mesh on one processor only) which can lose
260 : * synchronization of id counts.
261 : *
262 : * User code which does distributed additions of nodes or elements
263 : * must call either this method or \p update_parallel_id_counts().
264 : */
265 : void unset_has_synched_id_counts()
266 : { _preparation.has_synched_id_counts = false; }
267 :
268 : /**
269 : * Tells this we have done some operation (e.g. adding elements
270 : * without setting their neighbor pointers, or adding disjoint
271 : * neighbor boundary pairs) which requires neighbor pointers to be
272 : * determined later.
273 : *
274 : * User code which adds new elements to this mesh must call this
275 : * function or manually set neighbor pointer from and to those
276 : * elements.
277 : */
278 16 : void unset_has_neighbor_ptrs()
279 4708 : { _preparation.has_neighbor_ptrs = false; }
280 :
281 : /**
282 : * Tells this we have done some operation (e.g. adding elements with
283 : * a new dimension or subdomain value) which may invalidate cached
284 : * summaries of element data.
285 : *
286 : * User code which adds new elements to this mesh must call this
287 : * function.
288 : */
289 22 : void unset_has_cached_elem_data()
290 380805 : { _preparation.has_cached_elem_data = false; }
291 :
292 : /**
293 : * Tells this we have done some operation (e.g. refining elements
294 : * with interior parents) which requires interior parent pointers to
295 : * be found later.
296 : *
297 : * Most user code will not need to call this method; any user code
298 : * that manipulates interior parents or their boundary elements may
299 : * be an exception.
300 : */
301 : void unset_has_interior_parent_ptrs()
302 : { _preparation.has_interior_parent_ptrs = false; }
303 :
304 : /**
305 : * Tells this we have done some operation (e.g. repartitioning)
306 : * which may have left elements as ghosted which on a distributed
307 : * mesh should be remote.
308 : *
309 : * User code should probably never need to use this; we can set it
310 : * in Partitioner. Any user code which manually repartitions
311 : * elements on distributed meshes may need to call this manually, in
312 : * addition to manually communicating elements with newly-created
313 : * ghosting requirements.
314 : */
315 0 : void unset_has_removed_remote_elements()
316 0 : { _preparation.has_removed_remote_elements = false; }
317 :
318 : /**
319 : * Tells this we have done some operation (e.g. coarsening)
320 : * which may have left orphaned nodes in need of removal.
321 : *
322 : * Most user code should probably never need to use this; we can set
323 : * it in MeshRefinement. User code which deletes elements without
324 : * carefully deleting orphaned nodes should call this manually.
325 : */
326 0 : void unset_has_removed_orphaned_nodes()
327 0 : { _preparation.has_removed_orphaned_nodes = false; }
328 :
329 : /**
330 : * Tells this we have done some operation (e.g. adding or removing
331 : * elements) which may require a reinit() of custom ghosting
332 : * functors.
333 : *
334 : * User code which adds or removes elements should call this method.
335 : * User code which moves nodes ... should probably call this method,
336 : * in case ghosting functors depending on position exist?
337 : */
338 94 : void unset_has_reinit_ghosting_functors()
339 3337 : { _preparation.has_reinit_ghosting_functors = false; }
340 :
341 : /**
342 : * Tells this we have done some operation which may have invalidated
343 : * our cached boundary id sets.
344 : *
345 : * User code which removes elements, or which adds or removes
346 : * boundary entries, should call this method.
347 : */
348 2 : void unset_has_boundary_id_sets()
349 3245 : { _preparation.has_boundary_id_sets = false; }
350 :
351 : /**
352 : * Tells this we have done some operation which may have left the
353 : * subdomain id to name map inconsistent across processors.
354 : *
355 : * User code which adds or changes subdomain names should call this
356 : * method.
357 : */
358 62008 : void unset_has_synched_subdomain_name_map()
359 1170077 : { _preparation.has_synched_subdomain_name_map = false; }
360 :
361 : /**
362 : * \returns \p true if all elements and nodes of the mesh
363 : * exist on the current processor, \p false otherwise
364 : */
365 845444 : virtual bool is_serial () const
366 845444 : { return true; }
367 :
368 : /**
369 : * \returns \p true if all elements and nodes of the mesh
370 : * exist on the processor 0, \p false otherwise
371 : */
372 1645 : virtual bool is_serial_on_zero () const
373 1645 : { return true; }
374 :
375 : /**
376 : * Asserts that not all elements and nodes of the mesh necessarily
377 : * exist on the current processor. Only valid to call on classes
378 : * which can be created in a distributed form.
379 : */
380 0 : virtual void set_distributed ()
381 0 : { libmesh_error(); }
382 :
383 : /**
384 : * \returns \p true if new elements and nodes can and should be
385 : * created in synchronization on all processors, \p false otherwise
386 : */
387 2499853 : virtual bool is_replicated () const
388 2499853 : { return true; }
389 :
390 : /**
391 : * Gathers all elements and nodes of the mesh onto
392 : * every processor
393 : */
394 2 : virtual void allgather () {}
395 :
396 : /**
397 : * Gathers all elements and nodes of the mesh onto
398 : * processor zero
399 : */
400 0 : virtual void gather_to_zero() {}
401 :
402 : /**
403 : * When supported, deletes all nonlocal elements of the mesh
404 : * except for "ghosts" which touch a local element, and deletes
405 : * all nodes which are not part of a local or ghost element
406 : */
407 72542 : virtual void delete_remote_elements () {
408 72542 : _preparation.has_removed_remote_elements = true;
409 72542 : }
410 :
411 : /**
412 : * Loops over ghosting functors and calls mesh_reinit()
413 : */
414 : void reinit_ghosting_functors();
415 :
416 : /**
417 : * \returns The logical dimension of the mesh; i.e. the manifold
418 : * dimension of the elements in the mesh. When we have
419 : * multi-dimensional meshes (e.g. hexes and quads in the same mesh)
420 : * then this will return the largest such dimension.
421 : */
422 : unsigned int mesh_dimension () const;
423 :
424 : /**
425 : * Resets the logical dimension of the mesh. If the mesh has
426 : * elements of multiple dimensions, this should be set to the largest
427 : * dimension. E.g. if the mesh has 1D and 2D elements, this should
428 : * be set to 2. If the mesh has 2D and 3D elements, this should be
429 : * set to 3.
430 : */
431 10698 : void set_mesh_dimension (unsigned char d)
432 317362 : { _elem_dims.clear(); _elem_dims.insert(d); }
433 :
434 : /**
435 : * \returns A const reference to a std::set of element dimensions
436 : * present in the mesh.
437 : */
438 : const std::set<unsigned char> & elem_dimensions() const;
439 :
440 : /**
441 : * \returns A const reference to a std::set of element default
442 : * orders present in the mesh.
443 : */
444 : const std::set<Order> & elem_default_orders() const;
445 :
446 : /**
447 : * \returns The smallest supported_nodal_order() of any element
448 : * present in the mesh, which is thus the maximum supported nodal
449 : * order on the mesh as a whole.
450 : */
451 : Order supported_nodal_order() const;
452 :
453 : /**
454 : * Most of the time you should not need to call this, as the element
455 : * dimensions will be set automatically by a call to cache_elem_data(),
456 : * therefore only call this if you know what you're doing.
457 : *
458 : * In some specialized situations, for example when adding a single
459 : * Elem on all procs, it can be faster to skip calling cache_elem_data()
460 : * and simply specify the element dimensions manually, which is why this
461 : * setter exists.
462 : */
463 : void set_elem_dimensions(std::set<unsigned char> elem_dims);
464 :
465 : /**
466 : * Typedef for the "set" container used to store elemset ids. The
467 : * main requirements are that the entries be sorted and unique, so
468 : * std::set works for this, but there may be more efficient
469 : * alternatives.
470 : */
471 : typedef std::set<elemset_id_type> elemset_type;
472 :
473 : /**
474 : * Tabulate a user-defined "code" for elements which belong to the element sets
475 : * specified in \p id_set. For example, suppose that we have two elemsets A and
476 : * B with the following Elem ids:
477 : * Elemset A = {1, 3}
478 : * Elemset B = {2, 3}
479 : *
480 : * This implies the following mapping from elem id to elemset id:
481 : * Elem 1 -> {A}
482 : * Elem 2 -> {B}
483 : * Elem 3 -> {A,B}
484 : *
485 : * In this case, we would need to tabulate three different elemset codes, e.g.:
486 : * 0 -> {A}
487 : * 1 -> {B}
488 : * 2 -> {A,B}
489 : *
490 : * Also sets up the inverse mapping, so that if one knows all the
491 : * element sets an Elem belongs to, one can look up the
492 : * corresponding elemset code.
493 : */
494 : void add_elemset_code(dof_id_type code, MeshBase::elemset_type id_set);
495 :
496 : /**
497 : * Returns the number of unique elemset ids which have been added
498 : * via add_elemset_code(), which is the size of the _all_elemset_ids
499 : * set.
500 : */
501 : unsigned int n_elemsets() const;
502 :
503 : /**
504 : * Look up the element sets for a given elemset code and
505 : * vice-versa. The elemset must have been previously stored by
506 : * calling add_elemset_code(). If no such code/set is found, returns
507 : * the empty set or DofObject::invalid_id, respectively.
508 : */
509 : void get_elemsets(dof_id_type elemset_code, MeshBase::elemset_type & id_set_to_fill) const;
510 : dof_id_type get_elemset_code(const MeshBase::elemset_type & id_set) const;
511 :
512 : /**
513 : * Return a vector of all elemset codes defined on the mesh. We get
514 : * this by looping over the _elemset_codes map.
515 : */
516 : std::vector<dof_id_type> get_elemset_codes() const;
517 :
518 : /**
519 : * Replace elemset code "old_code" with "new_code". This function loops over
520 : * all elements and changes the extra integer corresponding to the "elemset_code"
521 : * label, and updates the _elemset_codes and _elemset_codes_inverse_map members.
522 : * Does not change the elemset ids of any of the sets.
523 : */
524 : void change_elemset_code(dof_id_type old_code, dof_id_type new_code);
525 :
526 : /**
527 : * Replace elemset id "old_id" with "new_id". Does not change any of the
528 : * elemset codes, so does not need to loop over the elements themselves.
529 : */
530 : void change_elemset_id(elemset_id_type old_id, elemset_id_type new_id);
531 :
532 : /**
533 : * \returns The "spatial dimension" of the mesh.
534 : *
535 : * The spatial dimension is defined as:
536 : *
537 : * 1 - for an exactly x-aligned mesh of 1D elements
538 : * 2 - for an exactly x-y planar mesh of 2D elements
539 : * 3 - otherwise
540 : *
541 : * No tolerance checks are performed to determine whether the Mesh
542 : * is x-aligned or x-y planar, only strict equality with zero in the
543 : * higher dimensions is checked. Also, x-z and y-z planar meshes are
544 : * considered to have spatial dimension == 3.
545 : *
546 : * The spatial dimension is updated during mesh preparation based
547 : * on the dimensions of the various elements present in the Mesh,
548 : * but is *never automatically decreased*.
549 : *
550 : * For example, if the user calls set_spatial_dimension(2) and then
551 : * later inserts 3D elements into the mesh,
552 : * Mesh::spatial_dimension() will return 3 after the next call to
553 : * prepare_for_use() or complete_preparation(). On the other hand,
554 : * if the user calls set_spatial_dimension(3) and then inserts only
555 : * x-aligned 1D elements into the Mesh, mesh.spatial_dimension()
556 : * will remain 3.
557 : */
558 : unsigned int spatial_dimension () const;
559 :
560 : /**
561 : * Sets the "spatial dimension" of the Mesh. See the documentation
562 : * for Mesh::spatial_dimension() for more information.
563 : */
564 : void set_spatial_dimension(unsigned char d);
565 :
566 : /**
567 : * \returns The number of nodes in the mesh.
568 : *
569 : * This function and others must be defined in derived classes since
570 : * the MeshBase class has no specific storage for nodes or elements.
571 : * The standard \p n_nodes() function may return a cached value on
572 : * distributed meshes, and so can be called by any processor at any
573 : * time.
574 : */
575 : virtual dof_id_type n_nodes () const = 0;
576 :
577 : /**
578 : * \returns The number of nodes in the mesh.
579 : *
580 : * This function and others must be overridden in derived classes since
581 : * the MeshBase class has no specific storage for nodes or elements.
582 : * The \p parallel_n_nodes() function computes a parallel-synchronized
583 : * value on distributed meshes, and so must be called in parallel
584 : * only.
585 : */
586 : virtual dof_id_type parallel_n_nodes () const = 0;
587 :
588 : /**
589 : * \returns The number of nodes on processor \p proc.
590 : */
591 : dof_id_type n_nodes_on_proc (const processor_id_type proc) const;
592 :
593 : /**
594 : * \returns The number of nodes on the local processor.
595 : */
596 500 : dof_id_type n_local_nodes () const
597 2055628 : { return this->n_nodes_on_proc (this->processor_id()); }
598 :
599 : /**
600 : * \returns The number of nodes owned by no processor.
601 : */
602 35878 : dof_id_type n_unpartitioned_nodes () const
603 2289954 : { return this->n_nodes_on_proc (DofObject::invalid_processor_id); }
604 :
605 : /**
606 : * \returns A number one greater than the maximum node id in the
607 : * mesh. A more apt name for this method would be end_node_id
608 : */
609 : virtual dof_id_type max_node_id () const = 0;
610 :
611 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
612 : /**
613 : * \returns The next unique id to be used.
614 : */
615 9729 : unique_id_type next_unique_id() const { return _next_unique_id; }
616 :
617 : /**
618 : * Sets the next available unique id to be used. On a
619 : * ReplicatedMesh, or when adding unpartitioned objects to a
620 : * DistributedMesh, this must be kept in sync on all processors.
621 : *
622 : * On a DistributedMesh, other unique_id values (larger than this
623 : * one) may be chosen next, to allow unique_id assignment without
624 : * communication.
625 : */
626 : virtual void set_next_unique_id(unique_id_type id) = 0;
627 : #endif
628 :
629 : /**
630 : * Reserves space for a known number of nodes.
631 : *
632 : * \note This method may or may not do anything, depending on the
633 : * actual \p Mesh implementation. If you know the number of nodes
634 : * you will add and call this method before repeatedly calling \p
635 : * add_point() the implementation will be more efficient.
636 : */
637 : virtual void reserve_nodes (const dof_id_type nn) = 0;
638 :
639 : /**
640 : * \returns The number of elements in the mesh.
641 : *
642 : * The standard n_elem() function may return a cached value on
643 : * distributed meshes, and so can be called by any processor at any
644 : * time.
645 : */
646 : virtual dof_id_type n_elem () const = 0;
647 :
648 : /**
649 : * \returns The number of elements in the mesh.
650 : *
651 : * The parallel_n_elem() function computes a parallel-synchronized
652 : * value on distributed meshes, and so must be called in parallel
653 : * only.
654 : */
655 : virtual dof_id_type parallel_n_elem () const = 0;
656 :
657 : /**
658 : * \returns A number one greater than the maximum element id in the
659 : * mesh. A more apt name for this method would be end_elem_id
660 : */
661 : virtual dof_id_type max_elem_id () const = 0;
662 :
663 : /**
664 : * \returns A number greater than or equal to the maximum unique_id in the
665 : * mesh.
666 : */
667 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
668 : virtual unique_id_type parallel_max_unique_id () const = 0;
669 : #endif
670 :
671 : /**
672 : * Reserves space for a known number of elements.
673 : *
674 : * \note This method may or may not do anything, depending on the
675 : * actual \p Mesh implementation. If you know the number of
676 : * elements you will add and call this method before repeatedly
677 : * calling \p add_point() the implementation will be more efficient.
678 : */
679 : virtual void reserve_elem (const dof_id_type ne) = 0;
680 :
681 : /**
682 : * Updates parallel caches so that methods like n_elem()
683 : * accurately reflect changes on other processors
684 : */
685 : virtual void update_parallel_id_counts () = 0;
686 :
687 : /**
688 : * \returns The number of active elements in the mesh.
689 : *
690 : * Implemented in terms of active_element_iterators.
691 : */
692 : virtual dof_id_type n_active_elem () const = 0;
693 :
694 : /**
695 : * \returns The number of elements on processor \p proc.
696 : */
697 : dof_id_type n_elem_on_proc (const processor_id_type proc) const;
698 :
699 : /**
700 : * \returns The number of elements on the local processor.
701 : */
702 484 : dof_id_type n_local_elem () const
703 2054609 : { return this->n_elem_on_proc (this->processor_id()); }
704 :
705 : /**
706 : * \returns The number of elements owned by no processor.
707 : */
708 50050 : dof_id_type n_unpartitioned_elem () const
709 2756083 : { return this->n_elem_on_proc (DofObject::invalid_processor_id); }
710 :
711 : /**
712 : * \returns The number of active elements on processor \p proc.
713 : */
714 : dof_id_type n_active_elem_on_proc (const processor_id_type proc) const;
715 :
716 : /**
717 : * \returns The number of active elements on the local processor.
718 : */
719 216 : dof_id_type n_active_local_elem () const
720 1378686 : { return this->n_active_elem_on_proc (this->processor_id()); }
721 :
722 : /**
723 : * \returns The number of elements that will be written
724 : * out in certain I/O formats.
725 : *
726 : * For example, a 9-noded quadrilateral will be broken into 4 linear
727 : * sub-elements for plotting purposes. Thus, for a mesh of 2 \p
728 : * QUAD9 elements \p n_tecplot_elem() will return 8. Implemented in
729 : * terms of element_iterators.
730 : */
731 : dof_id_type n_sub_elem () const;
732 :
733 : /**
734 : * Same as \p n_sub_elem(), but only counts active elements.
735 : */
736 : dof_id_type n_active_sub_elem () const;
737 :
738 : /**
739 : * \returns A constant reference (for reading only) to the
740 : * \f$ i^{th} \f$ point, which should be present in this processor's
741 : * subset of the mesh data structure.
742 : */
743 : virtual const Point & point (const dof_id_type i) const = 0;
744 :
745 : /**
746 : * \returns A constant reference (for reading only) to the
747 : * \f$ i^{th} \f$ node, which should be present in this processor's
748 : * subset of the mesh data structure.
749 : */
750 60230101 : virtual const Node & node_ref (const dof_id_type i) const
751 : {
752 60230101 : return *this->node_ptr(i);
753 : }
754 :
755 : /**
756 : * \returns A reference to the \f$ i^{th} \f$ node, which should be
757 : * present in this processor's subset of the mesh data structure.
758 : */
759 406114994 : virtual Node & node_ref (const dof_id_type i)
760 : {
761 406114994 : return *this->node_ptr(i);
762 : }
763 :
764 : /**
765 : * \returns A pointer to the \f$ i^{th} \f$ node, which should be
766 : * present in this processor's subset of the mesh data structure.
767 : */
768 : virtual const Node * node_ptr (const dof_id_type i) const = 0;
769 :
770 : /**
771 : * \returns A writable pointer to the \f$ i^{th} \f$ node, which
772 : * should be present in this processor's subset of the mesh data
773 : * structure.
774 : */
775 : virtual Node * node_ptr (const dof_id_type i) = 0;
776 :
777 : /**
778 : * \returns A pointer to the \f$ i^{th} \f$ node, or \p nullptr if no such
779 : * node exists in this processor's mesh data structure.
780 : */
781 : virtual const Node * query_node_ptr (const dof_id_type i) const = 0;
782 :
783 : /**
784 : * \returns A writable pointer to the \f$ i^{th} \f$ node, or \p nullptr if
785 : * no such node exists in this processor's mesh data structure.
786 : */
787 : virtual Node * query_node_ptr (const dof_id_type i) = 0;
788 :
789 : /**
790 : * \returns A reference to the \f$ i^{th} \f$ element, which should be
791 : * present in this processor's subset of the mesh data structure.
792 : */
793 5306311 : virtual const Elem & elem_ref (const dof_id_type i) const
794 : {
795 5306311 : return *this->elem_ptr(i);
796 : }
797 :
798 : /**
799 : * \returns A writable reference to the \f$ i^{th} \f$ element, which
800 : * should be present in this processor's subset of the mesh data
801 : * structure.
802 : */
803 306082337 : virtual Elem & elem_ref (const dof_id_type i)
804 : {
805 306082337 : return *this->elem_ptr(i);
806 : }
807 :
808 : /**
809 : * \returns A pointer to the \f$ i^{th} \f$ element, which should be
810 : * present in this processor's subset of the mesh data structure.
811 : */
812 : virtual const Elem * elem_ptr (const dof_id_type i) const = 0;
813 :
814 : /**
815 : * \returns A writable pointer to the \f$ i^{th} \f$ element, which
816 : * should be present in this processor's subset of the mesh data
817 : * structure.
818 : */
819 : virtual Elem * elem_ptr (const dof_id_type i) = 0;
820 :
821 : /**
822 : * \returns A pointer to the \f$ i^{th} \f$ element, or nullptr if no
823 : * such element exists in this processor's mesh data structure.
824 : */
825 : virtual const Elem * query_elem_ptr (const dof_id_type i) const = 0;
826 :
827 : /**
828 : * \returns A writable pointer to the \f$ i^{th} \f$ element, or nullptr
829 : * if no such element exists in this processor's mesh data structure.
830 : */
831 : virtual Elem * query_elem_ptr (const dof_id_type i) = 0;
832 :
833 : /**
834 : * Add a new \p Node at \p Point \p p to the end of the vertex array,
835 : * with processor_id \p procid.
836 : * Use DofObject::invalid_processor_id (default) to add a node to all
837 : * processors, or this->processor_id() to add a node to the local
838 : * processor only.
839 : * If adding a node locally, passing an \p id other than
840 : * DofObject::invalid_id will set that specific node id. Only
841 : * do this in parallel if you are manually keeping ids consistent.
842 : */
843 : virtual Node * add_point (const Point & p,
844 : const dof_id_type id = DofObject::invalid_id,
845 : const processor_id_type proc_id =
846 : DofObject::invalid_processor_id) = 0;
847 :
848 : /**
849 : * Add \p Node \p n to the end of the vertex array.
850 : */
851 : virtual Node * add_node (Node * n) = 0;
852 :
853 : /**
854 : * Version of add_node() taking a std::unique_ptr by value. The version
855 : * taking a dumb pointer will eventually be deprecated in favor of this
856 : * version. This API is intended to indicate that ownership of the Node
857 : * is transferred to the Mesh when this function is called, and it should
858 : * play more nicely with the Node::build() API which has always returned
859 : * a std::unique_ptr.
860 : */
861 : virtual Node * add_node (std::unique_ptr<Node> n) = 0;
862 :
863 : /**
864 : * Removes the Node n from the mesh.
865 : */
866 : virtual void delete_node (Node * n) = 0;
867 :
868 : /**
869 : * Takes ownership of node \p n on this partition of a distributed
870 : * mesh, by setting n.processor_id() to this->processor_id(), as
871 : * well as changing n.id() and moving it in the mesh's internal
872 : * container to give it a new authoritative id.
873 : */
874 0 : virtual void own_node (Node &) {}
875 :
876 : /**
877 : * Changes the id of node \p old_id, both by changing node(old_id)->id() and
878 : * by moving node(old_id) in the mesh's internal container. No element with
879 : * the id \p new_id should already exist.
880 : */
881 : virtual void renumber_node (dof_id_type old_id, dof_id_type new_id) = 0;
882 :
883 : /**
884 : * Add elem \p e to the end of the element array.
885 : * To add an element locally, set e->processor_id() before adding it.
886 : * To ensure a specific element id, call e->set_id() before adding it;
887 : * only do this in parallel if you are manually keeping ids consistent.
888 : *
889 : * Users should call MeshBase::complete_preparation() after elements are
890 : * added to and/or deleted from the mesh.
891 : */
892 : virtual Elem * add_elem (Elem * e) = 0;
893 :
894 : /**
895 : * Version of add_elem() taking a std::unique_ptr by value. The version
896 : * taking a dumb pointer will eventually be deprecated in favor of this
897 : * version. This API is intended to indicate that ownership of the Elem
898 : * is transferred to the Mesh when this function is called, and it should
899 : * play more nicely with the Elem::build() API which has always returned
900 : * a std::unique_ptr.
901 : */
902 : virtual Elem * add_elem (std::unique_ptr<Elem> e) = 0;
903 :
904 : /**
905 : * Insert elem \p e to the element array, preserving its id
906 : * and replacing/deleting any existing element with the same id.
907 : *
908 : * Users should call MeshBase::complete_preparation() after elements are
909 : * added to and/or deleted from the mesh.
910 : */
911 : virtual Elem * insert_elem (Elem * e) = 0;
912 :
913 : /**
914 : * Version of insert_elem() taking a std::unique_ptr by value. The version
915 : * taking a dumb pointer will eventually be deprecated in favor of this
916 : * version. This API is intended to indicate that ownership of the Elem
917 : * is transferred to the Mesh when this function is called, and it should
918 : * play more nicely with the Elem::build() API which has always returned
919 : * a std::unique_ptr.
920 : */
921 : virtual Elem * insert_elem (std::unique_ptr<Elem> e) = 0;
922 :
923 : /**
924 : * Removes element \p e from the mesh. This method must be
925 : * implemented in derived classes in such a way that it does not
926 : * invalidate element iterators. Users should call
927 : * MeshBase::complete_preparation() after elements are added to
928 : * and/or deleted from the mesh.
929 : *
930 : * \note Calling this method may produce isolated nodes, i.e. nodes
931 : * not connected to any element.
932 : */
933 : virtual void delete_elem (Elem * e) = 0;
934 :
935 : /**
936 : * Changes the id of element \p old_id, both by changing elem(old_id)->id()
937 : * and by moving elem(old_id) in the mesh's internal container. No element
938 : * with the id \p new_id should already exist.
939 : */
940 : virtual void renumber_elem (dof_id_type old_id, dof_id_type new_id) = 0;
941 :
942 : /**
943 : * Returns the default master space to physical space mapping basis
944 : * functions to be used on newly added elements.
945 : */
946 1840127 : ElemMappingType default_mapping_type () const
947 : {
948 59697546 : return _default_mapping_type;
949 : }
950 :
951 : /**
952 : * Set the default master space to physical space mapping basis
953 : * functions to be used on newly added elements.
954 : */
955 44 : void set_default_mapping_type (const ElemMappingType type)
956 : {
957 16431 : _default_mapping_type = type;
958 44 : }
959 :
960 : /**
961 : * Returns any default data value used by the master space to
962 : * physical space mapping.
963 : */
964 1840127 : unsigned char default_mapping_data () const
965 : {
966 59697546 : return _default_mapping_data;
967 : }
968 :
969 : /**
970 : * Set the default master space to physical space mapping basis
971 : * functions to be used on newly added elements.
972 : */
973 44 : void set_default_mapping_data (const unsigned char data)
974 : {
975 16431 : _default_mapping_data = data;
976 44 : }
977 :
978 : /**
979 : * Locate element face (edge in 2D) neighbors. This is done with the help
980 : * of a \p std::map that functions like a hash table.
981 : * After this routine is called all the elements with a \p nullptr neighbor
982 : * pointer are guaranteed to be on the boundary. Thus this routine is
983 : * useful for automatically determining the boundaries of the domain.
984 : *
985 : * If \p reset_remote_elements is left to false, remote neighbor
986 : * links are not reset and searched for in the local mesh.
987 : *
988 : * If \p reset_current_list is left as true, then any existing links
989 : * will be reset before initiating the algorithm, while honoring the
990 : * value of the \p reset_remote_elements flag.
991 : *
992 : * If \p assert_valid is left as true, then in dbg mode extensive
993 : * consistency checking is performed before returning.
994 : *
995 : * If \p check_non_remote is set to false, then only sides which
996 : * currently have remote neighbor_ptr links are checked for possible
997 : * semilocal side-neighbors. This is intended to handle a corner case
998 : * where ancestor neighbors are redistributed to a processor only by
999 : * other processors who do not see that neighbor link.
1000 : */
1001 : virtual void find_neighbors (const bool reset_remote_elements = false,
1002 : const bool reset_current_list = true,
1003 : const bool assert_valid = true,
1004 : const bool check_non_remote = true) = 0;
1005 :
1006 : /**
1007 : * Removes any orphaned nodes, nodes not connected to any elements.
1008 : * Typically done automatically in a preparation step
1009 : */
1010 : void remove_orphaned_nodes ();
1011 :
1012 : /**
1013 : * After partitioning a mesh it is useful to renumber the nodes and elements
1014 : * so that they lie in contiguous blocks on the processors. This method
1015 : * does just that.
1016 : */
1017 : virtual void renumber_nodes_and_elements () = 0;
1018 :
1019 : /**
1020 : * There is no reason for a user to ever call this function.
1021 : *
1022 : * This function restores a previously broken element/node numbering such that
1023 : * \p mesh.node_ref(n).id() == n.
1024 : */
1025 : virtual void fix_broken_node_and_element_numbering () = 0;
1026 :
1027 :
1028 : #ifdef LIBMESH_ENABLE_AMR
1029 : /**
1030 : * Delete subactive (i.e. children of coarsened) elements.
1031 : * This removes all elements descended from currently active
1032 : * elements in the mesh.
1033 : */
1034 : virtual bool contract () = 0;
1035 : #endif
1036 :
1037 : /**
1038 : * Register an integer datum (of type dof_id_type) to be added to
1039 : * each element in the mesh.
1040 : *
1041 : * If the mesh already has elements, data by default is allocated in
1042 : * each of them. This may be expensive to do repeatedly; use
1043 : * add_elem_integers instead. Alternatively, the \p allocate_data
1044 : * option can be manually set to false, but if this is done then a
1045 : * manual call to \p size_elem_extra_integers() will need to be done
1046 : * before the new space is usable.
1047 : *
1048 : * Newly allocated values for the new datum will be initialized to
1049 : * \p default_value
1050 : *
1051 : * \returns The index number for the new datum, or for the existing
1052 : * datum if one by the same name has already been added.
1053 : */
1054 : unsigned int add_elem_integer(std::string name,
1055 : bool allocate_data = true,
1056 : dof_id_type default_value = DofObject::invalid_id);
1057 :
1058 : /**
1059 : * Register integer data (of type dof_id_type) to be added to
1060 : * each element in the mesh, one string name for each new integer.
1061 : *
1062 : * If the mesh already has elements, data by default is allocated in
1063 : * each of them.
1064 : *
1065 : * Newly allocated values for the new datum with name \p names[i]
1066 : * will be initialized to \p default_values[i], or to
1067 : * DofObject::invalid_id if \p default_values is null.
1068 : *
1069 : * \returns The index numbers for the new data, and/or for existing
1070 : * data if data by some of the same names has already been added.
1071 : */
1072 : std::vector<unsigned int> add_elem_integers(const std::vector<std::string> & names,
1073 : bool allocate_data = true,
1074 : const std::vector<dof_id_type> * default_values = nullptr);
1075 :
1076 : /*
1077 : * \returns The index number for the named extra element integer
1078 : * datum, which must have already been added.
1079 : */
1080 : unsigned int get_elem_integer_index(std::string_view name) const;
1081 :
1082 : /*
1083 : * \returns Whether or not the mesh has an element integer with its name.
1084 : */
1085 : bool has_elem_integer(std::string_view name) const;
1086 :
1087 : /*
1088 : * \returns The name for the indexed extra element integer
1089 : * datum, which must have already been added.
1090 : */
1091 19 : const std::string & get_elem_integer_name(unsigned int i) const
1092 38 : { return _elem_integer_names[i]; }
1093 :
1094 : /*
1095 : * \returns The number of extra element integers for which space is
1096 : * being reserved on this mesh.
1097 : *
1098 : * If non-integer data has been associated, each datum of type T
1099 : * counts for sizeof(T)/sizeof(dof_id_type) times in the return
1100 : * value.
1101 : */
1102 916 : unsigned int n_elem_integers() const { return _elem_integer_names.size(); }
1103 :
1104 : /**
1105 : * Register a datum (of type T) to be added to each element in the
1106 : * mesh.
1107 : *
1108 : * If the mesh already has elements, data by default is allocated in
1109 : * each of them. This may be expensive to do repeatedly; use
1110 : * add_elem_data instead. Alternatively, the \p allocate_data
1111 : * option can be manually set to false, but if this is done then a
1112 : * manual call to \p size_elem_extra_integers() will need to be done
1113 : * before the new space is usable.
1114 : *
1115 : * Newly allocated values for the new datum will be initialized to
1116 : * \p *default_value if \p default_value is not null, or to
1117 : * meaningless memcpy output otherwise.
1118 : *
1119 : * \returns The index numbers for the new data, and/or for existing
1120 : * data if data by some of the same names has already been added.
1121 : *
1122 : * If type T is larger than dof_id_type, its data will end up
1123 : * spanning multiple index values, but will be queried with the
1124 : * starting index number.
1125 : *
1126 : * No type checking is done with this function! If you add data of
1127 : * type T, don't try to access it with a call specifying type U.
1128 : */
1129 : template <typename T>
1130 : unsigned int add_elem_datum(const std::string & name,
1131 : bool allocate_data = true,
1132 : const T * default_value = nullptr);
1133 :
1134 : /**
1135 : * Register data (of type T) to be added to each element in the
1136 : * mesh.
1137 : *
1138 : * If the mesh already has elements, data is allocated in each.
1139 : *
1140 : * Newly allocated values for the new datum with name \p names[i]
1141 : * will be initialized to \p default_values[i], or to
1142 : * meaningless memcpy output if \p default_values is null.
1143 : *
1144 : * \returns The starting index number for the new data, or for the
1145 : * existing data if one by the same name has already been added.
1146 : *
1147 : * If type T is larger than dof_id_type, each datum will end up
1148 : * spanning multiple index values, but will be queried with the
1149 : * starting index number.
1150 : *
1151 : * No type checking is done with this function! If you add data of
1152 : * type T, don't try to access it with a call specifying type U.
1153 : */
1154 : template <typename T>
1155 : std::vector<unsigned int> add_elem_data(const std::vector<std::string> & names,
1156 : bool allocate_data = true,
1157 : const std::vector<T> * default_values = nullptr);
1158 :
1159 : /**
1160 : * Register an integer datum (of type dof_id_type) to be added to
1161 : * each node in the mesh.
1162 : *
1163 : * If the mesh already has nodes, data by default is allocated in
1164 : * each of them. This may be expensive to do repeatedly; use
1165 : * add_node_integers instead. Alternatively, the \p allocate_data
1166 : * option can be manually set to false, but if this is done then a
1167 : * manual call to \p size_node_extra_integers() will need to be done
1168 : * before the new space is usable.
1169 : *
1170 : * Newly allocated values for the new datum will be initialized to
1171 : * \p default_value
1172 : *
1173 : * \returns The index number for the new datum, or for the existing
1174 : * datum if one by the same name has already been added.
1175 : */
1176 : unsigned int add_node_integer(std::string name,
1177 : bool allocate_data = true,
1178 : dof_id_type default_value = DofObject::invalid_id);
1179 :
1180 : /**
1181 : * Register integer data (of type dof_id_type) to be added to
1182 : * each node in the mesh.
1183 : *
1184 : * If the mesh already has nodes, data by default is allocated in
1185 : * each.
1186 : *
1187 : * Newly allocated values for the new datum with name \p names[i]
1188 : * will be initialized to \p default_values[i], or to
1189 : * DofObject::invalid_id if \p default_values is null.
1190 : *
1191 : * \returns The index numbers for the new data, and/or for existing
1192 : * data if data by some of the same names has already been added.
1193 : */
1194 : std::vector<unsigned int> add_node_integers(const std::vector<std::string> & names,
1195 : bool allocate_data = true,
1196 : const std::vector<dof_id_type> * default_values = nullptr);
1197 :
1198 : /*
1199 : * \returns The index number for the named extra node integer
1200 : * datum, which must have already been added.
1201 : */
1202 : unsigned int get_node_integer_index(std::string_view name) const;
1203 :
1204 : /*
1205 : * \returns Whether or not the mesh has a node integer with its name.
1206 : */
1207 : bool has_node_integer(std::string_view name) const;
1208 :
1209 : /*
1210 : * \returns The name for the indexed extra node integer
1211 : * datum, which must have already been added.
1212 : */
1213 36 : const std::string & get_node_integer_name(unsigned int i) const
1214 72 : { return _node_integer_names[i]; }
1215 :
1216 : /*
1217 : * \returns The number of extra node integers for which space is
1218 : * being reserved on this mesh.
1219 : *
1220 : * If non-integer data has been associated, each datum of type T
1221 : * counts for sizeof(T)/sizeof(dof_id_type) times in the return
1222 : * value.
1223 : */
1224 916 : unsigned int n_node_integers() const { return _node_integer_names.size(); }
1225 :
1226 : /**
1227 : * Register a datum (of type T) to be added to each node in the
1228 : * mesh.
1229 : *
1230 : * If the mesh already has nodes, data by default is allocated in
1231 : * each of them. This may be expensive to do repeatedly; use
1232 : * add_node_data instead. Alternatively, the \p allocate_data
1233 : * option can be manually set to false, but if this is done then a
1234 : * manual call to \p size_node_extra_integers() will need to be done
1235 : * before the new space is usable.
1236 : *
1237 : * Newly allocated values for the new datum will be initialized to
1238 : * \p *default_value if \p default_value is not null, or to
1239 : * meaningless memcpy output otherwise.
1240 : *
1241 : * \returns The starting index number for the new datum, or for the
1242 : * existing datum if one by the same name has already been added.
1243 : *
1244 : * If type T is larger than dof_id_type, its data will end up
1245 : * spanning multiple index values, but will be queried with the
1246 : * starting index number.
1247 : *
1248 : * No type checking is done with this function! If you add data of
1249 : * type T, don't try to access it with a call specifying type U.
1250 : */
1251 : template <typename T>
1252 : unsigned int add_node_datum(const std::string & name,
1253 : bool allocate_data = true,
1254 : const T * default_value = nullptr);
1255 :
1256 : /**
1257 : * Register data (of type T) to be added to each node in the
1258 : * mesh.
1259 : *
1260 : * If the mesh already has nodes, data by default is allocated in each.
1261 : *
1262 : * Newly allocated values for the new datum with name \p names[i]
1263 : * will be initialized to \p default_values[i], or to
1264 : * meaningless memcpy output if \p default_values is null.
1265 : *
1266 : * \returns The starting index number for the new data, or for the
1267 : * existing data if one by the same name has already been added.
1268 : *
1269 : * If type T is larger than dof_id_type, its data will end up
1270 : * spanning multiple index values, but will be queried with the
1271 : * starting index number.
1272 : *
1273 : * No type checking is done with this function! If you add data of
1274 : * type T, don't try to access it with a call specifying type U.
1275 : */
1276 : template <typename T>
1277 : std::vector<unsigned int> add_node_data(const std::vector<std::string> & name,
1278 : bool allocate_data = true,
1279 : const std::vector<T> * default_values = nullptr);
1280 :
1281 : /**
1282 : * Prepare a newly created (or read) mesh for use.
1283 : * This involves several steps:
1284 : * 1.) renumbering (if enabled)
1285 : * 2.) removing any orphaned nodes
1286 : * 3.) updating parallel id counts
1287 : * 4.) finding neighbor links
1288 : * 5.) caching summarized element data
1289 : * 6.) finding interior parent links
1290 : * 7.) clearing any old point locator
1291 : * 8.) calling reinit() on ghosting functors
1292 : * 9.) repartitioning (if enabled)
1293 : * 10.) removing any remote elements (if enabled)
1294 : * 11.) regenerating summarized boundary id sets
1295 : *
1296 : * For backwards compatibility, prepare_for_use() performs *all* those
1297 : * steps, regardless of the official preparation() state of the
1298 : * mesh. In codes which have maintained a valid preparation() state
1299 : * via methods such as unset_has_synched_id_counts(), calling
1300 : * complete_preparation() will result in a fully-prepared mesh at
1301 : * less cost.
1302 : *
1303 : * The argument to skip renumbering is now deprecated - to prevent a
1304 : * mesh from being renumbered, set allow_renumbering(false). The argument to skip
1305 : * finding neighbors is also deprecated. To prevent find_neighbors, set
1306 : * allow_find_neighbors(false)
1307 : *
1308 : * If this is a distributed mesh, local copies of remote elements
1309 : * will be deleted here - to keep those elements replicated during
1310 : * preparation, set allow_remote_element_removal(false).
1311 : */
1312 : #ifdef LIBMESH_ENABLE_DEPRECATED
1313 : void prepare_for_use (const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors);
1314 : void prepare_for_use (const bool skip_renumber_nodes_and_elements);
1315 : #endif // LIBMESH_ENABLE_DEPRECATED
1316 : void prepare_for_use ();
1317 :
1318 : /*
1319 : * Prepare a newly created or modified mesh for use.
1320 : *
1321 : * Unlike \p prepare_for_use(), \p complete_preparation() performs
1322 : * *only* those preparatory steps that have been marked as
1323 : * necessary in the MeshBase::Preparation state.
1324 : */
1325 : void complete_preparation();
1326 :
1327 : /**
1328 : * Call the default partitioner (currently \p metis_partition()).
1329 : */
1330 : virtual void partition (const unsigned int n_parts);
1331 :
1332 2018 : void partition ()
1333 467467 : { this->partition(this->n_processors()); }
1334 :
1335 : /**
1336 : * Redistribute elements between processors. This gets called
1337 : * automatically by the Partitioner, and merely notifies any
1338 : * GhostingFunctors of redistribution in the case of a
1339 : * ReplicatedMesh or serialized DistributedMesh
1340 : */
1341 : virtual void redistribute ();
1342 :
1343 : /**
1344 : * Recalculate any cached data (or invalidate any caches that are
1345 : * computed on the fly) after elements and nodes have been
1346 : * repartitioned.
1347 : */
1348 : virtual void update_post_partitioning ();
1349 :
1350 : /**
1351 : * If false is passed in then this mesh will no longer be renumbered
1352 : * when being prepared for use. This may slightly adversely affect
1353 : * performance during subsequent element access, particularly when
1354 : * using a distributed mesh.
1355 : *
1356 : * Important! When allow_renumbering(false) is set,
1357 : * ReplicatedMesh::n_elem() and ReplicatedMesh::n_nodes() will
1358 : * return *wrong* values whenever adaptive refinement is followed by
1359 : * adaptive coarsening. (Uniform refinement followed by uniform
1360 : * coarsening is OK.) This is due to the fact that n_elem() and
1361 : * n_nodes() are currently O(1) functions that just return the size
1362 : * of the respective underlying vectors, and this size is wrong when
1363 : * the numbering includes "gaps" from nodes and elements that have
1364 : * been deleted. We plan to implement a caching mechanism in the
1365 : * near future that will fix this incorrect behavior.
1366 : */
1367 83080 : void allow_renumbering(bool allow) { _skip_renumber_nodes_and_elements = !allow; }
1368 75054 : bool allow_renumbering() const { return !_skip_renumber_nodes_and_elements; }
1369 :
1370 : /**
1371 : * If \p false is passed then this mesh will no longer work to find element
1372 : * neighbors when being prepared for use
1373 : */
1374 88247 : void allow_find_neighbors(bool allow) { _skip_find_neighbors = !allow; }
1375 189632 : bool allow_find_neighbors() const { return !_skip_find_neighbors; }
1376 :
1377 : /**
1378 : * If \p false is passed then this mesh will no longer work to detect
1379 : * interior parents when being prepared for use
1380 : */
1381 44057 : void allow_detect_interior_parents(bool allow) { _skip_detect_interior_parents = !allow; }
1382 43271 : bool allow_detect_interior_parents() const { return !_skip_detect_interior_parents; }
1383 :
1384 : /**
1385 : * If false is passed in then this mesh will no longer have remote
1386 : * elements deleted when being prepared for use; i.e. even a
1387 : * DistributedMesh will remain (if it is already) serialized.
1388 : * This may adversely affect performance and memory use.
1389 : */
1390 758828 : void allow_remote_element_removal(bool allow) { _allow_remote_element_removal = allow; }
1391 452523 : bool allow_remote_element_removal() const { return _allow_remote_element_removal; }
1392 :
1393 : /**
1394 : * If \p true is passed, then this mesh will no longer require
1395 : * unique_ids to be unique across the set of all DofObjects. That
1396 : * is, although no two Elems (resp. Nodes) will share the same
1397 : * unique_id, a given Elem and Node might share the same unique_id.
1398 : */
1399 142 : void allow_node_and_elem_unique_id_overlap(bool allow) { _allow_node_and_elem_unique_id_overlap = allow; }
1400 67838 : bool allow_node_and_elem_unique_id_overlap() const { return _allow_node_and_elem_unique_id_overlap; }
1401 :
1402 : /**
1403 : * If true is passed in then the elements on this mesh will no
1404 : * longer be (re)partitioned, and the nodes on this mesh will only
1405 : * be repartitioned if they are found "orphaned" via coarsening or
1406 : * other removal of the last element responsible for their
1407 : * node/element processor id consistency.
1408 : *
1409 : * \note It would probably be a bad idea to call this on a
1410 : * DistributedMesh _before_ the first partitioning has happened...
1411 : * because no elements would get assigned to your processor pool.
1412 : *
1413 : * \note Skipping partitioning can have adverse effects on your
1414 : * performance when using AMR... i.e. you could get large load
1415 : * imbalances. However you might still want to use this if the
1416 : * communication and computation of the rebalance and repartition is
1417 : * too high for your application.
1418 : *
1419 : * It is also possible, for backwards-compatibility purposes, to
1420 : * skip noncritical partitioning by resetting the partitioner()
1421 : * pointer for this mesh.
1422 : */
1423 : void skip_noncritical_partitioning(bool skip)
1424 : { _skip_noncritical_partitioning = skip; }
1425 :
1426 3884 : bool skip_noncritical_partitioning() const
1427 160158 : { return _skip_noncritical_partitioning || _skip_all_partitioning || !_partitioner.get(); }
1428 :
1429 :
1430 : /**
1431 : * If true is passed in then nothing on this mesh will be
1432 : * (re)partitioned.
1433 : *
1434 : * \note The caveats for skip_noncritical_partitioning() still
1435 : * apply, and removing elements from a mesh with this setting
1436 : * enabled can leave node processor ids in an inconsistent state
1437 : * (not matching any attached element), causing failures in other
1438 : * library code. Do not use this setting along with element
1439 : * deletion or coarsening.
1440 : */
1441 35266 : void skip_partitioning(bool skip) { _skip_all_partitioning = skip; }
1442 :
1443 768533 : bool skip_partitioning() const { return _skip_all_partitioning; }
1444 :
1445 : /**
1446 : * Adds a functor which can specify ghosting requirements for use on
1447 : * distributed meshes. Multiple ghosting functors can be added; any
1448 : * element which is required by any functor will be ghosted.
1449 : *
1450 : * GhostingFunctor memory must be managed by the code which calls
1451 : * this function; the GhostingFunctor lifetime is expected to extend
1452 : * until either the functor is removed or the Mesh is destructed.
1453 : */
1454 : void add_ghosting_functor(GhostingFunctor & ghosting_functor);
1455 :
1456 : /**
1457 : * Adds a functor which can specify ghosting requirements for use on
1458 : * distributed meshes. Multiple ghosting functors can be added; any
1459 : * element which is required by any functor will be ghosted.
1460 : *
1461 : * GhostingFunctor memory when using this method is managed by the
1462 : * shared_ptr mechanism.
1463 : */
1464 33366 : void add_ghosting_functor(std::shared_ptr<GhostingFunctor> ghosting_functor)
1465 63034 : { _shared_functors[ghosting_functor.get()] = ghosting_functor;
1466 33366 : this->add_ghosting_functor(*ghosting_functor); }
1467 :
1468 : /**
1469 : * Removes a functor which was previously added to the set of
1470 : * ghosting functors.
1471 : */
1472 : void remove_ghosting_functor(GhostingFunctor & ghosting_functor);
1473 :
1474 : /**
1475 : * Iterator type for ghosting functor ranges. This has changed in
1476 : * the past and may change again; code should use auto or the type
1477 : * here.
1478 : */
1479 : typedef std::vector<GhostingFunctor *>::const_iterator GhostingFunctorIterator;
1480 :
1481 : /**
1482 : * Beginning of range of ghosting functors
1483 : */
1484 2662 : GhostingFunctorIterator ghosting_functors_begin() const
1485 18631 : { return _ghosting_functors.begin(); }
1486 :
1487 : /**
1488 : * End of range of ghosting functors
1489 : */
1490 2662 : GhostingFunctorIterator ghosting_functors_end() const
1491 18631 : { return _ghosting_functors.end(); }
1492 :
1493 : /**
1494 : * Default ghosting functor
1495 : */
1496 6 : GhostingFunctor & default_ghosting() { return *_default_ghosting; }
1497 :
1498 : /**
1499 : * Constructs a list of all subdomain identifiers in the local mesh if
1500 : * \p global == false, and in the global mesh if \p global == true (default).
1501 : * Subdomains correspond to separate subsets of the mesh which could correspond
1502 : * e.g. to different materials in a solid mechanics application,
1503 : * or regions where different physical processes are important. The subdomain
1504 : * mapping is independent from the parallel decomposition.
1505 : *
1506 : * Unpartitioned elements are included in the set in the case that \p
1507 : * global == true. If \p global == false, the unpartitioned elements are not
1508 : * included because unpartitioned elements do not have a sense of locality.
1509 : */
1510 : void subdomain_ids (std::set<subdomain_id_type> & ids, const bool global = true) const;
1511 :
1512 : /**
1513 : * \returns The number of subdomains in the global mesh. Subdomains correspond
1514 : * to separate subsets of the mesh which could correspond e.g. to different
1515 : * materials in a solid mechanics application, or regions where different
1516 : * physical processes are important. The subdomain mapping is independent
1517 : * from the parallel decomposition.
1518 : */
1519 : subdomain_id_type n_subdomains () const;
1520 :
1521 : /**
1522 : * \returns The number of subdomains in the local mesh. Subdomains correspond
1523 : * to separate subsets of the mesh which could correspond e.g. to different
1524 : * materials in a solid mechanics application, or regions where different
1525 : * physical processes are important. The subdomain mapping is independent
1526 : * from the parallel decomposition.
1527 : */
1528 : subdomain_id_type n_local_subdomains () const;
1529 :
1530 : /**
1531 : * \returns The number of partitions which have been defined via
1532 : * a call to either mesh.partition() or by building a Partitioner
1533 : * object and calling partition.
1534 : *
1535 : * \note The partitioner object is responsible for setting this
1536 : * value.
1537 : */
1538 8612 : unsigned int n_partitions () const
1539 58437 : { return _n_parts; }
1540 :
1541 : /**
1542 : * \returns A string containing relevant information
1543 : * about the mesh.
1544 : *
1545 : * \p verbosity sets the verbosity, with 0 being the least and 2 being the greatest.
1546 : * 0 - Dimensions, number of nodes, number of elems, number of subdomains, number of
1547 : * partitions, prepared status.
1548 : * 1 - Adds the mesh bounding box, mesh element types, specific nodesets/edgesets/sidesets
1549 : * with element types, number of nodes/edges/sides.
1550 : * 2 - Adds volume information and bounding boxes to boundary information.
1551 : *
1552 : * The \p global parameter pertains primarily to verbosity levels 1 and above.
1553 : * When \p global == true, information is only output on rank 0 and the information
1554 : * is reduced. When \p global == false, information is output on all ranks that pertains
1555 : * only to that local partition.
1556 : */
1557 : std::string get_info (const unsigned int verbosity = 0, const bool global = true) const;
1558 :
1559 : /**
1560 : * Prints relevant information about the mesh.
1561 : *
1562 : * Take note of the docstring for get_info() for more information pretaining to
1563 : * the \p verbosity and \p global parameters.
1564 : */
1565 : void print_info (std::ostream & os=libMesh::out, const unsigned int verbosity = 0, const bool global = true) const;
1566 :
1567 : /**
1568 : * Equivalent to calling print_info() above, but now you can write:
1569 : * Mesh mesh;
1570 : * libMesh::out << mesh << std::endl;
1571 : */
1572 : friend std::ostream & operator << (std::ostream & os, const MeshBase & m);
1573 :
1574 : /**
1575 : * Interfaces for reading/writing a mesh to/from a file. Must be
1576 : * implemented in derived classes.
1577 : */
1578 : virtual void read (const std::string & name,
1579 : void * mesh_data=nullptr,
1580 : bool skip_renumber_nodes_and_elements=false,
1581 : bool skip_find_neighbors=false,
1582 : bool skip_detect_interior_parents=false) = 0;
1583 : virtual void write (const std::string & name) const = 0;
1584 :
1585 : /**
1586 : * Converts a mesh with higher-order
1587 : * elements into a mesh with linear elements. For
1588 : * example, a mesh consisting of \p Tet10 will be converted
1589 : * to a mesh with \p Tet4 etc.
1590 : */
1591 : virtual void all_first_order () = 0;
1592 :
1593 : /**
1594 : * We need an empty, generic class to act as a predicate for this
1595 : * and derived mesh classes.
1596 : */
1597 : typedef Predicates::multi_predicate Predicate;
1598 :
1599 : /**
1600 : * structs for the element_iterator's.
1601 : *
1602 : * \note These iterators were designed so that derived mesh classes
1603 : * could use the _same_ base class iterators interchangeably. Their
1604 : * definition comes later in the header file.
1605 : */
1606 : struct element_iterator;
1607 : struct const_element_iterator;
1608 :
1609 : /**
1610 : * structs for the node_iterator's.
1611 : *
1612 : * \note These iterators were designed so that derived mesh classes
1613 : * could use the _same_ base class iterators interchangeably. Their
1614 : * definition comes later in the header file.
1615 : */
1616 : struct node_iterator;
1617 : struct const_node_iterator;
1618 :
1619 : /**
1620 : * Converts a set of this Mesh's elements defined by \p range from
1621 : * FIRST order to SECOND order. Must be called on conforming,
1622 : * non-refined meshes. For example, a mesh consisting of \p Tet4
1623 : * will be converted to a mesh with \p Tet10 etc.
1624 : *
1625 : * \note For some elements like \p Hex8 there exist two higher order
1626 : * equivalents, \p Hex20 and \p Hex27. When \p full_ordered is \p
1627 : * true (default), then \p Hex27 is built. Otherwise, \p Hex20 is
1628 : * built. The same holds obviously for \p Quad4, \p Prism6, etc.
1629 : */
1630 : virtual void all_second_order_range(const SimpleRange<element_iterator> & range,
1631 : const bool full_ordered = true) = 0;
1632 :
1633 : /**
1634 : * Calls the range-based version of this function with a range
1635 : * consisting of all elements in the mesh.
1636 : */
1637 : void all_second_order (const bool full_ordered = true);
1638 :
1639 : /**
1640 : * Converts a set of elements in this (conforming, non-refined) mesh
1641 : * into "complete" order elements, i.e. elements which
1642 : * can store degrees of freedom on any vertex, edge, or face. For
1643 : * example, a mesh consisting of \p Tet4 or \p Tet10 will be
1644 : * converted to a mesh with \p Tet14 etc.
1645 : */
1646 : virtual void all_complete_order_range(const SimpleRange<element_iterator> & range) = 0;
1647 :
1648 : /**
1649 : * Calls the range-based version of this function with a range
1650 : * consisting of all elements in the mesh.
1651 : */
1652 : virtual void all_complete_order ();
1653 :
1654 : /**
1655 : * In a few (very rare) cases, the user may have manually tagged the
1656 : * elements with specific processor IDs by hand, without using a
1657 : * partitioner. In this case, the Mesh will not know that the total
1658 : * number of partitions, _n_parts, has changed, unless you call this
1659 : * function. This is an O(N active elements) calculation. The return
1660 : * value is the number of partitions, and _n_parts is also set by
1661 : * this function.
1662 : */
1663 : unsigned int recalculate_n_partitions();
1664 :
1665 : /**
1666 : * \returns A pointer to a subordinate \p PointLocatorBase object
1667 : * for this mesh, constructing a master PointLocator first if
1668 : * necessary. This should not be used in threaded or
1669 : * non-parallel_only code unless the master has already been
1670 : * constructed.
1671 : */
1672 : std::unique_ptr<PointLocatorBase> sub_point_locator () const;
1673 :
1674 : /**
1675 : * Set value used by PointLocatorBase::close_to_point_tol().
1676 : *
1677 : * Defaults to 0.0. If nonzero, calls close_to_point_tol() whenever
1678 : * a new PointLocator is built for use by this Mesh. Since the Mesh
1679 : * controls the creation and destruction of the PointLocator, if
1680 : * there are any parameters we need to customize on it, the Mesh
1681 : * will need to know about them.
1682 : */
1683 : void set_point_locator_close_to_point_tol(Real val);
1684 : Real get_point_locator_close_to_point_tol() const;
1685 :
1686 : /**
1687 : * Releases the current \p PointLocator object.
1688 : */
1689 : void clear_point_locator ();
1690 :
1691 : /**
1692 : * In the point locator, do we count lower dimensional elements
1693 : * when we refine point locator regions? This is relevant in
1694 : * tree-based point locators, for example.
1695 : */
1696 : void set_count_lower_dim_elems_in_point_locator(bool count_lower_dim_elems);
1697 :
1698 : /**
1699 : * Get the current value of _count_lower_dim_elems_in_point_locator.
1700 : */
1701 : bool get_count_lower_dim_elems_in_point_locator() const;
1702 :
1703 : /**
1704 : * Verify id and processor_id consistency of our elements and
1705 : * nodes containers.
1706 : * Calls libmesh_assert() on each possible failure.
1707 : * Currently only implemented on DistributedMesh; a serial data
1708 : * structure is much harder to get out of sync.
1709 : */
1710 292 : virtual void libmesh_assert_valid_parallel_ids() const {}
1711 :
1712 : #ifdef LIBMESH_ENABLE_DEPRECATED
1713 : /**
1714 : * \deprecated
1715 : * \returns A writable reference for setting an optional name for a
1716 : * subdomain. This method is deprecated; use set_subdomain_name()
1717 : * instead.
1718 : */
1719 : std::string & subdomain_name(subdomain_id_type id);
1720 : #endif // LIBMESH_ENABLE_DEPRECATED
1721 :
1722 : /**
1723 : * \returns A reference for getting an optional name for a
1724 : * subdomain.
1725 : */
1726 : const std::string & subdomain_name(subdomain_id_type id) const;
1727 :
1728 : /**
1729 : * Sets the \p name for the provided \p id
1730 : * @param id The subdomain id to set the name for
1731 : * @param name The subdomain name
1732 : * @param synchronous Whether this method is being called across all mesh ranks. If this is true,
1733 : * then we don't have to register this collective container as being out of sync
1734 : */
1735 : void set_subdomain_name(subdomain_id_type id,
1736 : const std::string & name,
1737 : bool synchronous = false);
1738 :
1739 : /**
1740 : * \returns The id of the named subdomain if it exists,
1741 : * \p Elem::invalid_subdomain_id otherwise.
1742 : */
1743 : subdomain_id_type get_id_by_name(std::string_view name) const;
1744 :
1745 : /*
1746 : * We have many combinations of iterators that filter on various
1747 : * characteristics; we use macros to make their abstract base class
1748 : * and their subclass declarations more terse.
1749 : */
1750 : #define ABSTRACT_ELEM_ITERATORS(TYPE, ARGDECL) \
1751 : virtual element_iterator TYPE##elements_begin(ARGDECL) = 0; \
1752 : virtual element_iterator TYPE##elements_end(ARGDECL) = 0; \
1753 : virtual const_element_iterator TYPE##elements_begin(ARGDECL) const = 0; \
1754 : virtual const_element_iterator TYPE##elements_end(ARGDECL) const = 0; \
1755 : virtual SimpleRange<element_iterator> TYPE##element_ptr_range(ARGDECL) = 0; \
1756 : virtual SimpleRange<const_element_iterator> TYPE##element_ptr_range(ARGDECL) const = 0;
1757 :
1758 : #define DECLARE_ELEM_ITERATORS(TYPE, ARGDECL, ARGS) \
1759 : virtual element_iterator TYPE##elements_begin(ARGDECL) override final; \
1760 : virtual element_iterator TYPE##elements_end(ARGDECL) override final; \
1761 : virtual const_element_iterator TYPE##elements_begin(ARGDECL) const override final; \
1762 : virtual const_element_iterator TYPE##elements_end(ARGDECL) const override final; \
1763 : virtual SimpleRange<element_iterator> TYPE##element_ptr_range(ARGDECL) override final { return {TYPE##elements_begin(ARGS), TYPE##elements_end(ARGS)}; } \
1764 : virtual SimpleRange<const_element_iterator> TYPE##element_ptr_range(ARGDECL) const override final { return {TYPE##elements_begin(ARGS), TYPE##elements_end(ARGS)}; }
1765 :
1766 : #define ABSTRACT_NODE_ITERATORS(TYPE, ARGDECL) \
1767 : virtual node_iterator TYPE##nodes_begin(ARGDECL) = 0; \
1768 : virtual node_iterator TYPE##nodes_end(ARGDECL) = 0; \
1769 : virtual const_node_iterator TYPE##nodes_begin(ARGDECL) const = 0; \
1770 : virtual const_node_iterator TYPE##nodes_end(ARGDECL) const = 0; \
1771 : virtual SimpleRange<node_iterator> TYPE##node_ptr_range(ARGDECL) = 0; \
1772 : virtual SimpleRange<const_node_iterator> TYPE##node_ptr_range(ARGDECL) const = 0;
1773 :
1774 : #define DECLARE_NODE_ITERATORS(TYPE, ARGDECL, ARGS) \
1775 : virtual node_iterator TYPE##nodes_begin(ARGDECL) override final; \
1776 : virtual node_iterator TYPE##nodes_end(ARGDECL) override final; \
1777 : virtual const_node_iterator TYPE##nodes_begin(ARGDECL) const override final; \
1778 : virtual const_node_iterator TYPE##nodes_end(ARGDECL) const override final; \
1779 : virtual SimpleRange<node_iterator> TYPE##node_ptr_range(ARGDECL) override final { return {TYPE##nodes_begin(ARGS), TYPE##nodes_end(ARGS)}; } \
1780 : virtual SimpleRange<const_node_iterator> TYPE##node_ptr_range(ARGDECL) const override final { return {TYPE##nodes_begin(ARGS), TYPE##nodes_end(ARGS)}; }
1781 :
1782 : #define LIBMESH_COMMA ,
1783 :
1784 : /*
1785 : * element_iterator accessors
1786 : *
1787 : * The basic elements_begin() and elements_end() iterators iterate
1788 : * over all elements in a mesh, returning element pointers or const
1789 : * element pointers when dereferenced (depending on whether the mesh
1790 : * reference was const). range-for loops can be written using
1791 : * element_ptr_range()
1792 : *
1793 : * Filtered versions of these iterators, which skip over all
1794 : * elements not matching some predicate, are also available, by
1795 : * adding a prefix to the methods above. E.g. local_ (in a form
1796 : * like local_elements_begin() or local_element_ptr_range()) will
1797 : * iterate only over elements whose processor_id() is the current
1798 : * processor, or active_ will iterate only over active elements even
1799 : * if the mesh is refined, or active_local_ will iterate over
1800 : * elements that are both active and local. Negation forms such as
1801 : * not_local_ also exist.
1802 : *
1803 : * For some iterator prefixes, such as type_, an argument is needed
1804 : * for the filter; e.g. the ElemType to select for in that case.
1805 : *
1806 : * All valid prefixes and their corresponding arguments can be found
1807 : * in the macro invocations below.
1808 : */
1809 : ABSTRACT_ELEM_ITERATORS(,) // elements_begin(), element_ptr_range(): all elements
1810 : ABSTRACT_ELEM_ITERATORS(active_,) // Elem::active() == true
1811 : ABSTRACT_ELEM_ITERATORS(ancestor_,) // Elem::ancestor() == true
1812 : ABSTRACT_ELEM_ITERATORS(subactive_,) // Elem::subactive() == true
1813 : ABSTRACT_ELEM_ITERATORS(local_,) // Elem::processor_id() == this processor
1814 : ABSTRACT_ELEM_ITERATORS(unpartitioned_,) // Elem::processor_id() == invalid_processor_id
1815 : ABSTRACT_ELEM_ITERATORS(facelocal_,) // is on or has a neighbor on this processor
1816 : ABSTRACT_ELEM_ITERATORS(level_,unsigned int level) // Elem::level() == level
1817 : ABSTRACT_ELEM_ITERATORS(pid_,processor_id_type pid) // Elem::processor_id() == pid
1818 : ABSTRACT_ELEM_ITERATORS(type_,ElemType type) // Elem::type() == type
1819 :
1820 : ABSTRACT_ELEM_ITERATORS(active_subdomain_,subdomain_id_type sid) // active && Elem::subdomain_id() == sid
1821 : ABSTRACT_ELEM_ITERATORS(active_subdomain_set_,std::set<subdomain_id_type> ss) // active && ss.contains(Elem::subdomain_id())
1822 :
1823 : // Iterators which use negations of filters described above
1824 : ABSTRACT_ELEM_ITERATORS(not_active_,)
1825 : ABSTRACT_ELEM_ITERATORS(not_ancestor_,)
1826 : ABSTRACT_ELEM_ITERATORS(not_subactive_,)
1827 : ABSTRACT_ELEM_ITERATORS(not_local_,)
1828 : ABSTRACT_ELEM_ITERATORS(not_level_,unsigned int level)
1829 :
1830 : // Iterators which combine multiple of the filters described above
1831 : ABSTRACT_ELEM_ITERATORS(active_local_,)
1832 : ABSTRACT_ELEM_ITERATORS(active_not_local_,)
1833 : ABSTRACT_ELEM_ITERATORS(active_unpartitioned_,)
1834 : ABSTRACT_ELEM_ITERATORS(active_type_,ElemType type)
1835 : ABSTRACT_ELEM_ITERATORS(active_pid_,processor_id_type pid)
1836 : ABSTRACT_ELEM_ITERATORS(local_level_,unsigned int level)
1837 : ABSTRACT_ELEM_ITERATORS(local_not_level_,unsigned int level)
1838 : ABSTRACT_ELEM_ITERATORS(active_local_subdomain_,subdomain_id_type sid)
1839 : ABSTRACT_ELEM_ITERATORS(active_local_subdomain_set_,std::set<subdomain_id_type> ss)
1840 :
1841 : // Backwards compatibility
1842 : virtual SimpleRange<element_iterator> active_subdomain_elements_ptr_range(subdomain_id_type sid) = 0;
1843 : virtual SimpleRange<const_element_iterator> active_subdomain_elements_ptr_range(subdomain_id_type sid) const = 0;
1844 : virtual SimpleRange<element_iterator> active_local_subdomain_elements_ptr_range(subdomain_id_type sid) = 0;
1845 : virtual SimpleRange<const_element_iterator> active_local_subdomain_elements_ptr_range(subdomain_id_type sid) const = 0;
1846 : virtual SimpleRange<element_iterator> active_subdomain_set_elements_ptr_range(std::set<subdomain_id_type> ss) = 0;
1847 : virtual SimpleRange<const_element_iterator> active_subdomain_set_elements_ptr_range(std::set<subdomain_id_type> ss) const = 0;
1848 :
1849 : // Discouraged from use - these iterators use outdated
1850 : // pre-GhostingFunctor definitions and should be renamed if not
1851 : // deprecated
1852 : ABSTRACT_ELEM_ITERATORS(semilocal_,) // active && Elem::is_semilocal()
1853 : ABSTRACT_ELEM_ITERATORS(ghost_,) // active && Elem::is_semilocal() && not local discouraged
1854 : ABSTRACT_ELEM_ITERATORS(active_semilocal_,)
1855 :
1856 : // solution can be evaluated, with the given DoF map, for the given
1857 : // variable number, or for all variables by default
1858 : ABSTRACT_ELEM_ITERATORS(evaluable_,const DofMap & dof_map LIBMESH_COMMA unsigned int var_num = libMesh::invalid_uint)
1859 :
1860 : // solution can be evaluated for all variables of all given DoF maps
1861 : ABSTRACT_ELEM_ITERATORS(multi_evaluable_,std::vector<const DofMap *> dof_maps)
1862 :
1863 : #ifdef LIBMESH_ENABLE_AMR
1864 : ABSTRACT_ELEM_ITERATORS(flagged_,unsigned char rflag) // Elem::refinement_flag() == rflag
1865 :
1866 : // Elem::refinement_flag() == rflag && Elem::processor_id() == pid
1867 : ABSTRACT_ELEM_ITERATORS(flagged_pid_,unsigned char rflag LIBMESH_COMMA processor_id_type pid)
1868 : #endif
1869 :
1870 : /*
1871 : * node_iterator accessors
1872 : *
1873 : * The basic nodes_begin() and nodes_end() iterators iterate
1874 : * over all nodes in a mesh, returning node pointers or const
1875 : * node pointers when dereferenced (depending on whether the mesh
1876 : * reference was const). range-for loops can be written using
1877 : * node_ptr_range()
1878 : *
1879 : * Filtered versions of these iterators, which skip over all
1880 : * nodes not matching some predicate, are also available, by
1881 : * adding a prefix to the methods above. E.g. local_ (in a form
1882 : * like local_nodes_begin() or local_node_ptr_range()) will
1883 : * iterate only over nodes whose processor_id() is the current
1884 : * processor.
1885 : *
1886 : * All valid prefixes and their corresponding arguments can be found
1887 : * in the macro invocations below.
1888 : */
1889 : ABSTRACT_NODE_ITERATORS(,) // nodes_begin(), node_ptr_range(): all nodes
1890 : ABSTRACT_NODE_ITERATORS(active_,) // Node::active() == true; i.e. Node::id() != invalid_id
1891 : ABSTRACT_NODE_ITERATORS(local_,) // Node::processor_id() == this processor
1892 : ABSTRACT_NODE_ITERATORS(bnd_,) // BoundaryInfo::n_boundary_ids(node) > 0
1893 : ABSTRACT_NODE_ITERATORS(pid_,processor_id_type pid) // Node::processor_id() == pid
1894 : ABSTRACT_NODE_ITERATORS(bid_,boundary_id_type bid) // BoundaryInfo::has_boundary_id(node, bid)
1895 :
1896 : // solution can be evaluated, with the given DoF map, for the given
1897 : // variable number, or for all variables by default
1898 : ABSTRACT_NODE_ITERATORS(evaluable_,const DofMap & dof_map LIBMESH_COMMA unsigned int var_num = libMesh::invalid_uint)
1899 :
1900 : // solution can be evaluated for all variables of all given DoF maps
1901 : ABSTRACT_NODE_ITERATORS(multi_evaluable_,std::vector<const DofMap *> dof_maps)
1902 :
1903 : // Technically these define libMesh::MeshBase::*ElemRange, but since
1904 : // those don't conflict with libMesh::*ElemRange they're as good as
1905 : // a real forward declaration, which we can't do here.
1906 : typedef StoredRange<MeshBase::element_iterator, Elem *> ElemRange;
1907 : typedef StoredRange<MeshBase::const_element_iterator, const Elem *> ConstElemRange;
1908 :
1909 : /**
1910 : * \returns A reference to a cached vector copy of a range of
1911 : * pointers to all semilocal elements, suitable for threading.
1912 : *
1913 : * Iterating over all semilocal elements is most useful for
1914 : * modifying the mesh, so we only have a non-const version for now.
1915 : */
1916 : const ElemRange & element_stored_range();
1917 :
1918 : /**
1919 : * \returns A reference to a cached vector copy of a range of
1920 : * pointers to all active local elements, suitable for threading.
1921 : *
1922 : * Iterating over only local elements is most useful for computing
1923 : * on the mesh, so we only have a non-const version for now.
1924 : */
1925 : const ConstElemRange & active_local_element_stored_range() const;
1926 :
1927 : /**
1928 : * Clears stored ranges, to indicate that the mesh has changed and
1929 : * they should be regenerated when next needed.
1930 : */
1931 : void clear_stored_ranges();
1932 :
1933 : /**
1934 : * \returns A writable reference to the whole subdomain name map
1935 : */
1936 14856 : std::map<subdomain_id_type, std::string> & set_subdomain_name_map ()
1937 37681 : { this->unset_has_synched_subdomain_name_map(); return _block_id_to_name; }
1938 2123 : const std::map<subdomain_id_type, std::string> & get_subdomain_name_map () const
1939 2399 : { return _block_id_to_name; }
1940 :
1941 : typedef std::vector<std::pair<std::pair<const Elem *, unsigned int>, Real>> constraint_rows_mapped_type;
1942 : typedef std::map<const Node *, constraint_rows_mapped_type> constraint_rows_type;
1943 :
1944 : /**
1945 : * Constraint rows accessors
1946 : */
1947 9108 : constraint_rows_type & get_constraint_rows()
1948 205345 : { return _constraint_rows; }
1949 :
1950 86117 : const constraint_rows_type & get_constraint_rows() const
1951 86117 : { return _constraint_rows; }
1952 :
1953 : dof_id_type n_constraint_rows() const;
1954 :
1955 : /**
1956 : * Copy the constraints from the other mesh to this mesh
1957 : */
1958 : void copy_constraint_rows(const MeshBase & other_mesh);
1959 :
1960 : /**
1961 : * Copy the constraints from the given matrix to this mesh. The
1962 : * \p constraint_operator should be an mxn matrix, where
1963 : * m == this->n_nodes() and the operator indexing matches the
1964 : * current node indexing. This may require users to disable mesh
1965 : * renumbering in between loading a mesh file and loading a
1966 : * constraint matrix which matches it.
1967 : *
1968 : * If any "constraint" rows in the matrix are unit vectors, the node
1969 : * corresponding to that row index will be left unconstrained, and
1970 : * will be used to constrain any other nodes which have a non-zero
1971 : * in the column index of that unit vector.
1972 : *
1973 : * For each matrix column index which does not correspond to an
1974 : * existing node, a new NodeElem will be added to the mesh on which
1975 : * to store the new unconstrained degree(s) of freedom.
1976 : *
1977 : * If \p precondition_constraint_operator is true, then the values
1978 : * of those new unconstrained degrees of freedom may be scaled to
1979 : * improve the conditioning of typical PDE matrices integrated on
1980 : * constrained mesh elements.
1981 : *
1982 : * \p T for the constraint_operator in this function should be \p
1983 : * Real or \p Number ... and the data should be \p Real - we just
1984 : * allow complex \p T for the sake of subclasses which have to be
1985 : * configured and compiled with only one runtime option.
1986 : */
1987 : template <typename T>
1988 : void copy_constraint_rows(const SparseMatrix<T> & constraint_operator,
1989 : bool precondition_constraint_operator = false);
1990 :
1991 : /**
1992 : * Prints (from processor 0) all mesh constraint rows. If \p
1993 : * print_nonlocal is true, then each constraint is printed once for
1994 : * each processor that knows about it, which may be useful for \p
1995 : * DistributedMesh debugging.
1996 : */
1997 : void print_constraint_rows(std::ostream & os=libMesh::out,
1998 : bool print_nonlocal=false) const;
1999 :
2000 : /**
2001 : * Gets a string reporting all mesh constraint rows local to
2002 : * this processor. If \p print_nonlocal is true, then nonlocal
2003 : * constraints which are locally known are included.
2004 : */
2005 : std::string get_local_constraints(bool print_nonlocal=false) const;
2006 :
2007 : #ifdef LIBMESH_ENABLE_DEPRECATED
2008 : /**
2009 : * \deprecated This method has ben replaced by \p cache_elem_data which
2010 : * caches data in addition to elem dimensions (e.g. elem subdomain ids)
2011 : * Search the mesh and cache the different dimensions of the elements
2012 : * present in the mesh. This is done in prepare_for_use(), but can
2013 : * be done manually by other classes after major mesh modifications.
2014 : */
2015 : void cache_elem_dims();
2016 : #endif // LIBMESH_ENABLE_DEPRECATED
2017 :
2018 : /*
2019 : * Search the mesh and cache data for the elements
2020 : * present in the mesh. This is done in prepare_for_use(), but can
2021 : * be done manually by other classes after major mesh modifications.
2022 : * Data cached includes:
2023 : * - elem dimensions
2024 : * - elem subdomains
2025 : */
2026 : void cache_elem_data();
2027 :
2028 : /**
2029 : * libMesh often expects all processors to know about names of all
2030 : * subdomain ids, but distributed mesh generators may only know
2031 : * about part of a mesh when creating names. This method can
2032 : * synchronize the subdomain id to name map across processors,
2033 : * assuming no conflicts exist. It is called automatically during
2034 : * complete_preparation() unless the map is already known to be
2035 : * synchronized.
2036 : */
2037 : void sync_subdomain_name_map();
2038 :
2039 : /**
2040 : * Search the mesh for elements that have a neighboring element
2041 : * of dim+1 and set that element as the interior parent
2042 : */
2043 : void detect_interior_parents();
2044 :
2045 : /**
2046 : * \return A mesh that may own interior parents of elements in this
2047 : * mesh. In most cases this mesh includes its own interior parents,
2048 : * but in cases where a separate "interior" mesh was used to create
2049 : * this mesh as a distinct lower-dimensional boundary (or boundary
2050 : * subset) mesh, the original mesh will be returned here.
2051 : */
2052 298 : const MeshBase & interior_mesh() const { return *_interior_mesh; }
2053 :
2054 : /**
2055 : * \return A writeable reference to the interior mesh.
2056 : */
2057 34326 : MeshBase & interior_mesh() { return *_interior_mesh; }
2058 :
2059 : /**
2060 : * Sets the interior mesh. For advanced use only.
2061 : */
2062 3635 : void set_interior_mesh(MeshBase & int_mesh) { _interior_mesh = &int_mesh; }
2063 :
2064 : /**
2065 : * \return The cached mesh subdomains. As long as the mesh is prepared, this
2066 : * should contain all the subdomain ids across processors. Relies on the mesh
2067 : * being prepared
2068 : */
2069 : const std::set<subdomain_id_type> & get_mesh_subdomains() const;
2070 :
2071 : #ifdef LIBMESH_ENABLE_PERIODIC
2072 : /**
2073 : * Register a pair of boundaries as disjoint neighbor boundary pairs.
2074 : */
2075 : void add_disjoint_neighbor_boundary_pairs(const boundary_id_type b1,
2076 : const boundary_id_type b2,
2077 : const RealVectorValue & translation);
2078 :
2079 : PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs();
2080 :
2081 : const PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs() const;
2082 :
2083 : void remove_disjoint_boundary_pair(const boundary_id_type b1,
2084 : const boundary_id_type b2);
2085 : #endif
2086 :
2087 : /**
2088 : * Flags indicating in what ways a mesh has been prepared for use.
2089 : */
2090 : struct Preparation
2091 : {
2092 : /**
2093 : * Constructor. Initializes all flags to false.
2094 : */
2095 : Preparation();
2096 :
2097 : /**
2098 : * Returns true iff all the flags are true.
2099 : */
2100 : explicit operator bool() const;
2101 :
2102 : /**
2103 : * Set all flags to the "set_all" value.
2104 : */
2105 : Preparation & operator= (bool set_all);
2106 :
2107 : /**
2108 : * Two Preparation objects are equivalent iff all the flags match,
2109 : * regardless of the true/false status of any given flag.
2110 : */
2111 : bool operator== (const Preparation & other) const;
2112 : bool operator!= (const Preparation & other) const;
2113 :
2114 : // Assert that a Preparation object is identical across processors
2115 : void libmesh_assert_consistent (const Parallel::Communicator & libmesh_dbg_var(comm));
2116 :
2117 : bool is_partitioned;
2118 : bool has_synched_id_counts;
2119 : bool has_neighbor_ptrs;
2120 : bool has_cached_elem_data;
2121 : bool has_interior_parent_ptrs;
2122 : bool has_removed_remote_elements;
2123 : bool has_removed_orphaned_nodes;
2124 : bool has_boundary_id_sets;
2125 : bool has_reinit_ghosting_functors;
2126 : bool has_synched_subdomain_name_map;
2127 : };
2128 :
2129 : protected:
2130 :
2131 : #ifdef LIBMESH_ENABLE_PERIODIC
2132 : /// @brief The disjoint neighbor boundary id pairs.
2133 : std::unique_ptr<PeriodicBoundaries> _disjoint_neighbor_boundary_pairs;
2134 : #endif
2135 :
2136 : /**
2137 : * This class holds the boundary information. It can store nodes, edges,
2138 : * and faces with a corresponding id that facilitates setting boundary
2139 : * conditions.
2140 : *
2141 : * Direct access to this class is now officially deprecated and will
2142 : * be removed in future libMesh versions. Use the \p get_boundary_info()
2143 : * accessor instead.
2144 : */
2145 : std::unique_ptr<BoundaryInfo> boundary_info;
2146 :
2147 : /**
2148 : * Moves any superclass data (e.g. GhostingFunctors that might rely
2149 : * on element and nodal data (which is managed by subclasses!)
2150 : * being already moved first.
2151 : *
2152 : * Must be manually called in dofobject-managing subclass move
2153 : * operators.
2154 : */
2155 : void post_dofobject_moves(MeshBase && other_mesh);
2156 :
2157 : /**
2158 : * Helper class to copy cached data, to synchronize with a possibly
2159 : * unprepared \p other_mesh
2160 : */
2161 : void copy_cached_data (const MeshBase & other_mesh);
2162 :
2163 : /**
2164 : * Shim to allow operator == (&) to behave like a virtual function
2165 : * without having to be one.
2166 : */
2167 : virtual std::string_view subclass_first_difference_from (const MeshBase & other_mesh) const = 0;
2168 :
2169 : /**
2170 : * Tests for equality of all elements and nodes in the mesh. Helper
2171 : * function for subclass_equals() in unstructured mesh subclasses.
2172 : */
2173 : bool nodes_and_elements_equal(const MeshBase & other_mesh) const;
2174 :
2175 : /**
2176 : *
2177 : */
2178 : std::string_view first_difference_from(const MeshBase & other_mesh) const;
2179 :
2180 :
2181 : /**
2182 : * \returns A writable reference to the number of partitions.
2183 : */
2184 14648 : unsigned int & set_n_partitions ()
2185 14648 : { return _n_parts; }
2186 :
2187 : /**
2188 : * The number of partitions the mesh has. This is set by
2189 : * the partitioners, and may not be changed directly by
2190 : * the user.
2191 : *
2192 : * \note The number of partitions \e need \e not equal
2193 : * this->n_processors(), consider for example the case where you
2194 : * simply want to partition a mesh on one processor and view the
2195 : * result in GMV.
2196 : */
2197 : unsigned int _n_parts;
2198 :
2199 : /**
2200 : * The default mapping type (typically Lagrange) between master and
2201 : * physical space to assign to newly added elements.
2202 : */
2203 : ElemMappingType _default_mapping_type;
2204 :
2205 : /**
2206 : * The default mapping data (unused with Lagrange, used for nodal
2207 : * weight lookup index with rational bases) to assign to newly added
2208 : * elements.
2209 : */
2210 : unsigned char _default_mapping_data;
2211 :
2212 : /**
2213 : * Flags indicating in what ways \p this mesh has been prepared.
2214 : */
2215 : Preparation _preparation;
2216 :
2217 : /**
2218 : * A cached \p ElemRange for threaded mutation of all semilocal
2219 : * elements of this mesh.
2220 : *
2221 : * This will not actually be built unless needed. Further, since we
2222 : * want our \p elem_stored_range() method to be \p const (yet do the
2223 : * dynamic allocating) this needs to be mutable.
2224 : */
2225 : mutable std::unique_ptr<ElemRange> _element_stored_range;
2226 :
2227 : /**
2228 : * A cached \p ConstElemRange for threaded calculation on all
2229 : * local elements of this mesh.
2230 : *
2231 : * This will not actually be built unless needed. Further, since we
2232 : * want our \p elem_stored_range() method to be \p const (yet do the
2233 : * dynamic allocating) this needs to be mutable.
2234 : */
2235 : mutable std::unique_ptr<ConstElemRange>
2236 : _const_active_local_element_stored_range;
2237 :
2238 : /**
2239 : * A \p PointLocator class for this mesh.
2240 : * This will not actually be built unless needed. Further, since we want
2241 : * our \p point_locator() method to be \p const (yet do the dynamic allocating)
2242 : * this needs to be mutable. Since the PointLocatorBase::build() member is used,
2243 : * and it operates on a constant reference to the mesh, this is OK.
2244 : */
2245 : mutable std::unique_ptr<PointLocatorBase> _point_locator;
2246 :
2247 : /**
2248 : * Do we count lower dimensional elements in point locator refinement?
2249 : * This is relevant in tree-based point locators, for example.
2250 : */
2251 : bool _count_lower_dim_elems_in_point_locator;
2252 :
2253 : /**
2254 : * A partitioner to use at each prepare_for_use().
2255 : *
2256 : * This will be built in the constructor of each derived class, but
2257 : * can be replaced by the user through the partitioner() accessor.
2258 : */
2259 : std::unique_ptr<Partitioner> _partitioner;
2260 :
2261 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
2262 : /**
2263 : * The next available unique id for assigning ids to DOF objects
2264 : */
2265 : unique_id_type _next_unique_id;
2266 : #endif
2267 :
2268 : /**
2269 : * Defaulting to \p this, a pointer to the mesh used to generate
2270 : * boundary elements on \p this.
2271 : */
2272 : MeshBase *_interior_mesh;
2273 :
2274 : /**
2275 : * If this is true then no partitioning should be done with the
2276 : * possible exception of orphaned nodes.
2277 : */
2278 : bool _skip_noncritical_partitioning;
2279 :
2280 : /**
2281 : * If this is true then no partitioning should be done.
2282 : */
2283 : bool _skip_all_partitioning;
2284 :
2285 : /**
2286 : * If this is true then renumbering will be kept to a minimum.
2287 : *
2288 : * This is set when prepare_for_use() is called.
2289 : */
2290 : bool _skip_renumber_nodes_and_elements;
2291 :
2292 : /**
2293 : * If this is \p true then we will skip \p find_neighbors in \p prepare_for_use
2294 : */
2295 : bool _skip_find_neighbors;
2296 :
2297 : /**
2298 : * If this is \p true then we will skip \p detect_interior_parents in \p prepare_for_use
2299 : */
2300 : bool _skip_detect_interior_parents;
2301 :
2302 : /**
2303 : * If this is false then even on DistributedMesh remote elements
2304 : * will not be deleted during mesh preparation.
2305 : *
2306 : * This is true by default.
2307 : */
2308 : bool _allow_remote_element_removal;
2309 :
2310 : /**
2311 : * The Exodus reader (and potentially other readers in the future?)
2312 : * now supports setting Node and Elem unique_ids based on values
2313 : * from within the Exodus file itself, rather than generating them
2314 : * automatically in LibMesh. In this case, the unique_ids will not
2315 : * necessarily be unique across the set of all _DofObjects_,
2316 : * although they should still be unique within the individual sets
2317 : * of Elems and Nodes. The reader can therefore set this Mesh flag
2318 : * (which defaults to false) to indicate we should be less strict
2319 : * when checking the "uniqueness" of unique_ids.
2320 : */
2321 : bool _allow_node_and_elem_unique_id_overlap;
2322 :
2323 : /**
2324 : * This structure maintains the mapping of named blocks
2325 : * for file formats that support named blocks. Currently
2326 : * this is only implemented for ExodusII
2327 : */
2328 : std::map<subdomain_id_type, std::string> _block_id_to_name;
2329 :
2330 : /**
2331 : * We cache the dimension of the elements present in the mesh.
2332 : * So, if we have a mesh with 1D and 2D elements, this structure
2333 : * will contain 1 and 2.
2334 : */
2335 : std::set<unsigned char> _elem_dims;
2336 :
2337 : /**
2338 : * We cache the (default) order of the geometric elements present in
2339 : * the mesh. E.g. if we have a mesh with TRI3 and TRI6 elements,
2340 : * this structure will contain FIRST and SECOND.
2341 : */
2342 : std::set<Order> _elem_default_orders;
2343 :
2344 : /**
2345 : * We cache the maximum nodal order supported by all the mesh's
2346 : * elements (the minimum supported_nodal_order() of any element)
2347 : */
2348 : Order _supported_nodal_order;
2349 :
2350 : /**
2351 : * We cache the subdomain ids of the elements present in the mesh.
2352 : */
2353 : std::set<subdomain_id_type> _mesh_subdomains;
2354 :
2355 : /**
2356 : * Map from "element set code" to list of set ids to which that element
2357 : * belongs (and vice-versa). Remarks:
2358 : * 1.) The elemset code is a dof_id_type because (if used) it is
2359 : * stored as an extra_integer (named "elemset_code") on all elements,
2360 : * and extra_integers are of type dof_id_type. Elements which do not
2361 : * belong to any set should be assigned an elemset code of DofObject::invalid_id.
2362 : * 2.) Element sets can be thought of as a generalization of the concept
2363 : * of a subdomain. Subdomains have the following restrictions:
2364 : * a.) A given element can only belong to a single subdomain
2365 : * b.) When using Exodus file input/output, subdomains are (unfortunately)
2366 : * tied to the concept of exodus element blocks, which consist of a single
2367 : * geometric element type, somewhat limiting their generality.
2368 : * 3.) The user is responsible for filling in the values of this map
2369 : * in a consistent manner, unless the elemsets are read in from an
2370 : * Exodus file, in which case the elemset codes will be set up
2371 : * automatically. The codes can basically be chosen arbitrarily,
2372 : * with the one requirement that elements which belong to no sets
2373 : * should have a set code of DofObject::invalid_id.
2374 : * 4.) We also keep a list of all the elemset ids which have been added in
2375 : * order to support O(1) performance behavior in n_elemsets() calls.
2376 : */
2377 : std::map<dof_id_type, const MeshBase::elemset_type *> _elemset_codes;
2378 : std::map<MeshBase::elemset_type, dof_id_type> _elemset_codes_inverse_map;
2379 : MeshBase::elemset_type _all_elemset_ids;
2380 :
2381 : /**
2382 : * The "spatial dimension" of the Mesh. See the documentation for
2383 : * Mesh::spatial_dimension() for more information.
2384 : */
2385 : unsigned char _spatial_dimension;
2386 :
2387 : /**
2388 : * The array of names for integer data associated with each element
2389 : * in the mesh
2390 : */
2391 : std::vector<std::string> _elem_integer_names;
2392 :
2393 : /**
2394 : * The array of default initialization values for integer data
2395 : * associated with each element in the mesh
2396 : */
2397 : std::vector<dof_id_type> _elem_integer_default_values;
2398 :
2399 : /**
2400 : * The array of names for integer data associated with each node
2401 : * in the mesh
2402 : */
2403 : std::vector<std::string> _node_integer_names;
2404 :
2405 : /**
2406 : * The array of default initialization values for integer data
2407 : * associated with each node in the mesh
2408 : */
2409 : std::vector<dof_id_type> _node_integer_default_values;
2410 :
2411 : /**
2412 : * Size extra-integer arrays of all elements in the mesh
2413 : */
2414 : void size_elem_extra_integers();
2415 :
2416 : /**
2417 : * Size extra-integer arrays of all nodes in the mesh
2418 : */
2419 : void size_node_extra_integers();
2420 :
2421 : /**
2422 : * Merge extra-integer arrays from an \p other mesh. Returns two
2423 : * mappings from index values in \p other to (possibly newly created)
2424 : * index values with the same string name in \p this mesh, the first
2425 : * for element integers and the second for node integers.
2426 : */
2427 : std::pair<std::vector<unsigned int>, std::vector<unsigned int>>
2428 : merge_extra_integer_names(const MeshBase & other);
2429 :
2430 : /**
2431 : * The default geometric GhostingFunctor, used to implement standard
2432 : * libMesh element ghosting behavior. We use a base class pointer
2433 : * here to avoid dragging in more header dependencies.
2434 : */
2435 : std::unique_ptr<GhostingFunctor> _default_ghosting;
2436 :
2437 : /**
2438 : * The list of all GhostingFunctor objects to be used when
2439 : * distributing a DistributedMesh.
2440 : *
2441 : * Basically unused by ReplicatedMesh for now, but belongs to
2442 : * MeshBase because the cost is trivial.
2443 : */
2444 : std::vector<GhostingFunctor *> _ghosting_functors;
2445 :
2446 : /**
2447 : * Hang on to references to any GhostingFunctor objects we were
2448 : * passed in shared_ptr form
2449 : */
2450 : std::map<GhostingFunctor *, std::shared_ptr<GhostingFunctor> > _shared_functors;
2451 :
2452 : // Keep track of any constraint equations that are inherent to the
2453 : // mesh, such as FE nodes whose Rational Bernstein values need to be
2454 : // constrained in terms of values on spline control nodes.
2455 : //
2456 : // _constraint_rows[constrained_node][i].first.first is an
2457 : // element (e.g. a NodeElem for a spline control node),
2458 : // _constraint_rows[constrained_node][i].first.second is the
2459 : // local node id of that element which is a constraining node,
2460 : // _constraint_rows[constrained_node][i].second is that node's
2461 : // constraint coefficient.
2462 : constraint_rows_type _constraint_rows;
2463 :
2464 : /**
2465 : * If nonzero, we will call PointLocatorBase::set_close_to_point_tol()
2466 : * on any PointLocators that we create.
2467 : */
2468 : Real _point_locator_close_to_point_tol;
2469 :
2470 : /**
2471 : * The partitioner class is a friend so that it can set
2472 : * the number of partitions.
2473 : */
2474 : friend class Partitioner;
2475 :
2476 : /**
2477 : * The MeshInput classes are friends so that they can set the number
2478 : * of partitions.
2479 : */
2480 : friend class MeshInput<MeshBase>;
2481 :
2482 : /**
2483 : * Make the \p BoundaryInfo class a friend so that
2484 : * it can create and interact with \p BoundaryMesh.
2485 : */
2486 : friend class BoundaryInfo;
2487 :
2488 : /**
2489 : * Make the \p MeshCommunication class a friend so that
2490 : * it can directly broadcast *_integer_names
2491 : */
2492 : friend class MeshCommunication;
2493 :
2494 :
2495 : /**
2496 : * The original iterator classes weren't properly const-safe;
2497 : * relying on their const-incorrectness is now deprecated.
2498 : */
2499 : #ifdef LIBMESH_ENABLE_DEPRECATED
2500 : typedef variant_filter_iterator<MeshBase::Predicate, Elem *> elem_filter_iter;
2501 :
2502 : typedef variant_filter_iterator<MeshBase::Predicate,
2503 : Elem * const,
2504 : Elem * const &,
2505 : Elem * const *> const_elem_filter_iter;
2506 :
2507 : typedef variant_filter_iterator<MeshBase::Predicate, Node *> node_filter_iter;
2508 :
2509 : typedef variant_filter_iterator<MeshBase::Predicate,
2510 : Node * const,
2511 : Node * const &,
2512 : Node * const *> const_node_filter_iter;
2513 : #else
2514 : typedef variant_filter_iterator<MeshBase::Predicate,
2515 : Elem * const,
2516 : Elem * const &,
2517 : Elem * const *,
2518 : const Elem * const,
2519 : const Elem * const &,
2520 : const Elem * const *> elem_filter_iter;
2521 :
2522 : typedef variant_filter_iterator<MeshBase::Predicate,
2523 : const Elem * const,
2524 : const Elem * const &,
2525 : const Elem * const *> const_elem_filter_iter;
2526 :
2527 : typedef variant_filter_iterator<MeshBase::Predicate,
2528 : Node * const,
2529 : Node * const &,
2530 : Node * const *,
2531 : const Node * const,
2532 : const Node * const &,
2533 : const Node * const *> node_filter_iter;
2534 :
2535 : typedef variant_filter_iterator<MeshBase::Predicate,
2536 : const Node * const,
2537 : const Node * const &,
2538 : const Node * const *> const_node_filter_iter;
2539 : #endif // LIBMESH_ENABLE_DEPRECATED
2540 :
2541 : };
2542 :
2543 :
2544 :
2545 :
2546 :
2547 :
2548 :
2549 :
2550 :
2551 :
2552 :
2553 : /**
2554 : * The definition of the element_iterator struct.
2555 : */
2556 : struct
2557 40158347 : MeshBase::element_iterator : MeshBase::elem_filter_iter
2558 : {
2559 : // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
2560 : template <typename PredType, typename IterType>
2561 794280 : element_iterator (const IterType & d,
2562 : const IterType & e,
2563 : const PredType & p ) :
2564 31055790 : elem_filter_iter(d,e,p) {}
2565 : };
2566 :
2567 :
2568 :
2569 :
2570 : /**
2571 : * The definition of the const_element_iterator struct. It is similar to the regular
2572 : * iterator above, but also provides an additional conversion-to-const ctor.
2573 : */
2574 : struct
2575 77877364 : MeshBase::const_element_iterator : MeshBase::const_elem_filter_iter
2576 : {
2577 : /**
2578 : * Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor.
2579 : */
2580 : template <typename PredType, typename IterType>
2581 9161976 : const_element_iterator (const IterType & d,
2582 : const IterType & e,
2583 : const PredType & p ) :
2584 46506562 : const_elem_filter_iter(d,e,p) {}
2585 :
2586 : /**
2587 : * The conversion-to-const ctor. Takes a regular iterator and calls the appropriate
2588 : * variant_filter_iterator copy constructor.
2589 : *
2590 : * \note This one is \e not templated!
2591 : */
2592 6639040 : const_element_iterator (const MeshBase::element_iterator & rhs) :
2593 3688219 : const_elem_filter_iter(rhs) {}
2594 : };
2595 :
2596 :
2597 :
2598 :
2599 :
2600 :
2601 :
2602 : /**
2603 : * The definition of the node_iterator struct.
2604 : */
2605 : struct
2606 13757168 : MeshBase::node_iterator : MeshBase::node_filter_iter
2607 : {
2608 : /**
2609 : * Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor.
2610 : */
2611 : template <typename PredType, typename IterType>
2612 391286 : node_iterator (const IterType & d,
2613 : const IterType & e,
2614 : const PredType & p ) :
2615 12379620 : node_filter_iter(d,e,p) {}
2616 : };
2617 :
2618 :
2619 :
2620 :
2621 : /**
2622 : * The definition of the const_node_iterator struct. It is similar to the regular
2623 : * iterator above, but also provides an additional conversion-to-const ctor.
2624 : */
2625 : struct
2626 9305493 : MeshBase::const_node_iterator : MeshBase::const_node_filter_iter
2627 : {
2628 : /**
2629 : * Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor.
2630 : */
2631 : template <typename PredType, typename IterType>
2632 570072 : const_node_iterator (const IterType & d,
2633 : const IterType & e,
2634 : const PredType & p ) :
2635 9618021 : const_node_filter_iter(d,e,p) {}
2636 :
2637 : /**
2638 : * The conversion-to-const ctor. Takes a regular iterator and calls the appropriate
2639 : * variant_filter_iterator copy constructor.
2640 : *
2641 : * \note This one is *not* templated!
2642 : */
2643 39260 : const_node_iterator (const MeshBase::node_iterator & rhs) :
2644 20196 : const_node_filter_iter(rhs) {}
2645 : };
2646 :
2647 :
2648 : // ------------------------------------------------------------
2649 : // Elem class member functions
2650 : inline
2651 105124 : const std::set<unsigned char> & MeshBase::elem_dimensions() const
2652 : {
2653 105124 : libmesh_assert(_preparation.has_cached_elem_data);
2654 105124 : return _elem_dims;
2655 : }
2656 :
2657 :
2658 : inline
2659 0 : const std::set<Order> & MeshBase::elem_default_orders() const
2660 : {
2661 0 : libmesh_assert(_preparation.has_cached_elem_data);
2662 0 : return _elem_default_orders;
2663 : }
2664 :
2665 :
2666 : inline
2667 12 : Order MeshBase::supported_nodal_order() const
2668 : {
2669 12 : libmesh_assert(_preparation.has_cached_elem_data);
2670 414 : return _supported_nodal_order;
2671 : }
2672 :
2673 :
2674 : inline
2675 : const std::set<subdomain_id_type> & MeshBase::get_mesh_subdomains() const
2676 : {
2677 : libmesh_assert(_preparation.has_cached_elem_data);
2678 : return _mesh_subdomains;
2679 : }
2680 :
2681 :
2682 : inline
2683 7824 : unsigned int MeshBase::spatial_dimension () const
2684 : {
2685 7824 : libmesh_assert(_preparation.has_cached_elem_data);
2686 :
2687 238931 : return cast_int<unsigned int>(_spatial_dimension);
2688 : }
2689 :
2690 : template <typename T>
2691 : inline
2692 : unsigned int MeshBase::add_elem_datum(const std::string & name,
2693 : bool allocate_data,
2694 : const T * default_value)
2695 : {
2696 : const std::size_t old_size = _elem_integer_names.size();
2697 :
2698 : unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
2699 : std::vector<dof_id_type> int_data(n_more_integers+1, DofObject::invalid_id);
2700 : if (default_value)
2701 : std::memcpy(int_data.data(), default_value, sizeof(T));
2702 :
2703 : unsigned int start_idx = this->add_elem_integer(name, false, int_data[0]);
2704 : for (unsigned int i=0; i != n_more_integers; ++i)
2705 : this->add_elem_integer(name+"__"+std::to_string(i), false, int_data[i+1]);
2706 :
2707 : if (allocate_data && old_size != _elem_integer_names.size())
2708 : this->size_elem_extra_integers();
2709 :
2710 : return start_idx;
2711 : }
2712 :
2713 :
2714 : template <typename T>
2715 : inline
2716 : std::vector<unsigned int> MeshBase::add_elem_data(const std::vector<std::string> & names,
2717 : bool allocate_data,
2718 : const std::vector<T> * default_values)
2719 : {
2720 : libmesh_assert(!default_values || default_values->size() == names.size());
2721 :
2722 : std::vector<unsigned int> returnval(names.size());
2723 :
2724 : const std::size_t old_size = _elem_integer_names.size();
2725 :
2726 : for (auto i : index_range(names))
2727 : returnval[i] =
2728 : this->add_elem_datum<T>(names[i], false,
2729 : default_values ?
2730 : (*default_values)[i] : nullptr);
2731 :
2732 : if (allocate_data && old_size != _elem_integer_names.size())
2733 : this->size_elem_extra_integers();
2734 :
2735 : return returnval;
2736 : }
2737 :
2738 :
2739 : template <typename T>
2740 : inline
2741 72 : unsigned int MeshBase::add_node_datum(const std::string & name,
2742 : bool allocate_data,
2743 : const T * default_value)
2744 : {
2745 12 : const std::size_t old_size = _node_integer_names.size();
2746 :
2747 6 : unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
2748 72 : std::vector<dof_id_type> int_data(n_more_integers+1, DofObject::invalid_id);
2749 72 : if (default_value)
2750 72 : std::memcpy(int_data.data(), default_value, sizeof(T));
2751 :
2752 78 : unsigned int start_idx = this->add_node_integer(name, false, int_data[0]);
2753 36 : for (unsigned int i=0; i != n_more_integers; ++i)
2754 36 : this->add_node_integer(name+"__"+std::to_string(i), false, int_data[i+1]);
2755 :
2756 72 : if (allocate_data && old_size != _node_integer_names.size())
2757 72 : this->size_node_extra_integers();
2758 :
2759 78 : return start_idx;
2760 : }
2761 :
2762 :
2763 : template <typename T>
2764 : inline
2765 : std::vector<unsigned int> MeshBase::add_node_data(const std::vector<std::string> & names,
2766 : bool allocate_data,
2767 : const std::vector<T> * default_values)
2768 : {
2769 : libmesh_assert(!default_values || default_values->size() == names.size());
2770 :
2771 : std::vector<unsigned int> returnval(names.size());
2772 :
2773 : const std::size_t old_size = _node_integer_names.size();
2774 :
2775 : for (auto i : index_range(names))
2776 : returnval[i] =
2777 : this->add_node_datum<T>(names[i], false,
2778 : default_values ?
2779 : (*default_values)[i] : nullptr);
2780 :
2781 : if (allocate_data && old_size != _node_integer_names.size())
2782 : this->size_node_extra_integers();
2783 :
2784 : return returnval;
2785 : }
2786 :
2787 :
2788 :
2789 : } // namespace libMesh
2790 :
2791 : #endif // LIBMESH_MESH_BASE_H
|