libMesh
mesh_tools.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 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 // Local includes
21 #include "libmesh/elem.h"
22 #include "libmesh/elem_range.h"
23 #include "libmesh/libmesh_logging.h"
24 #include "libmesh/mesh_base.h"
25 #include "libmesh/mesh_communication.h"
26 #include "libmesh/mesh_tools.h"
27 #include "libmesh/node_range.h"
28 #include "libmesh/parallel.h"
29 #include "libmesh/parallel_algebra.h"
30 #include "libmesh/parallel_ghost_sync.h"
31 #include "libmesh/sphere.h"
32 #include "libmesh/threads.h"
33 #include "libmesh/enum_to_string.h"
34 #include "libmesh/enum_elem_type.h"
35 #include "libmesh/int_range.h"
36 #include "libmesh/utility.h"
37 
38 #ifdef DEBUG
39 # include "libmesh/remote_elem.h"
40 #endif
41 
42 // C++ includes
43 #include <limits>
44 #include <numeric> // for std::accumulate
45 #include <set>
46 #include <unordered_map>
47 #include <unordered_set>
48 
49 
50 
51 // ------------------------------------------------------------
52 // anonymous namespace for helper classes
53 namespace {
54 
55 using namespace libMesh;
56 
64 class SumElemWeight
65 {
66 public:
67  SumElemWeight () :
68  _weight(0)
69  {}
70 
71  SumElemWeight (SumElemWeight &, Threads::split) :
72  _weight(0)
73  {}
74 
75  void operator()(const ConstElemRange & range)
76  {
77  for (const auto & elem : range)
78  _weight += elem->n_nodes();
79  }
80 
81  dof_id_type weight() const
82  { return _weight; }
83 
84  // If we don't have threads we never need a join, and icpc yells a
85  // warning if it sees an anonymous function that's never used
86 #if LIBMESH_USING_THREADS
87  void join (const SumElemWeight & other)
88  { _weight += other.weight(); }
89 #endif
90 
91 private:
92  dof_id_type _weight;
93 };
94 
95 
102 class FindBBox
103 {
104 public:
105  FindBBox () : _bbox()
106  {}
107 
108  FindBBox (FindBBox & other, Threads::split) :
109  _bbox(other._bbox)
110  {}
111 
112  void operator()(const ConstNodeRange & range)
113  {
114  for (const auto & node : range)
115  {
116  libmesh_assert(node);
117  _bbox.union_with(*node);
118  }
119  }
120 
121  void operator()(const ConstElemRange & range)
122  {
123  for (const auto & elem : range)
124  {
125  libmesh_assert(elem);
126  _bbox.union_with(elem->loose_bounding_box());
127  }
128  }
129 
130  Point & min() { return _bbox.min(); }
131 
132  Point & max() { return _bbox.max(); }
133 
134  // If we don't have threads we never need a join, and icpc yells a
135  // warning if it sees an anonymous function that's never used
136 #if LIBMESH_USING_THREADS
137  void join (const FindBBox & other)
138  {
139  _bbox.union_with(other._bbox);
140  }
141 #endif
142 
143  libMesh::BoundingBox & bbox ()
144  {
145  return _bbox;
146  }
147 
148 private:
149  BoundingBox _bbox;
150 };
151 
152 #ifdef DEBUG
153 void assert_semiverify_dofobj(const Parallel::Communicator & communicator,
154  const DofObject * d,
155  unsigned int sysnum = libMesh::invalid_uint)
156 {
157  if (d)
158  {
159  const unsigned int n_sys = d->n_systems();
160 
161  std::vector<unsigned int> n_vars (n_sys, 0);
162  for (unsigned int s = 0; s != n_sys; ++s)
163  if (sysnum == s ||
164  sysnum == libMesh::invalid_uint)
165  n_vars[s] = d->n_vars(s);
166 
167  const unsigned int tot_n_vars =
168  std::accumulate(n_vars.begin(), n_vars.end(), 0);
169 
170  std::vector<unsigned int> n_comp (tot_n_vars, 0);
171  std::vector<dof_id_type> first_dof (tot_n_vars, 0);
172 
173  for (unsigned int s = 0, i=0; s != n_sys; ++s)
174  {
175  if (sysnum != s &&
176  sysnum != libMesh::invalid_uint)
177  continue;
178 
179  for (unsigned int v = 0; v != n_vars[s]; ++v, ++i)
180  {
181  n_comp[i] = d->n_comp(s,v);
182  first_dof[i] = n_comp[i] ? d->dof_number(s,v,0) : DofObject::invalid_id;
183  }
184  }
185 
186  libmesh_assert(communicator.semiverify(&n_sys));
187  libmesh_assert(communicator.semiverify(&n_vars));
188  libmesh_assert(communicator.semiverify(&n_comp));
189  libmesh_assert(communicator.semiverify(&first_dof));
190  }
191  else
192  {
193  const unsigned int * p_ui = nullptr;
194  const std::vector<unsigned int> * p_vui = nullptr;
195  const std::vector<dof_id_type> * p_vdid = nullptr;
196 
197  libmesh_assert(communicator.semiverify(p_ui));
198  libmesh_assert(communicator.semiverify(p_vui));
199  libmesh_assert(communicator.semiverify(p_vui));
200  libmesh_assert(communicator.semiverify(p_vdid));
201  }
202 }
203 #endif // DEBUG
204 
205 }
206 
207 
208 namespace libMesh
209 {
210 
211 // ------------------------------------------------------------
212 // MeshTools functions
214 {
215  if (!mesh.is_serial())
216  {
217  libmesh_parallel_only(mesh.comm());
219  mesh.comm().sum(weight);
220  dof_id_type unpartitioned_weight =
222  return weight + unpartitioned_weight;
223  }
224 
225  SumElemWeight sew;
226 
228  mesh.elements_end()),
229  sew);
230  return sew.weight();
231 
232 }
233 
234 
235 
237 {
238  SumElemWeight sew;
239 
241  mesh.pid_elements_end(pid)),
242  sew);
243  return sew.weight();
244 }
245 
246 
247 
249  std::vector<std::vector<dof_id_type>> & nodes_to_elem_map)
250 {
251  nodes_to_elem_map.resize (mesh.n_nodes());
252 
253  for (const auto & elem : mesh.element_ptr_range())
254  for (auto & node : elem->node_ref_range())
255  {
256  libmesh_assert_less (node.id(), nodes_to_elem_map.size());
257  libmesh_assert_less (elem->id(), mesh.n_elem());
258 
259  nodes_to_elem_map[node.id()].push_back(elem->id());
260  }
261 }
262 
263 
264 
266  std::vector<std::vector<const Elem *>> & nodes_to_elem_map)
267 {
268  nodes_to_elem_map.resize (mesh.n_nodes());
269 
270  for (const auto & elem : mesh.element_ptr_range())
271  for (auto & node : elem->node_ref_range())
272  {
273  libmesh_assert_less (node.id(), nodes_to_elem_map.size());
274 
275  nodes_to_elem_map[node.id()].push_back(elem);
276  }
277 }
278 
279 
280 
282  std::unordered_map<dof_id_type, std::vector<dof_id_type>> & nodes_to_elem_map)
283 {
284  nodes_to_elem_map.clear();
285 
286  for (const auto & elem : mesh.element_ptr_range())
287  for (auto & node : elem->node_ref_range())
288  nodes_to_elem_map[node.id()].push_back(elem->id());
289 }
290 
291 
292 
294  std::unordered_map<dof_id_type, std::vector<const Elem *>> & nodes_to_elem_map)
295 {
296  nodes_to_elem_map.clear();
297 
298  for (const auto & elem : mesh.element_ptr_range())
299  for (auto & node : elem->node_ref_range())
300  nodes_to_elem_map[node.id()].push_back(elem);
301 }
302 
303 
304 
305 #ifdef LIBMESH_ENABLE_DEPRECATED
307  std::vector<bool> & on_boundary)
308 {
309  libmesh_deprecated();
310 
311  // Resize the vector which holds boundary nodes and fill with false.
312  on_boundary.resize(mesh.max_node_id());
313  std::fill(on_boundary.begin(),
314  on_boundary.end(),
315  false);
316 
317  // Loop over elements, find those on boundary, and
318  // mark them as true in on_boundary.
319  for (const auto & elem : mesh.active_element_ptr_range())
320  for (auto s : elem->side_index_range())
321  if (elem->neighbor_ptr(s) == nullptr) // on the boundary
322  {
323  std::unique_ptr<const Elem> side = elem->build_side_ptr(s);
324 
325  auto nodes_on_side = elem->nodes_on_side(s);
326 
327  for (auto & node_id : nodes_on_side)
328  on_boundary[node_id] = true;
329  }
330 }
331 #endif
332 
333 std::unordered_set<dof_id_type>
335 {
336  std::unordered_set<dof_id_type> boundary_nodes;
337 
338  // Loop over elements, find those on boundary, and
339  // mark them as true in on_boundary.
340  for (const auto & elem : mesh.active_element_ptr_range())
341  for (auto s : elem->side_index_range())
342  if (elem->neighbor_ptr(s) == nullptr) // on the boundary
343  {
344  auto nodes_on_side = elem->nodes_on_side(s);
345 
346  for (auto & local_id : nodes_on_side)
347  boundary_nodes.insert(elem->node_ptr(local_id)->id());
348  }
349 
350  return boundary_nodes;
351 }
352 
353 std::unordered_set<dof_id_type>
355 {
356  std::unordered_set<dof_id_type> block_boundary_nodes;
357 
358  // Loop over elements, find those on boundary, and
359  // mark them as true in on_boundary.
360  for (const auto & elem : mesh.active_element_ptr_range())
361  for (auto s : elem->side_index_range())
362  if (elem->neighbor_ptr(s) && (elem->neighbor_ptr(s)->subdomain_id() != elem->subdomain_id()))
363  {
364  auto nodes_on_side = elem->nodes_on_side(s);
365 
366  for (auto & local_id : nodes_on_side)
367  block_boundary_nodes.insert(elem->node_ptr(local_id)->id());
368  }
369 
370  return block_boundary_nodes;
371 }
372 
373 
374 #ifdef LIBMESH_ENABLE_DEPRECATED
377 {
378  // This function is deprecated. It simply calls
379  // create_bounding_box() and converts the result to a
380  // MeshTools::BoundingBox.
381  libmesh_deprecated();
383 }
384 #endif
385 
386 
387 
390 {
391  // This function must be run on all processors at once
392  libmesh_parallel_only(mesh.comm());
393 
394  FindBBox find_bbox;
395 
396  // Start with any unpartitioned elements we know about locally
399  find_bbox);
400 
401  // And combine with our local elements
402  find_bbox.bbox().union_with(MeshTools::create_local_bounding_box(mesh));
403 
404  // Compare the bounding boxes across processors
405  mesh.comm().min(find_bbox.min());
406  mesh.comm().max(find_bbox.max());
407 
408  return find_bbox.bbox();
409 }
410 
411 
412 
415 {
416  // This function must be run on all processors at once
417  libmesh_parallel_only(mesh.comm());
418 
419  FindBBox find_bbox;
420 
421  // Start with any unpartitioned nodes we know about locally
424  find_bbox);
425 
426  // Add our local nodes
429  find_bbox);
430 
431  // Compare the bounding boxes across processors
432  mesh.comm().min(find_bbox.min());
433  mesh.comm().max(find_bbox.max());
434 
435  return find_bbox.bbox();
436 }
437 
438 
439 
440 Sphere
442 {
444 
445  const Real diag = (bbox.second - bbox.first).norm();
446  const Point cent = (bbox.second + bbox.first)/2;
447 
448  return Sphere (cent, .5*diag);
449 }
450 
451 
452 
455 {
456  FindBBox find_bbox;
457 
460  find_bbox);
461 
462  return find_bbox.bbox();
463 }
464 
465 
466 
467 #ifdef LIBMESH_ENABLE_DEPRECATED
470  const processor_id_type pid)
471 {
472  libmesh_deprecated();
474 }
475 #endif
476 
477 
478 
481  const processor_id_type pid)
482 {
483  // This can only be run in parallel, with consistent arguments.
484  libmesh_parallel_only(mesh.comm());
485  libmesh_assert(mesh.comm().verify(pid));
486 
487  libmesh_assert_less (pid, mesh.n_processors());
488 
489  FindBBox find_bbox;
490 
492  mesh.pid_elements_end(pid)),
493  find_bbox);
494 
495  // Compare the bounding boxes across processors
496  mesh.comm().min(find_bbox.min());
497  mesh.comm().max(find_bbox.max());
498 
499  return find_bbox.bbox();
500 }
501 
502 
503 
504 Sphere
506  const processor_id_type pid)
507 {
508  libMesh::BoundingBox bbox =
510 
511  const Real diag = (bbox.second - bbox.first).norm();
512  const Point cent = (bbox.second + bbox.first)/2;
513 
514  return Sphere (cent, .5*diag);
515 }
516 
517 
518 
519 #ifdef LIBMESH_ENABLE_DEPRECATED
522  const subdomain_id_type sid)
523 {
524  libmesh_deprecated();
526 }
527 #endif
528 
529 
530 
533  const subdomain_id_type sid)
534 {
535  // This can only be run in parallel, with consistent arguments.
536  libmesh_parallel_only(mesh.comm());
537  libmesh_assert(mesh.comm().verify(sid));
538 
539  FindBBox find_bbox;
540 
544  find_bbox);
545 
546  // Compare the bounding boxes across processors
547  mesh.comm().min(find_bbox.min());
548  mesh.comm().max(find_bbox.max());
549 
550  return find_bbox.bbox();
551 }
552 
553 
554 
555 Sphere
557  const subdomain_id_type sid)
558 {
559  libMesh::BoundingBox bbox =
561 
562  const Real diag = (bbox.second - bbox.first).norm();
563  const Point cent = (bbox.second + bbox.first)/2;
564 
565  return Sphere (cent, .5*diag);
566 }
567 
568 
569 
571  std::vector<ElemType> & et)
572 {
573  // Loop over the the elements. If the current element type isn't in
574  // the vector, insert it.
575  for (const auto & elem : mesh.element_ptr_range())
576  if (!std::count(et.begin(), et.end(), elem->type()))
577  et.push_back(elem->type());
578 }
579 
580 
581 
583  const ElemType type)
584 {
585  return static_cast<dof_id_type>(std::distance(mesh.type_elements_begin(type),
586  mesh.type_elements_end (type)));
587 }
588 
589 
590 
592  const ElemType type)
593 {
594  return static_cast<dof_id_type>(std::distance(mesh.active_type_elements_begin(type),
596 }
597 
599  const ElemType type,
600  const unsigned int level)
601 {
602  dof_id_type cnt = 0;
603 
604  // iterate over the elements of the specified type
605  for (const auto & elem : as_range(mesh.type_elements_begin(type),
606  mesh.type_elements_end(type)))
607  if ((elem->level() == level) && !elem->subactive())
608  cnt++;
609 
610  return cnt;
611 }
612 
613 
615 {
616  unsigned int nl = 0;
617 
618  for (auto & elem : mesh.active_local_element_ptr_range())
619  nl = std::max(elem->level() + 1, nl);
620 
621  return nl;
622 }
623 
624 
625 
627 {
628  libmesh_parallel_only(mesh.comm());
629 
630  unsigned int nl = MeshTools::n_active_local_levels(mesh);
631 
632  for (const auto & elem : as_range(mesh.unpartitioned_elements_begin(),
634  if (elem->active())
635  nl = std::max(elem->level() + 1, nl);
636 
637  mesh.comm().max(nl);
638  return nl;
639 }
640 
641 
642 
644 {
645  unsigned int nl = 0;
646 
647  for (const auto & elem : as_range(mesh.local_elements_begin(),
649  nl = std::max(elem->level() + 1, nl);
650 
651  return nl;
652 }
653 
654 
655 
656 unsigned int MeshTools::n_levels(const MeshBase & mesh)
657 {
658  libmesh_parallel_only(mesh.comm());
659 
660  unsigned int nl = MeshTools::n_local_levels(mesh);
661 
662  for (const auto & elem : as_range(mesh.unpartitioned_elements_begin(),
664  nl = std::max(elem->level() + 1, nl);
665 
666  mesh.comm().max(nl);
667 
668  // n_levels() is only valid and should only be called in cases where
669  // the mesh is validly distributed (or serialized). Let's run an
670  // expensive test in debug mode to make sure this is such a case.
671 #ifdef DEBUG
672  const unsigned int paranoid_nl = MeshTools::paranoid_n_levels(mesh);
673  libmesh_assert_equal_to(nl, paranoid_nl);
674 #endif
675  return nl;
676 }
677 
678 
679 
681 {
682  libmesh_parallel_only(mesh.comm());
683 
684  unsigned int nl = 0;
685  for (const auto & elem : mesh.element_ptr_range())
686  nl = std::max(elem->level() + 1, nl);
687 
688  mesh.comm().max(nl);
689  return nl;
690 }
691 
692 
693 
695  std::set<dof_id_type> & not_subactive_node_ids)
696 {
697  for (const auto & elem : mesh.element_ptr_range())
698  if (!elem->subactive())
699  for (auto & n : elem->node_ref_range())
700  not_subactive_node_ids.insert(n.id());
701 }
702 
703 
704 
707 {
708  return cast_int<dof_id_type>(std::distance(begin, end));
709 }
710 
711 
712 
715 {
716  return cast_int<dof_id_type>(std::distance(begin, end));
717 }
718 
719 
720 
721 unsigned int MeshTools::n_p_levels (const MeshBase & mesh)
722 {
723  libmesh_parallel_only(mesh.comm());
724 
725  unsigned int max_p_level = 0;
726 
727  // first my local elements
728  for (const auto & elem : as_range(mesh.local_elements_begin(),
730  max_p_level = std::max(elem->p_level(), max_p_level);
731 
732  // then any unpartitioned objects
733  for (const auto & elem : as_range(mesh.unpartitioned_elements_begin(),
735  max_p_level = std::max(elem->p_level(), max_p_level);
736 
737  mesh.comm().max(max_p_level);
738  return max_p_level + 1;
739 }
740 
741 
742 
744  const Node & node,
745  const std::vector<std::vector<const Elem *>> & nodes_to_elem_map,
746  std::vector<const Node *> & neighbors)
747 {
748  // We'll refer back to the Node ID several times
749  dof_id_type global_id = node.id();
750 
751  // We'll construct a std::set<const Node *> for more efficient
752  // searching while finding the nodal neighbors, and return it to the
753  // user in a std::vector.
754  std::set<const Node *> neighbor_set;
755 
756  // Look through the elements that contain this node
757  // find the local node id... then find the side that
758  // node lives on in the element
759  // next, look for the _other_ node on that side
760  // That other node is a "nodal_neighbor"... save it
761  for (const auto & elem : nodes_to_elem_map[global_id])
762  {
763  // We only care about active elements...
764  if (elem->active())
765  {
766  // Which local node number is global_id?
767  unsigned local_node_number = elem->local_node(global_id);
768 
769  // Make sure it was found
770  libmesh_assert_not_equal_to(local_node_number, libMesh::invalid_uint);
771 
772  const unsigned short n_edges = elem->n_edges();
773 
774  // If this element has no edges, the edge-based algorithm below doesn't make sense.
775  if (!n_edges)
776  {
777  switch (elem->type())
778  {
779  case EDGE2:
780  {
781  switch (local_node_number)
782  {
783  case 0:
784  // The other node is a nodal neighbor
785  neighbor_set.insert(elem->node_ptr(1));
786  break;
787 
788  case 1:
789  // The other node is a nodal neighbor
790  neighbor_set.insert(elem->node_ptr(0));
791  break;
792 
793  default:
794  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
795  }
796  break;
797  }
798 
799  case EDGE3:
800  {
801  switch (local_node_number)
802  {
803  // The outside nodes have node 2 as a neighbor
804  case 0:
805  case 1:
806  neighbor_set.insert(elem->node_ptr(2));
807  break;
808 
809  // The middle node has the outer nodes as neighbors
810  case 2:
811  neighbor_set.insert(elem->node_ptr(0));
812  neighbor_set.insert(elem->node_ptr(1));
813  break;
814 
815  default:
816  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
817  }
818  break;
819  }
820 
821  case EDGE4:
822  {
823  switch (local_node_number)
824  {
825  case 0:
826  // The left-middle node is a nodal neighbor
827  neighbor_set.insert(elem->node_ptr(2));
828  break;
829 
830  case 1:
831  // The right-middle node is a nodal neighbor
832  neighbor_set.insert(elem->node_ptr(3));
833  break;
834 
835  // The left-middle node
836  case 2:
837  neighbor_set.insert(elem->node_ptr(0));
838  neighbor_set.insert(elem->node_ptr(3));
839  break;
840 
841  // The right-middle node
842  case 3:
843  neighbor_set.insert(elem->node_ptr(1));
844  neighbor_set.insert(elem->node_ptr(2));
845  break;
846 
847  default:
848  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
849  }
850  break;
851  }
852 
853  default:
854  libmesh_error_msg("Unrecognized ElemType: " << Utility::enum_to_string(elem->type()) << std::endl);
855  }
856  }
857 
858  // Index of the current edge
859  unsigned current_edge = 0;
860 
861  const unsigned short n_nodes = elem->n_nodes();
862 
863  while (current_edge < n_edges)
864  {
865  // Find the edge the node is on
866  bool found_edge = false;
867  for (; current_edge<n_edges; ++current_edge)
868  if (elem->is_node_on_edge(local_node_number, current_edge))
869  {
870  found_edge = true;
871  break;
872  }
873 
874  // Did we find one?
875  if (found_edge)
876  {
877  const Node * node_to_save = nullptr;
878 
879  // Find another node in this element on this edge
880  for (unsigned other_node_this_edge = 0; other_node_this_edge != n_nodes; other_node_this_edge++)
881  if ( (elem->is_node_on_edge(other_node_this_edge, current_edge)) && // On the current edge
882  (elem->node_id(other_node_this_edge) != global_id)) // But not the original node
883  {
884  // We've found a nodal neighbor! Save a pointer to it..
885  node_to_save = elem->node_ptr(other_node_this_edge);
886  break;
887  }
888 
889  // Make sure we found something
890  libmesh_assert(node_to_save != nullptr);
891 
892  neighbor_set.insert(node_to_save);
893  }
894 
895  // Keep looking for edges, node may be on more than one edge
896  current_edge++;
897  }
898  } // if (elem->active())
899  } // for
900 
901  // Assign the entries from the set to the vector. Note: this
902  // replaces any existing contents in neighbors and modifies its size
903  // accordingly.
904  neighbors.assign(neighbor_set.begin(), neighbor_set.end());
905 }
906 
907 
908 
910  const Node & node,
911  const std::unordered_map<dof_id_type, std::vector<const Elem *>> & nodes_to_elem_map,
912  std::vector<const Node *> & neighbors)
913 {
914  // We'll refer back to the Node ID several times
915  dof_id_type global_id = node.id();
916 
917  // We'll construct a std::set<const Node *> for more efficient
918  // searching while finding the nodal neighbors, and return it to the
919  // user in a std::vector.
920  std::set<const Node *> neighbor_set;
921 
922  // List of Elems attached to this node.
923  const auto & elem_vec = libmesh_map_find(nodes_to_elem_map, global_id);
924 
925  // Look through the elements that contain this node
926  // find the local node id... then find the side that
927  // node lives on in the element
928  // next, look for the _other_ node on that side
929  // That other node is a "nodal_neighbor"... save it
930  for (const auto & elem : elem_vec)
931  {
932  // We only care about active elements...
933  if (elem->active())
934  {
935  // Which local node number is global_id?
936  unsigned local_node_number = elem->local_node(global_id);
937 
938  // Make sure it was found
939  libmesh_assert_not_equal_to(local_node_number, libMesh::invalid_uint);
940 
941  const unsigned short n_edges = elem->n_edges();
942 
943  // If this element has no edges, the edge-based algorithm below doesn't make sense.
944  if (!n_edges)
945  {
946  switch (elem->type())
947  {
948  case EDGE2:
949  {
950  switch (local_node_number)
951  {
952  case 0:
953  // The other node is a nodal neighbor
954  neighbor_set.insert(elem->node_ptr(1));
955  break;
956 
957  case 1:
958  // The other node is a nodal neighbor
959  neighbor_set.insert(elem->node_ptr(0));
960  break;
961 
962  default:
963  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
964  }
965  break;
966  }
967 
968  case EDGE3:
969  {
970  switch (local_node_number)
971  {
972  // The outside nodes have node 2 as a neighbor
973  case 0:
974  case 1:
975  neighbor_set.insert(elem->node_ptr(2));
976  break;
977 
978  // The middle node has the outer nodes as neighbors
979  case 2:
980  neighbor_set.insert(elem->node_ptr(0));
981  neighbor_set.insert(elem->node_ptr(1));
982  break;
983 
984  default:
985  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
986  }
987  break;
988  }
989 
990  case EDGE4:
991  {
992  switch (local_node_number)
993  {
994  case 0:
995  // The left-middle node is a nodal neighbor
996  neighbor_set.insert(elem->node_ptr(2));
997  break;
998 
999  case 1:
1000  // The right-middle node is a nodal neighbor
1001  neighbor_set.insert(elem->node_ptr(3));
1002  break;
1003 
1004  // The left-middle node
1005  case 2:
1006  neighbor_set.insert(elem->node_ptr(0));
1007  neighbor_set.insert(elem->node_ptr(3));
1008  break;
1009 
1010  // The right-middle node
1011  case 3:
1012  neighbor_set.insert(elem->node_ptr(1));
1013  neighbor_set.insert(elem->node_ptr(2));
1014  break;
1015 
1016  default:
1017  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
1018  }
1019  break;
1020  }
1021 
1022  default:
1023  libmesh_error_msg("Unrecognized ElemType: " << Utility::enum_to_string(elem->type()) << std::endl);
1024  }
1025  }
1026 
1027  // Index of the current edge
1028  unsigned current_edge = 0;
1029 
1030  const unsigned short n_nodes = elem->n_nodes();
1031 
1032  while (current_edge < n_edges)
1033  {
1034  // Find the edge the node is on
1035  bool found_edge = false;
1036  for (; current_edge<n_edges; ++current_edge)
1037  if (elem->is_node_on_edge(local_node_number, current_edge))
1038  {
1039  found_edge = true;
1040  break;
1041  }
1042 
1043  // Did we find one?
1044  if (found_edge)
1045  {
1046  const Node * node_to_save = nullptr;
1047 
1048  // Find another node in this element on this edge
1049  for (unsigned other_node_this_edge = 0; other_node_this_edge != n_nodes; other_node_this_edge++)
1050  if ( (elem->is_node_on_edge(other_node_this_edge, current_edge)) && // On the current edge
1051  (elem->node_id(other_node_this_edge) != global_id)) // But not the original node
1052  {
1053  // We've found a nodal neighbor! Save a pointer to it..
1054  node_to_save = elem->node_ptr(other_node_this_edge);
1055  break;
1056  }
1057 
1058  // Make sure we found something
1059  libmesh_assert(node_to_save != nullptr);
1060 
1061  neighbor_set.insert(node_to_save);
1062  }
1063 
1064  // Keep looking for edges, node may be on more than one edge
1065  current_edge++;
1066  }
1067  } // if (elem->active())
1068  } // for
1069 
1070  // Assign the entries from the set to the vector. Note: this
1071  // replaces any existing contents in neighbors and modifies its size
1072  // accordingly.
1073  neighbors.assign(neighbor_set.begin(), neighbor_set.end());
1074 }
1075 
1076 
1077 
1079  std::map<dof_id_type, std::vector<dof_id_type>> & hanging_nodes)
1080 {
1081  // Loop through all the elements
1082  for (auto & elem : mesh.active_local_element_ptr_range())
1083  if (elem->type() == QUAD4)
1084  for (auto s : elem->side_index_range())
1085  {
1086  // Loop over the sides looking for sides that have hanging nodes
1087  // This code is inspired by compute_proj_constraints()
1088  const Elem * neigh = elem->neighbor_ptr(s);
1089 
1090  // If not a boundary side
1091  if (neigh != nullptr)
1092  {
1093  // Is there a coarser element next to this one?
1094  if (neigh->level() < elem->level())
1095  {
1096  const Elem * ancestor = elem;
1097  while (neigh->level() < ancestor->level())
1098  ancestor = ancestor->parent();
1099  unsigned int s_neigh = neigh->which_neighbor_am_i(ancestor);
1100  libmesh_assert_less (s_neigh, neigh->n_neighbors());
1101 
1102  // Couple of helper uints...
1103  unsigned int local_node1=0;
1104  unsigned int local_node2=0;
1105 
1106  bool found_in_neighbor = false;
1107 
1108  // Find the two vertices that make up this side
1109  while (!elem->is_node_on_side(local_node1++,s)) { }
1110  local_node1--;
1111 
1112  // Start looking for the second one with the next node
1113  local_node2=local_node1+1;
1114 
1115  // Find the other one
1116  while (!elem->is_node_on_side(local_node2++,s)) { }
1117  local_node2--;
1118 
1119  //Pull out their global ids:
1120  dof_id_type node1 = elem->node_id(local_node1);
1121  dof_id_type node2 = elem->node_id(local_node2);
1122 
1123  // Now find which node is present in the neighbor
1124  // FIXME This assumes a level one rule!
1125  // The _other_ one is the hanging node
1126 
1127  // First look for the first one
1128  // FIXME could be streamlined a bit
1129  for (unsigned int n=0;n<neigh->n_sides();n++)
1130  if (neigh->node_id(n) == node1)
1131  found_in_neighbor=true;
1132 
1133  dof_id_type hanging_node=0;
1134 
1135  if (!found_in_neighbor)
1136  hanging_node=node1;
1137  else // If it wasn't node1 then it must be node2!
1138  hanging_node=node2;
1139 
1140  // Reset these for reuse
1141  local_node1=0;
1142  local_node2=0;
1143 
1144  // Find the first node that makes up the side in the neighbor (these should be the parent nodes)
1145  while (!neigh->is_node_on_side(local_node1++,s_neigh)) { }
1146  local_node1--;
1147 
1148  local_node2=local_node1+1;
1149 
1150  // Find the second node...
1151  while (!neigh->is_node_on_side(local_node2++,s_neigh)) { }
1152  local_node2--;
1153 
1154  // Save them if we haven't already found the parents for this one
1155  if (hanging_nodes[hanging_node].size()<2)
1156  {
1157  hanging_nodes[hanging_node].push_back(neigh->node_id(local_node1));
1158  hanging_nodes[hanging_node].push_back(neigh->node_id(local_node2));
1159  }
1160  }
1161  }
1162  }
1163 }
1164 
1165 
1166 
1167 #ifdef DEBUG
1169 {
1170  LOG_SCOPE("libmesh_assert_equal_n_systems()", "MeshTools");
1171 
1172  unsigned int n_sys = libMesh::invalid_uint;
1173 
1174  for (const auto & elem : mesh.element_ptr_range())
1175  {
1176  if (n_sys == libMesh::invalid_uint)
1177  n_sys = elem->n_systems();
1178  else
1179  libmesh_assert_equal_to (elem->n_systems(), n_sys);
1180  }
1181 
1182  for (const auto & node : mesh.node_ptr_range())
1183  {
1184  if (n_sys == libMesh::invalid_uint)
1185  n_sys = node->n_systems();
1186  else
1187  libmesh_assert_equal_to (node->n_systems(), n_sys);
1188  }
1189 }
1190 
1191 
1192 
1193 #ifdef LIBMESH_ENABLE_AMR
1195 {
1196  LOG_SCOPE("libmesh_assert_old_dof_objects()", "MeshTools");
1197 
1198  for (const auto & elem : mesh.element_ptr_range())
1199  {
1200  if (elem->refinement_flag() == Elem::JUST_REFINED ||
1201  elem->refinement_flag() == Elem::INACTIVE)
1202  continue;
1203 
1204  if (elem->has_dofs())
1205  libmesh_assert(elem->old_dof_object);
1206 
1207  for (auto & node : elem->node_ref_range())
1208  if (node.has_dofs())
1209  libmesh_assert(node.old_dof_object);
1210  }
1211 }
1212 #else
1214 #endif // LIBMESH_ENABLE_AMR
1215 
1216 
1217 
1219 {
1220  LOG_SCOPE("libmesh_assert_valid_node_pointers()", "MeshTools");
1221 
1222  // Here we specifically do not want "auto &" because we need to
1223  // reseat the (temporary) pointer variable in the loop below,
1224  // without modifying the original.
1225  for (const Elem * elem : mesh.element_ptr_range())
1226  {
1227  libmesh_assert (elem);
1228  while (elem)
1229  {
1230  elem->libmesh_assert_valid_node_pointers();
1231  for (auto n : elem->neighbor_ptr_range())
1232  if (n && n != remote_elem)
1233  n->libmesh_assert_valid_node_pointers();
1234 
1235  libmesh_assert_not_equal_to (elem->parent(), remote_elem);
1236  elem = elem->parent();
1237  }
1238  }
1239 }
1240 
1241 
1243 {
1244  LOG_SCOPE("libmesh_assert_valid_remote_elems()", "MeshTools");
1245 
1246  for (const auto & elem : as_range(mesh.local_elements_begin(),
1248  {
1249  libmesh_assert (elem);
1250 
1251  // We currently don't allow active_local_elements to have
1252  // remote_elem neighbors
1253  if (elem->active())
1254  for (auto n : elem->neighbor_ptr_range())
1255  libmesh_assert_not_equal_to (n, remote_elem);
1256 
1257 #ifdef LIBMESH_ENABLE_AMR
1258  const Elem * parent = elem->parent();
1259  if (parent)
1260  libmesh_assert_not_equal_to (parent, remote_elem);
1261 
1262  // We can only be strict about active elements' subactive
1263  // children
1264  if (elem->active() && elem->has_children())
1265  for (auto & child : elem->child_ref_range())
1266  libmesh_assert_not_equal_to (&child, remote_elem);
1267 #endif
1268  }
1269 }
1270 
1271 
1273  const Elem * bad_elem)
1274 {
1275  for (const auto & elem : mesh.element_ptr_range())
1276  {
1277  libmesh_assert (elem);
1278  libmesh_assert_not_equal_to (elem->parent(), bad_elem);
1279  for (auto n : elem->neighbor_ptr_range())
1280  libmesh_assert_not_equal_to (n, bad_elem);
1281 
1282 #ifdef LIBMESH_ENABLE_AMR
1283  if (elem->has_children())
1284  for (auto & child : elem->child_ref_range())
1285  libmesh_assert_not_equal_to (&child, bad_elem);
1286 #endif
1287  }
1288 }
1289 
1290 
1291 
1293 {
1294  LOG_SCOPE("libmesh_assert_valid_elem_ids()", "MeshTools");
1295 
1296  processor_id_type lastprocid = 0;
1297  dof_id_type lastelemid = 0;
1298 
1299  for (const auto & elem : mesh.active_element_ptr_range())
1300  {
1301  libmesh_assert (elem);
1302  processor_id_type elemprocid = elem->processor_id();
1303  dof_id_type elemid = elem->id();
1304 
1305  libmesh_assert_greater_equal (elemid, lastelemid);
1306  libmesh_assert_greater_equal (elemprocid, lastprocid);
1307 
1308  lastelemid = elemid;
1309  lastprocid = elemprocid;
1310  }
1311 }
1312 
1313 
1314 
1316 {
1317  LOG_SCOPE("libmesh_assert_valid_amr_elem_ids()", "MeshTools");
1318 
1319  for (const auto & elem : mesh.element_ptr_range())
1320  {
1321  libmesh_assert (elem);
1322 
1323  const Elem * parent = elem->parent();
1324 
1325  if (parent)
1326  {
1327  libmesh_assert_greater_equal (elem->id(), parent->id());
1328  libmesh_assert_greater_equal (elem->processor_id(), parent->processor_id());
1329  }
1330  }
1331 }
1332 
1333 
1334 
1336 {
1337  LOG_SCOPE("libmesh_assert_valid_amr_interior_parents()", "MeshTools");
1338 
1339  for (const auto & elem : mesh.element_ptr_range())
1340  {
1341  libmesh_assert (elem);
1342 
1343  // We can skip to the next element if we're full-dimension
1344  // and therefore don't have any interior parents
1345  if (elem->dim() >= LIBMESH_DIM)
1346  continue;
1347 
1348  const Elem * ip = elem->interior_parent();
1349 
1350  const Elem * parent = elem->parent();
1351 
1352  if (ip && (ip != remote_elem) && parent)
1353  {
1354  libmesh_assert_equal_to (ip->top_parent(),
1355  elem->top_parent()->interior_parent());
1356 
1357  if (ip->level() == elem->level())
1358  libmesh_assert_equal_to (ip->parent(),
1359  parent->interior_parent());
1360  else
1361  {
1362  libmesh_assert_less (ip->level(), elem->level());
1363  libmesh_assert_equal_to (ip, parent->interior_parent());
1364  }
1365  }
1366  }
1367 }
1368 
1369 
1370 
1372 {
1373  LOG_SCOPE("libmesh_assert_connected_nodes()", "MeshTools");
1374 
1375  std::set<const Node *> used_nodes;
1376 
1377  for (const auto & elem : mesh.element_ptr_range())
1378  {
1379  libmesh_assert (elem);
1380 
1381  for (auto & n : elem->node_ref_range())
1382  used_nodes.insert(&n);
1383  }
1384 
1385  for (const auto & node : mesh.node_ptr_range())
1386  {
1387  libmesh_assert(node);
1388  libmesh_assert(used_nodes.count(node));
1389  }
1390 }
1391 
1392 
1393 
1394 namespace MeshTools {
1395 
1397 {
1398  LOG_SCOPE("libmesh_assert_valid_boundary_ids()", "MeshTools");
1399 
1400  if (mesh.n_processors() == 1)
1401  return;
1402 
1403  libmesh_parallel_only(mesh.comm());
1404 
1405  const BoundaryInfo & boundary_info = mesh.get_boundary_info();
1406 
1407  dof_id_type pmax_elem_id = mesh.max_elem_id();
1408  mesh.comm().max(pmax_elem_id);
1409 
1410  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1411  {
1412  const Elem * elem = mesh.query_elem_ptr(i);
1413  const unsigned int my_n_nodes = elem ? elem->n_nodes() : 0;
1414  const unsigned int my_n_edges = elem ? elem->n_edges() : 0;
1415  const unsigned int my_n_sides = elem ? elem->n_sides() : 0;
1416  unsigned int
1417  n_nodes = my_n_nodes,
1418  n_edges = my_n_edges,
1419  n_sides = my_n_sides;
1420 
1421  mesh.comm().max(n_nodes);
1422  mesh.comm().max(n_edges);
1423  mesh.comm().max(n_sides);
1424 
1425  if (elem)
1426  {
1427  libmesh_assert_equal_to(my_n_nodes, n_nodes);
1428  libmesh_assert_equal_to(my_n_edges, n_edges);
1429  libmesh_assert_equal_to(my_n_sides, n_sides);
1430  }
1431 
1432  // Let's test all IDs on the element with one communication
1433  // rather than n_nodes + n_edges + n_sides communications, to
1434  // cut down on latency in dbg modes.
1435  std::vector<boundary_id_type> all_bcids;
1436 
1437  for (unsigned int n=0; n != n_nodes; ++n)
1438  {
1439  std::vector<boundary_id_type> bcids;
1440  if (elem)
1441  {
1442  boundary_info.boundary_ids(elem->node_ptr(n), bcids);
1443 
1444  // Ordering of boundary ids shouldn't matter
1445  std::sort(bcids.begin(), bcids.end());
1446  }
1447  // libmesh_assert(mesh.comm().semiverify (elem ? &bcids : nullptr));
1448 
1449  all_bcids.insert(all_bcids.end(), bcids.begin(),
1450  bcids.end());
1451  // Separator
1452  all_bcids.push_back(BoundaryInfo::invalid_id);
1453  }
1454 
1455  for (unsigned short e=0; e != n_edges; ++e)
1456  {
1457  std::vector<boundary_id_type> bcids;
1458 
1459  if (elem)
1460  {
1461  boundary_info.edge_boundary_ids(elem, e, bcids);
1462 
1463  // Ordering of boundary ids shouldn't matter
1464  std::sort(bcids.begin(), bcids.end());
1465  }
1466 
1467  // libmesh_assert(mesh.comm().semiverify (elem ? &bcids : nullptr));
1468 
1469  all_bcids.insert(all_bcids.end(), bcids.begin(),
1470  bcids.end());
1471  // Separator
1472  all_bcids.push_back(BoundaryInfo::invalid_id);
1473 
1474  if (elem)
1475  {
1476  boundary_info.raw_edge_boundary_ids(elem, e, bcids);
1477 
1478  // Ordering of boundary ids shouldn't matter
1479  std::sort(bcids.begin(), bcids.end());
1480 
1481  all_bcids.insert(all_bcids.end(), bcids.begin(),
1482  bcids.end());
1483  // Separator
1484  all_bcids.push_back(BoundaryInfo::invalid_id);
1485  }
1486 
1487  // libmesh_assert(mesh.comm().semiverify (elem ? &bcids : nullptr));
1488  }
1489 
1490  for (unsigned short s=0; s != n_sides; ++s)
1491  {
1492  std::vector<boundary_id_type> bcids;
1493 
1494  if (elem)
1495  {
1496  boundary_info.boundary_ids(elem, s, bcids);
1497 
1498  // Ordering of boundary ids shouldn't matter
1499  std::sort(bcids.begin(), bcids.end());
1500 
1501  all_bcids.insert(all_bcids.end(), bcids.begin(),
1502  bcids.end());
1503  // Separator
1504  all_bcids.push_back(BoundaryInfo::invalid_id);
1505  }
1506 
1507  // libmesh_assert(mesh.comm().semiverify (elem ? &bcids : nullptr));
1508 
1509  if (elem)
1510  {
1511  boundary_info.raw_boundary_ids(elem, s, bcids);
1512 
1513  // Ordering of boundary ids shouldn't matter
1514  std::sort(bcids.begin(), bcids.end());
1515 
1516  all_bcids.insert(all_bcids.end(), bcids.begin(),
1517  bcids.end());
1518  // Separator
1519  all_bcids.push_back(BoundaryInfo::invalid_id);
1520  }
1521 
1522  // libmesh_assert(mesh.comm().semiverify (elem ? &bcids : nullptr));
1523  }
1524 
1525  for (unsigned short sf=0; sf != 2; ++sf)
1526  {
1527  std::vector<boundary_id_type> bcids;
1528 
1529  if (elem)
1530  {
1531  boundary_info.shellface_boundary_ids(elem, sf, bcids);
1532 
1533  // Ordering of boundary ids shouldn't matter
1534  std::sort(bcids.begin(), bcids.end());
1535 
1536  all_bcids.insert(all_bcids.end(), bcids.begin(),
1537  bcids.end());
1538  // Separator
1539  all_bcids.push_back(BoundaryInfo::invalid_id);
1540  }
1541 
1542  // libmesh_assert(mesh.comm().semiverify (elem ? &bcids : nullptr));
1543 
1544  if (elem)
1545  {
1546  boundary_info.raw_shellface_boundary_ids(elem, sf, bcids);
1547 
1548  // Ordering of boundary ids shouldn't matter
1549  std::sort(bcids.begin(), bcids.end());
1550 
1551  all_bcids.insert(all_bcids.end(), bcids.begin(),
1552  bcids.end());
1553  // Separator
1554  all_bcids.push_back(BoundaryInfo::invalid_id);
1555  }
1556 
1557  // libmesh_assert(mesh.comm().semiverify (elem ? &bcids : nullptr));
1558  }
1559 
1560  libmesh_assert(mesh.comm().semiverify
1561  (elem ? &all_bcids : nullptr));
1562  }
1563 }
1564 
1565 
1566 void libmesh_assert_valid_dof_ids(const MeshBase & mesh, unsigned int sysnum)
1567 {
1568  LOG_SCOPE("libmesh_assert_valid_dof_ids()", "MeshTools");
1569 
1570  if (mesh.n_processors() == 1)
1571  return;
1572 
1573  libmesh_parallel_only(mesh.comm());
1574 
1575  dof_id_type pmax_elem_id = mesh.max_elem_id();
1576  mesh.comm().max(pmax_elem_id);
1577 
1578  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1579  assert_semiverify_dofobj(mesh.comm(),
1580  mesh.query_elem_ptr(i),
1581  sysnum);
1582 
1583  dof_id_type pmax_node_id = mesh.max_node_id();
1584  mesh.comm().max(pmax_node_id);
1585 
1586  for (dof_id_type i=0; i != pmax_node_id; ++i)
1587  assert_semiverify_dofobj(mesh.comm(),
1588  mesh.query_node_ptr(i),
1589  sysnum);
1590 }
1591 
1592 
1593 void libmesh_assert_contiguous_dof_ids(const MeshBase & mesh, unsigned int sysnum)
1594 {
1595  LOG_SCOPE("libmesh_assert_contiguous_dof_ids()", "MeshTools");
1596 
1597  if (mesh.n_processors() == 1)
1598  return;
1599 
1600  libmesh_parallel_only(mesh.comm());
1601 
1602  dof_id_type min_dof_id = std::numeric_limits<dof_id_type>::max(),
1603  max_dof_id = std::numeric_limits<dof_id_type>::min();
1604 
1605  // Figure out what our local dof id range is
1606  for (const auto * node : mesh.local_node_ptr_range())
1607  {
1608  for (auto v : IntRange<unsigned int>(0, node->n_vars(sysnum)))
1609  for (auto c : IntRange<unsigned int>(0, node->n_comp(sysnum, v)))
1610  {
1611  dof_id_type id = node->dof_number(sysnum, v, c);
1612  min_dof_id = std::min (min_dof_id, id);
1613  max_dof_id = std::max (max_dof_id, id);
1614  }
1615  }
1616 
1617  // Make sure no other processors' ids are inside it
1618  for (const auto * node : mesh.node_ptr_range())
1619  {
1620  if (node->processor_id() == mesh.processor_id())
1621  continue;
1622  for (auto v : IntRange<unsigned int>(0, node->n_vars(sysnum)))
1623  for (auto c : IntRange<unsigned int>(0, node->n_comp(sysnum, v)))
1624  {
1625  dof_id_type id = node->dof_number(sysnum, v, c);
1626  libmesh_assert (id < min_dof_id ||
1627  id > max_dof_id);
1628  }
1629  }
1630 }
1631 
1632 
1633 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1635 {
1636  LOG_SCOPE("libmesh_assert_valid_unique_ids()", "MeshTools");
1637 
1638  libmesh_parallel_only(mesh.comm());
1639 
1640  dof_id_type pmax_elem_id = mesh.max_elem_id();
1641  mesh.comm().max(pmax_elem_id);
1642 
1643  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1644  {
1645  const Elem * elem = mesh.query_elem_ptr(i);
1646  const unique_id_type unique_id = elem ? elem->unique_id() : 0;
1647  const unique_id_type * uid_ptr = elem ? &unique_id : nullptr;
1648  libmesh_assert(mesh.comm().semiverify(uid_ptr));
1649  }
1650 
1651  dof_id_type pmax_node_id = mesh.max_node_id();
1652  mesh.comm().max(pmax_node_id);
1653 
1654  for (dof_id_type i=0; i != pmax_node_id; ++i)
1655  {
1656  const Node * node = mesh.query_node_ptr(i);
1657  const unique_id_type unique_id = node ? node->unique_id() : 0;
1658  const unique_id_type * uid_ptr = node ? &unique_id : nullptr;
1659  libmesh_assert(mesh.comm().semiverify(uid_ptr));
1660  }
1661 }
1662 #endif
1663 
1665 {
1666  libmesh_parallel_only(mesh.comm());
1667 
1668  dof_id_type parallel_max_elem_id = mesh.max_elem_id();
1669  mesh.comm().max(parallel_max_elem_id);
1670 
1671  for (dof_id_type i=0; i != parallel_max_elem_id; ++i)
1672  {
1673  const Elem * elem = mesh.query_elem_ptr(i);
1674  processor_id_type pid =
1676  mesh.comm().min(pid);
1677  libmesh_assert(elem || pid != mesh.processor_id());
1678  }
1679 
1680  dof_id_type parallel_max_node_id = mesh.max_node_id();
1681  mesh.comm().max(parallel_max_node_id);
1682 
1683  for (dof_id_type i=0; i != parallel_max_node_id; ++i)
1684  {
1685  const Node * node = mesh.query_node_ptr(i);
1686  processor_id_type pid =
1688  mesh.comm().min(pid);
1689  libmesh_assert(node || pid != mesh.processor_id());
1690  }
1691 }
1692 
1693 
1695 {
1696  libmesh_parallel_only(mesh.comm());
1697  auto locator = mesh.sub_point_locator();
1698 
1699  dof_id_type parallel_max_elem_id = mesh.max_elem_id();
1700  mesh.comm().max(parallel_max_elem_id);
1701 
1702  for (dof_id_type i=0; i != parallel_max_elem_id; ++i)
1703  {
1704  const Elem * elem = mesh.query_elem_ptr(i);
1705 
1706  const unsigned int my_n_nodes = elem ? elem->n_nodes() : 0;
1707  unsigned int n_nodes = my_n_nodes;
1708  mesh.comm().max(n_nodes);
1709 
1710  if (n_nodes)
1711  libmesh_assert(mesh.comm().semiverify(elem ? &my_n_nodes : nullptr));
1712 
1713  for (unsigned int n=0; n != n_nodes; ++n)
1714  {
1715  const Node * node = elem ? elem->node_ptr(n) : nullptr;
1716  processor_id_type pid =
1718  mesh.comm().min(pid);
1719  libmesh_assert(node || pid != mesh.processor_id());
1720  }
1721  }
1722 }
1723 
1724 
1725 template <>
1727 {
1728  LOG_SCOPE("libmesh_assert_topology_consistent_procids()", "MeshTools");
1729 
1730  // This parameter is not used when !LIBMESH_ENABLE_AMR
1732 
1733  // If we're adaptively refining, check processor ids for consistency
1734  // between parents and children.
1735 #ifdef LIBMESH_ENABLE_AMR
1736 
1737  // Ancestor elements we won't worry about, but subactive and active
1738  // elements ought to have parents with consistent processor ids
1739  for (const auto & elem : mesh.element_ptr_range())
1740  {
1741  libmesh_assert(elem);
1742 
1743  if (!elem->active() && !elem->subactive())
1744  continue;
1745 
1746  const Elem * parent = elem->parent();
1747 
1748  if (parent)
1749  {
1750  libmesh_assert(parent->has_children());
1751  processor_id_type parent_procid = parent->processor_id();
1752  bool matching_child_id = false;
1753  // If we've got a remote_elem then we don't know whether
1754  // it's responsible for the parent's processor id; all
1755  // we can do is assume it is and let its processor fail
1756  // an assert if there's something wrong.
1757  for (auto & child : parent->child_ref_range())
1758  if (&child == remote_elem ||
1759  child.processor_id() == parent_procid)
1760  matching_child_id = true;
1761  libmesh_assert(matching_child_id);
1762  }
1763  }
1764 #endif
1765 }
1766 
1767 
1768 
1769 template <>
1771 {
1772  LOG_SCOPE("libmesh_assert_parallel_consistent_procids()", "MeshTools");
1773 
1774  if (mesh.n_processors() == 1)
1775  return;
1776 
1777  libmesh_parallel_only(mesh.comm());
1778 
1779  // Some code (looking at you, stitch_meshes) modifies DofObject ids
1780  // without keeping max_elem_id()/max_node_id() consistent, but
1781  // that's done in a safe way for performance reasons, so we'll play
1782  // along and just figure out new max ids ourselves.
1783  dof_id_type parallel_max_elem_id = 0;
1784  for (const auto & elem : mesh.element_ptr_range())
1785  parallel_max_elem_id = std::max<dof_id_type>(parallel_max_elem_id,
1786  elem->id()+1);
1787  mesh.comm().max(parallel_max_elem_id);
1788 
1789  // Check processor ids for consistency between processors
1790 
1791  for (dof_id_type i=0; i != parallel_max_elem_id; ++i)
1792  {
1793  const Elem * elem = mesh.query_elem_ptr(i);
1794 
1795  processor_id_type min_id =
1796  elem ? elem->processor_id() :
1797  std::numeric_limits<processor_id_type>::max();
1798  mesh.comm().min(min_id);
1799 
1800  processor_id_type max_id =
1801  elem ? elem->processor_id() :
1802  std::numeric_limits<processor_id_type>::min();
1803  mesh.comm().max(max_id);
1804 
1805  if (elem)
1806  {
1807  libmesh_assert_equal_to (min_id, elem->processor_id());
1808  libmesh_assert_equal_to (max_id, elem->processor_id());
1809  }
1810 
1811  if (min_id == mesh.processor_id())
1812  libmesh_assert(elem);
1813  }
1814 }
1815 
1816 
1817 
1818 template <>
1820 {
1821  LOG_SCOPE("libmesh_assert_topology_consistent_procids()", "MeshTools");
1822 
1823  if (mesh.n_processors() == 1)
1824  return;
1825 
1826  libmesh_parallel_only(mesh.comm());
1827 
1828  // We want this test to be valid even when called even after nodes
1829  // have been added asynchronously but before they're renumbered.
1830  //
1831  // Plus, some code (looking at you, stitch_meshes) modifies
1832  // DofObject ids without keeping max_elem_id()/max_node_id()
1833  // consistent, but that's done in a safe way for performance
1834  // reasons, so we'll play along and just figure out new max ids
1835  // ourselves.
1836  dof_id_type parallel_max_node_id = 0;
1837  for (const auto & node : mesh.node_ptr_range())
1838  parallel_max_node_id = std::max<dof_id_type>(parallel_max_node_id,
1839  node->id()+1);
1840  mesh.comm().max(parallel_max_node_id);
1841 
1842 
1843  std::vector<bool> node_touched_by_me(parallel_max_node_id, false);
1844 
1845  for (const auto & elem : as_range(mesh.local_elements_begin(),
1847  {
1848  libmesh_assert (elem);
1849 
1850  for (auto & node : elem->node_ref_range())
1851  {
1852  dof_id_type nodeid = node.id();
1853  node_touched_by_me[nodeid] = true;
1854  }
1855  }
1856  std::vector<bool> node_touched_by_anyone(node_touched_by_me);
1857  mesh.comm().max(node_touched_by_anyone);
1858 
1859  for (const auto & node : mesh.local_node_ptr_range())
1860  {
1861  libmesh_assert(node);
1862  dof_id_type nodeid = node->id();
1863  libmesh_assert(!node_touched_by_anyone[nodeid] ||
1864  node_touched_by_me[nodeid]);
1865  }
1866 }
1867 
1868 
1869 
1871 {
1872  LOG_SCOPE("libmesh_assert_parallel_consistent_new_node_procids()", "MeshTools");
1873 
1874  if (mesh.n_processors() == 1)
1875  return;
1876 
1877  libmesh_parallel_only(mesh.comm());
1878 
1879  // We want this test to hit every node when called even after nodes
1880  // have been added asynchronously but before everything has been
1881  // renumbered.
1882  dof_id_type parallel_max_elem_id = mesh.max_elem_id();
1883  mesh.comm().max(parallel_max_elem_id);
1884 
1885  std::vector<bool> elem_touched_by_anyone(parallel_max_elem_id, false);
1886 
1887  for (dof_id_type i=0; i != parallel_max_elem_id; ++i)
1888  {
1889  const Elem * elem = mesh.query_elem_ptr(i);
1890 
1891  const unsigned int my_n_nodes = elem ? elem->n_nodes() : 0;
1892  unsigned int n_nodes = my_n_nodes;
1893  mesh.comm().max(n_nodes);
1894 
1895  if (n_nodes)
1896  libmesh_assert(mesh.comm().semiverify(elem ? &my_n_nodes : nullptr));
1897 
1898  for (unsigned int n=0; n != n_nodes; ++n)
1899  {
1900  const Node * node = elem ? elem->node_ptr(n) : nullptr;
1901  const processor_id_type pid = node ? node->processor_id() : 0;
1902  libmesh_assert(mesh.comm().semiverify (node ? &pid : nullptr));
1903  }
1904  }
1905 }
1906 
1907 template <>
1909 {
1910  LOG_SCOPE("libmesh_assert_parallel_consistent_procids()", "MeshTools");
1911 
1912  if (mesh.n_processors() == 1)
1913  return;
1914 
1915  libmesh_parallel_only(mesh.comm());
1916 
1917  // We want this test to be valid even when called even after nodes
1918  // have been added asynchronously but before they're renumbered
1919  //
1920  // Plus, some code (looking at you, stitch_meshes) modifies
1921  // DofObject ids without keeping max_elem_id()/max_node_id()
1922  // consistent, but that's done in a safe way for performance
1923  // reasons, so we'll play along and just figure out new max ids
1924  // ourselves.
1925  dof_id_type parallel_max_node_id = 0;
1926  for (const auto & node : mesh.node_ptr_range())
1927  parallel_max_node_id = std::max<dof_id_type>(parallel_max_node_id,
1928  node->id()+1);
1929  mesh.comm().max(parallel_max_node_id);
1930 
1931  std::vector<bool> node_touched_by_anyone(parallel_max_node_id, false);
1932 
1933  for (const auto & elem : as_range(mesh.local_elements_begin(),
1935  {
1936  libmesh_assert (elem);
1937 
1938  for (auto & node : elem->node_ref_range())
1939  {
1940  dof_id_type nodeid = node.id();
1941  node_touched_by_anyone[nodeid] = true;
1942  }
1943  }
1944  mesh.comm().max(node_touched_by_anyone);
1945 
1946  // Check processor ids for consistency between processors
1947  // on any node an element touches
1948  for (dof_id_type i=0; i != parallel_max_node_id; ++i)
1949  {
1950  if (!node_touched_by_anyone[i])
1951  continue;
1952 
1953  const Node * node = mesh.query_node_ptr(i);
1954  const processor_id_type pid = node ? node->processor_id() : 0;
1955 
1956  libmesh_assert(mesh.comm().semiverify (node ? &pid : nullptr));
1957  }
1958 }
1959 
1960 
1962 {
1963  for (const auto & elem : mesh.active_element_ptr_range())
1964  for (auto & node : elem->node_ref_range())
1965  libmesh_assert_equal_to
1966  (node.processor_id(),
1967  node.choose_processor_id(node.processor_id(),
1968  elem->processor_id()));
1969 }
1970 
1971 
1972 
1973 } // namespace MeshTools
1974 
1975 
1976 
1977 #ifdef LIBMESH_ENABLE_AMR
1979 {
1980  LOG_SCOPE("libmesh_assert_valid_refinement_flags()", "MeshTools");
1981 
1982  libmesh_parallel_only(mesh.comm());
1983  if (mesh.n_processors() == 1)
1984  return;
1985 
1986  dof_id_type pmax_elem_id = mesh.max_elem_id();
1987  mesh.comm().max(pmax_elem_id);
1988 
1989  std::vector<unsigned char> my_elem_h_state(pmax_elem_id, 255);
1990  std::vector<unsigned char> my_elem_p_state(pmax_elem_id, 255);
1991 
1992  for (const auto & elem : mesh.element_ptr_range())
1993  {
1994  libmesh_assert (elem);
1995  dof_id_type elemid = elem->id();
1996 
1997  my_elem_h_state[elemid] =
1998  static_cast<unsigned char>(elem->refinement_flag());
1999 
2000  my_elem_p_state[elemid] =
2001  static_cast<unsigned char>(elem->p_refinement_flag());
2002  }
2003  std::vector<unsigned char> min_elem_h_state(my_elem_h_state);
2004  mesh.comm().min(min_elem_h_state);
2005 
2006  std::vector<unsigned char> min_elem_p_state(my_elem_p_state);
2007  mesh.comm().min(min_elem_p_state);
2008 
2009  for (dof_id_type i=0; i!= pmax_elem_id; ++i)
2010  {
2011  libmesh_assert(my_elem_h_state[i] == 255 ||
2012  my_elem_h_state[i] == min_elem_h_state[i]);
2013  libmesh_assert(my_elem_p_state[i] == 255 ||
2014  my_elem_p_state[i] == min_elem_p_state[i]);
2015  }
2016 }
2017 #else
2019 {
2020 }
2021 #endif // LIBMESH_ENABLE_AMR
2022 
2023 
2024 
2025 #ifdef LIBMESH_ENABLE_AMR
2027 {
2028  LOG_SCOPE("libmesh_assert_valid_refinement_tree()", "MeshTools");
2029 
2030  for (const auto & elem : mesh.element_ptr_range())
2031  {
2032  libmesh_assert(elem);
2033  if (elem->has_children())
2034  for (auto & child : elem->child_ref_range())
2035  if (&child != remote_elem)
2036  libmesh_assert_equal_to (child.parent(), elem);
2037  if (elem->active())
2038  {
2039  libmesh_assert(!elem->ancestor());
2040  libmesh_assert(!elem->subactive());
2041  }
2042  else if (elem->ancestor())
2043  {
2044  libmesh_assert(!elem->subactive());
2045  }
2046  else
2047  libmesh_assert(elem->subactive());
2048 
2049  if (elem->p_refinement_flag() == Elem::JUST_REFINED)
2050  libmesh_assert_greater(elem->p_level(), 0);
2051  }
2052 }
2053 #else
2055 {
2056 }
2057 #endif // LIBMESH_ENABLE_AMR
2058 
2059 
2060 
2062  bool assert_valid_remote_elems)
2063 {
2064  LOG_SCOPE("libmesh_assert_valid_neighbors()", "MeshTools");
2065 
2066  for (const auto & elem : mesh.element_ptr_range())
2067  {
2068  libmesh_assert (elem);
2069  elem->libmesh_assert_valid_neighbors();
2070  }
2071 
2072  if (mesh.n_processors() == 1)
2073  return;
2074 
2075  libmesh_parallel_only(mesh.comm());
2076 
2077  dof_id_type pmax_elem_id = mesh.max_elem_id();
2078  mesh.comm().max(pmax_elem_id);
2079 
2080  for (dof_id_type i=0; i != pmax_elem_id; ++i)
2081  {
2082  const Elem * elem = mesh.query_elem_ptr(i);
2083 
2084  const unsigned int my_n_neigh = elem ? elem->n_neighbors() : 0;
2085  unsigned int n_neigh = my_n_neigh;
2086  mesh.comm().max(n_neigh);
2087  if (elem)
2088  libmesh_assert_equal_to (my_n_neigh, n_neigh);
2089 
2090  for (unsigned int n = 0; n != n_neigh; ++n)
2091  {
2092  dof_id_type my_neighbor = DofObject::invalid_id;
2093  dof_id_type * p_my_neighbor = nullptr;
2094 
2095  // If we have a non-remote_elem neighbor link, then we can
2096  // verify it.
2097  if (elem && elem->neighbor_ptr(n) != remote_elem)
2098  {
2099  p_my_neighbor = &my_neighbor;
2100  if (elem->neighbor_ptr(n))
2101  my_neighbor = elem->neighbor_ptr(n)->id();
2102 
2103  // But wait - if we haven't set remote_elem links yet then
2104  // some nullptr links on ghost elements might be
2105  // future-remote_elem links, so we can't verify those.
2106  if (!assert_valid_remote_elems &&
2107  !elem->neighbor_ptr(n) &&
2108  elem->processor_id() != mesh.processor_id())
2109  p_my_neighbor = nullptr;
2110  }
2111  libmesh_assert(mesh.comm().semiverify(p_my_neighbor));
2112  }
2113  }
2114 }
2115 
2116 
2117 
2118 #endif // DEBUG
2119 
2120 
2121 
2122 // Functors for correct_node_proc_ids
2123 namespace {
2124 
2125 typedef std::unordered_map<dof_id_type, processor_id_type> proc_id_map_type;
2126 
2127 struct SyncNodeSet
2128 {
2129  typedef unsigned char datum; // bool but without bit twiddling issues
2130 
2131  SyncNodeSet(std::unordered_set<const Node *> & _set,
2132  MeshBase & _mesh) :
2133  node_set(_set), mesh(_mesh) {}
2134 
2135  std::unordered_set<const Node *> & node_set;
2136 
2138 
2139  // ------------------------------------------------------------
2140  void gather_data (const std::vector<dof_id_type> & ids,
2141  std::vector<datum> & data)
2142  {
2143  // Find whether each requested node belongs in the set
2144  data.resize(ids.size());
2145 
2146  for (auto i : index_range(ids))
2147  {
2148  const dof_id_type id = ids[i];
2149 
2150  // We'd better have every node we're asked for
2151  Node * node = mesh.node_ptr(id);
2152 
2153  // Return if the node is in the set.
2154  data[i] = (node_set.find(node) != node_set.end());
2155  }
2156  }
2157 
2158  // ------------------------------------------------------------
2159  bool act_on_data (const std::vector<dof_id_type> & ids,
2160  const std::vector<datum> in_set)
2161  {
2162  bool data_changed = false;
2163 
2164  // Add nodes we've been informed of to our own set
2165  for (auto i : index_range(ids))
2166  {
2167  if (in_set[i])
2168  {
2169  Node * node = mesh.node_ptr(ids[i]);
2170  if (!node_set.count(node))
2171  {
2172  node_set.insert(node);
2173  data_changed = true;
2174  }
2175  }
2176  }
2177 
2178  return data_changed;
2179  }
2180 };
2181 
2182 
2183 struct NodesNotInSet
2184 {
2185  NodesNotInSet(const std::unordered_set<const Node *> _set)
2186  : node_set(_set) {}
2187 
2188  bool operator() (const Node * node) const
2189  {
2190  if (node_set.count(node))
2191  return false;
2192  return true;
2193  }
2194 
2195  const std::unordered_set<const Node *> node_set;
2196 };
2197 
2198 
2199 struct SyncProcIdsFromMap
2200 {
2201  typedef processor_id_type datum;
2202 
2203  SyncProcIdsFromMap(const proc_id_map_type & _map,
2204  MeshBase & _mesh) :
2205  new_proc_ids(_map), mesh(_mesh) {}
2206 
2207  const proc_id_map_type & new_proc_ids;
2208 
2209  MeshBase & mesh;
2210 
2211  // ------------------------------------------------------------
2212  void gather_data (const std::vector<dof_id_type> & ids,
2213  std::vector<datum> & data)
2214  {
2215  // Find the new processor id of each requested node
2216  data.resize(ids.size());
2217 
2218  for (auto i : index_range(ids))
2219  {
2220  const dof_id_type id = ids[i];
2221  const proc_id_map_type::const_iterator it = new_proc_ids.find(id);
2222 
2223  // Return the node's new processor id if it has one, or its
2224  // old processor id if not.
2225  if (it != new_proc_ids.end())
2226  data[i] = it->second;
2227  else
2228  {
2229  // We'd better find every node we're asked for
2230  const Node & node = mesh.node_ref(id);
2231  data[i] = node.processor_id();
2232  }
2233  }
2234  }
2235 
2236  // ------------------------------------------------------------
2237  void act_on_data (const std::vector<dof_id_type> & ids,
2238  const std::vector<datum> proc_ids)
2239  {
2240  // Set the node processor ids we've now been informed of
2241  for (auto i : index_range(ids))
2242  {
2243  Node & node = mesh.node_ref(ids[i]);
2244  node.processor_id() = proc_ids[i];
2245  }
2246  }
2247 };
2248 }
2249 
2250 
2251 
2253 {
2254  LOG_SCOPE("correct_node_proc_ids()","MeshTools");
2255 
2256  // This function must be run on all processors at once
2257  libmesh_parallel_only(mesh.comm());
2258 
2259  // We require all processors to agree on nodal processor ids before
2260  // going into this algorithm.
2261 #ifdef DEBUG
2263 #endif
2264 
2265  // If we have any unpartitioned elements at this
2266  // stage there is a problem
2269 
2270  // Fix nodes' processor ids. Coarsening may have left us with nodes
2271  // which are no longer touched by any elements of the same processor
2272  // id, and for DofMap to work we need to fix that.
2273 
2274  // This is harder now that libMesh no longer requires a distributed
2275  // mesh to ghost all nodal neighbors: it is possible for two active
2276  // elements on two different processors to share the same node in
2277  // such a way that neither processor knows the others' element
2278  // exists!
2279 
2280  // While we're at it, if this mesh is configured to allow
2281  // repartitioning, we'll repartition *all* the nodes' processor ids
2282  // using the canonical Node heuristic, to try and improve DoF load
2283  // balancing. But if the mesh is disallowing repartitioning, we
2284  // won't touch processor_id on any node where it's valid, regardless
2285  // of whether or not it's canonical.
2286  bool repartition_all_nodes = !mesh.skip_noncritical_partitioning();
2287  std::unordered_set<const Node *> valid_nodes;
2288 
2289  // If we aren't allowed to repartition, then we're going to leave
2290  // every node we can at its current processor_id, and *only*
2291  // repartition the nodes whose current processor id is incompatible
2292  // with DoFMap (because it doesn't touch an active element, e.g. due
2293  // to coarsening)
2294  if (!repartition_all_nodes)
2295  {
2296  for (const auto & elem : mesh.active_element_ptr_range())
2297  for (const auto & node : elem->node_ref_range())
2298  if (elem->processor_id() == node.processor_id())
2299  valid_nodes.insert(&node);
2300 
2301  SyncNodeSet syncv(valid_nodes, mesh);
2302 
2304  (mesh.comm(), mesh.nodes_begin(), mesh.nodes_end(), syncv);
2305  }
2306 
2307  // We build up a set of compatible processor ids for each node
2308  proc_id_map_type new_proc_ids;
2309 
2310  for (auto & elem : mesh.active_element_ptr_range())
2311  {
2312  processor_id_type pid = elem->processor_id();
2313 
2314  for (auto & node : elem->node_ref_range())
2315  {
2316  const dof_id_type id = node.id();
2317  const proc_id_map_type::iterator it = new_proc_ids.find(id);
2318  if (it == new_proc_ids.end())
2319  new_proc_ids.insert(std::make_pair(id,pid));
2320  else
2321  it->second = node.choose_processor_id(it->second, pid);
2322  }
2323  }
2324 
2325  // Sort the new pids to push to each processor
2326  std::map<processor_id_type, std::vector<std::pair<dof_id_type, processor_id_type>>>
2327  ids_to_push;
2328 
2329  for (const auto & node : mesh.node_ptr_range())
2330  {
2331  const dof_id_type id = node->id();
2332  const proc_id_map_type::iterator it = new_proc_ids.find(id);
2333  if (it == new_proc_ids.end())
2334  continue;
2335  const processor_id_type pid = it->second;
2336  if (node->processor_id() != DofObject::invalid_processor_id)
2337  ids_to_push[node->processor_id()].push_back(std::make_pair(id, pid));
2338  }
2339 
2340  auto action_functor =
2341  [& mesh, & new_proc_ids]
2343  const std::vector<std::pair<dof_id_type, processor_id_type>> & data)
2344  {
2345  for (auto & p : data)
2346  {
2347  const dof_id_type id = p.first;
2348  const processor_id_type pid = p.second;
2349  const proc_id_map_type::iterator it = new_proc_ids.find(id);
2350  if (it == new_proc_ids.end())
2351  new_proc_ids.insert(std::make_pair(id,pid));
2352  else
2353  {
2354  const Node & node = mesh.node_ref(id);
2355  it->second = node.choose_processor_id(it->second, pid);
2356  }
2357  }
2358  };
2359 
2360  Parallel::push_parallel_vector_data
2361  (mesh.comm(), ids_to_push, action_functor);
2362 
2363  // Now new_proc_ids is correct for every node we used to own. Let's
2364  // ask every other processor about the nodes they used to own. But
2365  // first we'll need to keep track of which nodes we used to own,
2366  // lest we get them confused with nodes we newly own.
2367  std::unordered_set<Node *> ex_local_nodes;
2368  for (auto & node : mesh.local_node_ptr_range())
2369  {
2370  const proc_id_map_type::iterator it = new_proc_ids.find(node->id());
2371  if (it != new_proc_ids.end() && it->second != mesh.processor_id())
2372  ex_local_nodes.insert(node);
2373  }
2374 
2375  SyncProcIdsFromMap sync(new_proc_ids, mesh);
2376  if (repartition_all_nodes)
2378  (mesh.comm(), mesh.nodes_begin(), mesh.nodes_end(), sync);
2379  else
2380  {
2381  NodesNotInSet nnis(valid_nodes);
2382 
2384  (mesh.comm(), mesh.nodes_begin(), mesh.nodes_end(), nnis, sync);
2385  }
2386 
2387  // And finally let's update the nodes we used to own.
2388  for (const auto & node : ex_local_nodes)
2389  {
2390  if (valid_nodes.count(node))
2391  continue;
2392 
2393  const dof_id_type id = node->id();
2394  const proc_id_map_type::iterator it = new_proc_ids.find(id);
2395  libmesh_assert(it != new_proc_ids.end());
2396  node->processor_id() = it->second;
2397  }
2398 
2399  // We should still have consistent nodal processor ids coming out of
2400  // this algorithm, but if we're allowed to repartition the mesh then
2401  // they should be canonically correct too.
2402 #ifdef DEBUG
2403  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
2404  //if (repartition_all_nodes)
2405  // MeshTools::libmesh_assert_canonical_node_procids(mesh);
2406 #endif
2407 }
2408 
2409 
2410 
2412 {
2414 }
2415 
2416 } // namespace libMesh
libMesh::MeshBase::pid_elements_begin
virtual element_iterator pid_elements_begin(processor_id_type proc_id)=0
Iterate over all elements with a specified processor id.
libMesh::MeshBase::active_local_subdomain_elements_end
virtual element_iterator active_local_subdomain_elements_end(subdomain_id_type subdomain_id)=0
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::BoundaryInfo
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
Definition: boundary_info.h:57
libMesh::Elem::is_node_on_side
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
libMesh::Elem::n_edges
virtual unsigned int n_edges() const =0
libMesh::invalid_uint
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value.
Definition: libmesh.h:249
libMesh::MeshTools::n_local_levels
unsigned int n_local_levels(const MeshBase &mesh)
Definition: mesh_tools.C:643
libMesh::MeshTools::paranoid_n_levels
unsigned int paranoid_n_levels(const MeshBase &mesh)
Definition: mesh_tools.C:680
libMesh::DofObject::n_systems
unsigned int n_systems() const
Definition: dof_object.h:861
libMesh::MeshTools::n_elem
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).
Definition: mesh_tools.C:705
libMesh::Elem::JUST_REFINED
Definition: elem.h:1172
libMesh::unique_id_type
uint8_t unique_id_type
Definition: id_types.h:86
libMesh::MeshBase::get_boundary_info
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:132
libMesh::MeshTools::libmesh_assert_valid_boundary_ids
void libmesh_assert_valid_boundary_ids(const MeshBase &mesh)
A function for verifying that boundary condition ids match across processors.
Definition: mesh_tools.C:1396
n_vars
unsigned int n_vars
Definition: adaptivity_ex3.C:116
libMesh::MeshBase::is_serial
virtual bool is_serial() const
Definition: mesh_base.h:159
libMesh::Elem::level
unsigned int level() const
Definition: elem.h:2478
libMesh::MeshTools::total_weight
dof_id_type total_weight(const MeshBase &mesh)
Definition: mesh_tools.C:213
libMesh::Elem::child_ref_range
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
Definition: elem.h:1839
libMesh::Elem::n_nodes
virtual unsigned int n_nodes() const =0
libMesh::EDGE4
Definition: enum_elem_type.h:37
libMesh::MeshBase::active_local_element_ptr_range
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
libMesh::Elem::n_neighbors
unsigned int n_neighbors() const
Definition: elem.h:631
libMesh::MeshBase::pid_elements_end
virtual element_iterator pid_elements_end(processor_id_type proc_id)=0
libMesh::BoundingBox
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
libMesh::MeshTools::bounding_sphere
Sphere bounding_sphere(const MeshBase &mesh)
Definition: mesh_tools.C:441
libMesh::MeshBase::local_nodes_begin
virtual node_iterator local_nodes_begin()=0
Iterate over local nodes (nodes whose processor_id() matches the current processor).
mesh
MeshBase & mesh
Definition: mesh_tools.C:2137
libMesh::MeshBase::active_element_ptr_range
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
libMesh::MeshTools::libmesh_assert_valid_amr_elem_ids
void libmesh_assert_valid_amr_elem_ids(const MeshBase &mesh)
A function for verifying that ids of elements are correctly sorted for AMR (parents have lower ids th...
Definition: mesh_tools.C:1315
libMesh::MeshBase::n_elem
virtual dof_id_type n_elem() const =0
libMesh::MeshTools::create_nodal_bounding_box
libMesh::BoundingBox create_nodal_bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:414
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh::MeshBase::max_elem_id
virtual dof_id_type max_elem_id() const =0
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::MeshTools::create_subdomain_bounding_box
libMesh::BoundingBox create_subdomain_bounding_box(const MeshBase &mesh, const subdomain_id_type sid)
The same functionality as the deprecated MeshTools::subdomain_bounding_box().
Definition: mesh_tools.C:532
libMesh::MeshTools::libmesh_assert_valid_neighbors
void libmesh_assert_valid_neighbors(const MeshBase &mesh, bool assert_valid_remote_elems=true)
A function for verifying that neighbor connectivity is correct (each element is a neighbor of or desc...
Definition: mesh_tools.C:2061
libMesh::MeshTools::libmesh_assert_parallel_consistent_new_node_procids
void libmesh_assert_parallel_consistent_new_node_procids(const MeshBase &mesh)
A function for verifying that processor assignment is parallel consistent (every processor agrees on ...
Definition: mesh_tools.C:1870
libMesh::MeshTools::bounding_box
BoundingBox bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:376
libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Elem >
void libmesh_assert_topology_consistent_procids< Elem >(const MeshBase &mesh)
Definition: mesh_tools.C:1726
libMesh::MeshBase::type_elements_end
virtual element_iterator type_elements_end(ElemType type)=0
end
IterBase * end
Also have a polymorphic pointer to the end object, this prevents iterating past the end.
Definition: variant_filter_iterator.h:343
libMesh::ParallelObject::comm
const Parallel::Communicator & comm() const
Definition: parallel_object.h:94
libMesh::Threads::split
Dummy "splitting object" used to distinguish splitting constructors from copy constructors.
Definition: threads_none.h:63
libMesh::MeshTools::create_local_bounding_box
libMesh::BoundingBox create_local_bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:454
libMesh::MeshBase::node_ptr
virtual const Node * node_ptr(const dof_id_type i) const =0
libMesh::MeshTools::build_nodes_to_elem_map
void build_nodes_to_elem_map(const MeshBase &mesh, std::vector< std::vector< dof_id_type >> &nodes_to_elem_map)
After calling this function the input vector nodes_to_elem_map will contain the node to element conne...
Definition: mesh_tools.C:248
libMesh::MeshBase::max_node_id
virtual dof_id_type max_node_id() const =0
libMesh::MeshTools::processor_bounding_sphere
Sphere processor_bounding_sphere(const MeshBase &mesh, const processor_id_type pid)
Definition: mesh_tools.C:505
libMesh::MeshTools::find_block_boundary_nodes
std::unordered_set< dof_id_type > find_block_boundary_nodes(const MeshBase &mesh)
Returns a std::set containing Node IDs for all of the block boundary nodes.
Definition: mesh_tools.C:354
libMesh::MeshTools::libmesh_assert_valid_elem_ids
void libmesh_assert_valid_elem_ids(const MeshBase &mesh)
A function for verifying that ids and processor assignment of elements are correctly sorted (monotone...
Definition: mesh_tools.C:1292
libMesh::MeshTools::libmesh_assert_valid_node_pointers
void libmesh_assert_valid_node_pointers(const MeshBase &mesh)
A function for walking across the mesh to try and ferret out invalidated or misassigned pointers.
Definition: mesh_tools.C:1218
libMesh::DofObject::processor_id
processor_id_type processor_id() const
Definition: dof_object.h:829
libMesh::MeshBase::elements_begin
virtual element_iterator elements_begin()=0
Iterate over all the elements in the Mesh.
libMesh::MeshBase::pid_nodes_begin
virtual node_iterator pid_nodes_begin(processor_id_type proc_id)=0
Iterate over nodes with processor_id() == proc_id.
libMesh::MeshBase::type_elements_begin
virtual element_iterator type_elements_begin(ElemType type)=0
Iterate over all elements with a specified geometric type.
libMesh::MeshTools::n_levels
unsigned int n_levels(const MeshBase &mesh)
Definition: mesh_tools.C:656
libMesh::MeshBase::local_elements_begin
virtual element_iterator local_elements_begin()=0
libMesh::MeshTools::libmesh_assert_connected_nodes
void libmesh_assert_connected_nodes(const MeshBase &mesh)
A function for verifying that all nodes are connected to at least one element.
Definition: mesh_tools.C:1371
libMesh::DofObject
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
Definition: dof_object.h:53
libMesh::MeshBase::query_elem_ptr
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
libMesh::MeshTools::processor_bounding_box
BoundingBox processor_bounding_box(const MeshBase &mesh, const processor_id_type pid)
Definition: mesh_tools.C:469
libMesh::MeshTools::libmesh_assert_consistent_distributed_nodes
void libmesh_assert_consistent_distributed_nodes(const MeshBase &mesh)
A function for verifying that distribution of nodes is parallel consistent (every processor can see e...
Definition: mesh_tools.C:1694
libMesh::Sphere
This class defines a sphere.
Definition: sphere.h:72
libMesh::MeshBase::element_ptr_range
virtual SimpleRange< element_iterator > element_ptr_range()=0
libMesh::DofObject::dof_number
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:956
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::IntRange
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition: int_range.h:53
libMesh::MeshTools::create_bounding_box
libMesh::BoundingBox create_bounding_box(const MeshBase &mesh)
The same functionality as the deprecated MeshTools::bounding_box().
Definition: mesh_tools.C:389
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::MeshTools::get_not_subactive_node_ids
void get_not_subactive_node_ids(const MeshBase &mesh, std::set< dof_id_type > &not_subactive_node_ids)
Builds a set of node IDs for nodes which belong to non-subactive elements.
Definition: mesh_tools.C:694
libMesh::MeshTools::libmesh_assert_valid_unique_ids
void libmesh_assert_valid_unique_ids(const MeshBase &mesh)
A function for verifying that unique ids match across processors.
Definition: mesh_tools.C:1634
libMesh::MeshBase::active_type_elements_end
virtual element_iterator active_type_elements_end(ElemType type)=0
libMesh::MeshTools::libmesh_assert_topology_consistent_procids< Node >
void libmesh_assert_topology_consistent_procids< Node >(const MeshBase &mesh)
Definition: mesh_tools.C:1819
libMesh::ParallelObject::n_processors
processor_id_type n_processors() const
Definition: parallel_object.h:100
new_proc_ids
const proc_id_map_type & new_proc_ids
Definition: mesh_tools.C:2207
libMesh::MeshTools::elem_types
void elem_types(const MeshBase &mesh, std::vector< ElemType > &et)
Fills in a vector of all element types in the mesh.
Definition: mesh_tools.C:570
libMesh::MeshBase::node_ptr_range
virtual SimpleRange< node_iterator > node_ptr_range()=0
node_set
std::unordered_set< const Node * > & node_set
Definition: mesh_tools.C:2135
libMesh::MeshBase::const_node_iterator
The definition of the const_node_iterator struct.
Definition: mesh_base.h:1945
libMesh::DofObject::n_comp
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:926
libMesh::ParallelObject::processor_id
processor_id_type processor_id() const
Definition: parallel_object.h:106
libMesh::libmesh_ignore
void libmesh_ignore(const Args &...)
Definition: libmesh_common.h:526
libMesh::MeshTools::n_nodes
dof_id_type n_nodes(const MeshBase::const_node_iterator &begin, const MeshBase::const_node_iterator &end)
Count up the number of nodes of a specific type (as defined by an iterator range).
Definition: mesh_tools.C:713
libMesh::MeshTools::subdomain_bounding_sphere
Sphere subdomain_bounding_sphere(const MeshBase &mesh, const subdomain_id_type sid)
Definition: mesh_tools.C:556
libMesh::DofObject::invalid_id
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:421
libMesh::MeshBase::local_node_ptr_range
virtual SimpleRange< node_iterator > local_node_ptr_range()=0
libMesh::MeshTools::create_processor_bounding_box
libMesh::BoundingBox create_processor_bounding_box(const MeshBase &mesh, const processor_id_type pid)
The same functionality as the deprecated MeshTools::processor_bounding_box().
Definition: mesh_tools.C:480
libMesh::QUAD4
Definition: enum_elem_type.h:41
libMesh::MeshBase::pid_nodes_end
virtual node_iterator pid_nodes_end(processor_id_type proc_id)=0
libMesh::MeshTools::libmesh_assert_contiguous_dof_ids
void libmesh_assert_contiguous_dof_ids(const MeshBase &mesh, unsigned int sysnum)
A function for verifying that degree of freedom indexes are contiguous on each processors,...
Definition: mesh_tools.C:1593
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
libMesh::MeshTools::libmesh_assert_old_dof_objects
void libmesh_assert_old_dof_objects(const MeshBase &mesh)
A function for testing that all non-recently-created DofObjects within a mesh have old_dof_object dat...
Definition: mesh_tools.C:1194
libMesh::MeshTools::n_non_subactive_elem_of_type_at_level
dof_id_type n_non_subactive_elem_of_type_at_level(const MeshBase &mesh, const ElemType type, const unsigned int level)
Definition: mesh_tools.C:598
libMesh::processor_id_type
uint8_t processor_id_type
Definition: id_types.h:104
libMesh::Node::choose_processor_id
processor_id_type choose_processor_id(processor_id_type pid1, processor_id_type pid2) const
Return which of pid1 and pid2 would be preferred by the current load-balancing heuristic applied to t...
Definition: node.C:78
libMesh::MeshTools::n_active_levels
unsigned int n_active_levels(const MeshBase &mesh)
Definition: mesh_tools.C:626
libMesh::Node
A Node is like a Point, but with more information.
Definition: node.h:52
libMesh::Threads::parallel_reduce
void parallel_reduce(const Range &range, Body &body)
Execute the provided reduction operation in parallel on the specified range.
Definition: threads_none.h:101
libMesh::MeshTools::libmesh_assert_equal_n_systems
void libmesh_assert_equal_n_systems(const MeshBase &mesh)
A function for testing that all DofObjects within a mesh have the same n_systems count.
Definition: mesh_tools.C:1168
libMesh::as_range
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
libMesh::MeshTools::n_elem_of_type
dof_id_type n_elem_of_type(const MeshBase &mesh, const ElemType type)
Definition: mesh_tools.C:582
n_nodes
const dof_id_type n_nodes
Definition: tecplot_io.C:68
libMesh::MeshTools::libmesh_assert_no_links_to_elem
void libmesh_assert_no_links_to_elem(const MeshBase &mesh, const Elem *bad_elem)
A function for verifying that an element has been cut off from the rest of the mesh.
Definition: mesh_tools.C:1272
libMesh::DofObject::unique_id
unique_id_type unique_id() const
Definition: dof_object.h:784
libMesh::MeshTools::find_nodal_neighbors
void find_nodal_neighbors(const MeshBase &mesh, const Node &n, const std::vector< std::vector< const Elem * >> &nodes_to_elem_map, std::vector< const Node * > &neighbors)
Given a mesh and a node in the mesh, the vector will be filled with every node directly attached to t...
Definition: mesh_tools.C:743
libMesh::Utility::enum_to_string
std::string enum_to_string(const T e)
libMesh::MeshBase::const_element_iterator
The definition of the const_element_iterator struct.
Definition: mesh_base.h:1891
libMesh::DofObject::n_vars
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:891
libMesh::MeshBase::nodes_end
virtual node_iterator nodes_end()=0
libMesh::MeshBase::skip_noncritical_partitioning
void skip_noncritical_partitioning(bool skip)
If true is passed in then the elements on this mesh will no longer be (re)partitioned,...
Definition: mesh_base.h:1058
libMesh::MeshTools::n_active_local_levels
unsigned int n_active_local_levels(const MeshBase &mesh)
Definition: mesh_tools.C:614
libMesh::MeshBase::node_ref
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:451
libMesh::MeshTools::libmesh_assert_valid_dof_ids
void libmesh_assert_valid_dof_ids(const MeshBase &mesh, unsigned int sysnum=libMesh::invalid_uint)
A function for verifying that degree of freedom indexing matches across processors.
Definition: mesh_tools.C:1566
libMesh::Elem::parent
const Elem * parent() const
Definition: elem.h:2434
libMesh::MeshBase::n_nodes
virtual dof_id_type n_nodes() const =0
distance
Real distance(const Point &p)
Definition: subdomains_ex3.C:50
libMesh::MeshTools::libmesh_assert_canonical_node_procids
void libmesh_assert_canonical_node_procids(const MeshBase &mesh)
A function for verifying that processor assignment of nodes matches the heuristic specified in Node::...
Definition: mesh_tools.C:1961
libMesh::MeshTools::n_active_elem_of_type
dof_id_type n_active_elem_of_type(const MeshBase &mesh, const ElemType type)
Definition: mesh_tools.C:591
libMesh::Elem::interior_parent
const Elem * interior_parent() const
Definition: elem.C:749
libMesh::Parallel::sync_dofobject_data_by_id
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
Definition: parallel_ghost_sync.h:338
libMesh::MeshBase::sub_point_locator
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:672
libMesh::MeshTools::Private::globally_renumber_nodes_and_elements
void globally_renumber_nodes_and_elements(MeshBase &)
There is no reason for a user to ever call this function.
Definition: mesh_tools.C:2411
libMesh::MeshBase::nodes_begin
virtual node_iterator nodes_begin()=0
Iterate over all the nodes in the Mesh.
libMesh::MeshTools::subdomain_bounding_box
BoundingBox subdomain_bounding_box(const MeshBase &mesh, const subdomain_id_type sid)
Definition: mesh_tools.C:521
libMesh::MeshBase::active_type_elements_begin
virtual element_iterator active_type_elements_begin(ElemType type)=0
libMesh::MeshBase::local_elements_end
virtual element_iterator local_elements_end()=0
libMesh::DofObject::id
dof_id_type id() const
Definition: dof_object.h:767
libMesh::MeshTools::libmesh_assert_valid_remote_elems
void libmesh_assert_valid_remote_elems(const MeshBase &mesh)
A function for verifying that active local elements' neighbors are never remote elements.
Definition: mesh_tools.C:1242
libMesh::MeshTools::find_hanging_nodes_and_parents
void find_hanging_nodes_and_parents(const MeshBase &mesh, std::map< dof_id_type, std::vector< dof_id_type >> &hanging_nodes)
Given a mesh hanging_nodes will be filled with an associative array keyed off the global id of all th...
Definition: mesh_tools.C:1078
libMesh::MeshBase::elements_end
virtual element_iterator elements_end()=0
libMesh::EDGE3
Definition: enum_elem_type.h:36
libMesh::Elem::has_children
bool has_children() const
Definition: elem.h:2383
libMesh::StoredRange
The StoredRange class defines a contiguous, divisible set of objects.
Definition: stored_range.h:52
libMesh::MeshCommunication::assign_global_indices
void assign_global_indices(MeshBase &) const
This method assigns globally unique, partition-agnostic indices to the nodes and elements in the mesh...
Definition: mesh_communication_global_indices.C:178
libMesh::MeshTools::libmesh_assert_valid_amr_interior_parents
void libmesh_assert_valid_amr_interior_parents(const MeshBase &mesh)
A function for verifying that any interior_parent pointers on elements are consistent with AMR (paren...
Definition: mesh_tools.C:1335
libMesh::MeshTools::n_p_levels
unsigned int n_p_levels(const MeshBase &mesh)
Definition: mesh_tools.C:721
libMesh::DofObject::invalid_processor_id
static const processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
Definition: dof_object.h:432
libMesh::Elem
This is the base class from which all geometric element types are derived.
Definition: elem.h:100
libMesh::MeshTools::libmesh_assert_consistent_distributed
void libmesh_assert_consistent_distributed(const MeshBase &mesh)
A function for verifying that distribution of dof objects is parallel consistent (every processor can...
Definition: mesh_tools.C:1664
std::norm
MetaPhysicL::DualNumber< T, D > norm(const MetaPhysicL::DualNumber< T, D > &in)
data
IterBase * data
Ideally this private member data should have protected access.
Definition: variant_filter_iterator.h:337
libMesh::MeshTools::libmesh_assert_valid_refinement_tree
void libmesh_assert_valid_refinement_tree(const MeshBase &mesh)
A function for verifying that elements on this processor have valid descendants and consistent active...
Definition: mesh_tools.C:2026
libMesh::MeshTools::find_boundary_nodes
void find_boundary_nodes(const MeshBase &mesh, std::vector< bool > &on_boundary)
Definition: mesh_tools.C:306
libMesh::Elem::neighbor_ptr
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2085
libMesh::MeshTools::libmesh_assert_valid_refinement_flags
void libmesh_assert_valid_refinement_flags(const MeshBase &mesh)
A function for verifying that refinement flags on elements are consistent between processors.
Definition: mesh_tools.C:1978
libMesh::TestClass
Definition: id_types.h:33
libMesh::Elem::node_id
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1977
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::Elem::INACTIVE
Definition: elem.h:1174
libMesh::MeshCommunication
This is the MeshCommunication class.
Definition: mesh_communication.h:50
libMesh::MeshTools::BoundingBox
Backwards compatibility with forward declarations.
Definition: mesh_tools.h:70
libMesh::Elem::n_sides
virtual unsigned int n_sides() const =0
libMesh::MeshBase::query_node_ptr
virtual const Node * query_node_ptr(const dof_id_type i) const =0
libMesh::MeshTools::weight
dof_id_type weight(const MeshBase &mesh, const processor_id_type pid)
Definition: mesh_tools.C:236
libMesh::BoundaryInfo::invalid_id
static const boundary_id_type invalid_id
Number used for internal use.
Definition: boundary_info.h:899
libMesh::Elem::node_ptr
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:2009
libMesh::MeshBase::local_nodes_end
virtual node_iterator local_nodes_end()=0
libMesh::Elem::which_neighbor_am_i
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
Definition: elem.h:2323
libMesh::remote_elem
const RemoteElem * remote_elem
Definition: remote_elem.C:57
libMesh::MeshTools::correct_node_proc_ids
void correct_node_proc_ids(MeshBase &)
Changes the processor ids on each node so be the same as the id of the lowest element touching that n...
Definition: mesh_tools.C:2252
libMesh::MeshBase::unpartitioned_elements_end
virtual element_iterator unpartitioned_elements_end()=0
libMesh::EDGE2
Definition: enum_elem_type.h:35
libMesh::MeshBase::unpartitioned_elements_begin
virtual element_iterator unpartitioned_elements_begin()=0
Iterate over unpartitioned elements in the Mesh.
libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Elem >
void libmesh_assert_parallel_consistent_procids< Elem >(const MeshBase &mesh)
Definition: mesh_tools.C:1770
libMesh::MeshBase::active_local_subdomain_elements_begin
virtual element_iterator active_local_subdomain_elements_begin(subdomain_id_type subdomain_id)=0
libMesh::ElemType
ElemType
Defines an enum for geometric element types.
Definition: enum_elem_type.h:33
libMesh::Elem::top_parent
const Elem * top_parent() const
Definition: elem.h:2460
libMesh::MeshTools::libmesh_assert_parallel_consistent_procids< Node >
void libmesh_assert_parallel_consistent_procids< Node >(const MeshBase &mesh)
Definition: mesh_tools.C:1908