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