libMesh
mesh_tools.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 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/mesh_base.h"
24 #include "libmesh/mesh_communication.h"
25 #include "libmesh/mesh_tools.h"
26 #include "libmesh/node_range.h"
27 #include "libmesh/parallel.h"
28 #include "libmesh/parallel_algebra.h"
29 #include "libmesh/parallel_ghost_sync.h"
30 #include "libmesh/sphere.h"
31 #include "libmesh/threads.h"
32 #include "libmesh/string_to_enum.h"
33 
34 #ifdef DEBUG
35 # include "libmesh/remote_elem.h"
36 #endif
37 
38 // C++ includes
39 #include <limits>
40 #include <numeric> // for std::accumulate
41 #include <set>
42 #include <unordered_map>
43 #include <unordered_set>
44 
45 
46 
47 // ------------------------------------------------------------
48 // anonymous namespace for helper classes
49 namespace {
50 
51 using namespace libMesh;
52 
60 class SumElemWeight
61 {
62 public:
63  SumElemWeight () :
64  _weight(0)
65  {}
66 
67  SumElemWeight (SumElemWeight &, Threads::split) :
68  _weight(0)
69  {}
70 
71  void operator()(const ConstElemRange & range)
72  {
73  for (ConstElemRange::const_iterator it = range.begin(); it !=range.end(); ++it)
74  _weight += (*it)->n_nodes();
75  }
76 
77  dof_id_type weight() const
78  { return _weight; }
79 
80  // If we don't have threads we never need a join, and icpc yells a
81  // warning if it sees an anonymous function that's never used
82 #if LIBMESH_USING_THREADS
83  void join (const SumElemWeight & other)
84  { _weight += other.weight(); }
85 #endif
86 
87 private:
88  dof_id_type _weight;
89 };
90 
91 
98 class FindBBox
99 {
100 public:
101  FindBBox () : _bbox()
102  {}
103 
104  FindBBox (FindBBox & other, Threads::split) :
105  _bbox(other._bbox)
106  {}
107 
108  void operator()(const ConstNodeRange & range)
109  {
110  for (ConstNodeRange::const_iterator it = range.begin(); it != range.end(); ++it)
111  {
112  const Node * node = *it;
113  libmesh_assert(node);
114 
115  _bbox.union_with(*node);
116  }
117  }
118 
119  void operator()(const ConstElemRange & range)
120  {
121  for (ConstElemRange::const_iterator it = range.begin(); it != range.end(); ++it)
122  {
123  const Elem * elem = *it;
124  libmesh_assert(elem);
125 
126  _bbox.union_with(elem->loose_bounding_box());
127  }
128  }
129 
130  const Point & min() const { return _bbox.min(); }
131 
132  Point & min() { return _bbox.min(); }
133 
134  const Point & max() const { return _bbox.max(); }
135 
136  Point & max() { return _bbox.max(); }
137 
138  // If we don't have threads we never need a join, and icpc yells a
139  // warning if it sees an anonymous function that's never used
140 #if LIBMESH_USING_THREADS
141  void join (const FindBBox & other)
142  {
143  _bbox.union_with(other._bbox);
144  }
145 #endif
146 
147  const libMesh::BoundingBox & bbox () const
148  {
149  return _bbox;
150  }
151 
152  libMesh::BoundingBox & bbox ()
153  {
154  return _bbox;
155  }
156 
157 private:
158  BoundingBox _bbox;
159 };
160 
161 #ifdef DEBUG
162 void assert_semiverify_dofobj(const Parallel::Communicator & communicator,
163  const DofObject * d,
164  unsigned int sysnum = libMesh::invalid_uint)
165 {
166  if (d)
167  {
168  const unsigned int n_sys = d->n_systems();
169 
170  std::vector<unsigned int> n_vars (n_sys, 0);
171  for (unsigned int s = 0; s != n_sys; ++s)
172  if (sysnum == s ||
173  sysnum == libMesh::invalid_uint)
174  n_vars[s] = d->n_vars(s);
175 
176  const unsigned int tot_n_vars =
177  std::accumulate(n_vars.begin(), n_vars.end(), 0);
178 
179  std::vector<unsigned int> n_comp (tot_n_vars, 0);
180  std::vector<dof_id_type> first_dof (tot_n_vars, 0);
181 
182  for (unsigned int s = 0, i=0; s != n_sys; ++s)
183  {
184  if (sysnum != s &&
185  sysnum != libMesh::invalid_uint)
186  continue;
187 
188  for (unsigned int v = 0; v != n_vars[s]; ++v, ++i)
189  {
190  n_comp[i] = d->n_comp(s,v);
191  first_dof[i] = n_comp[i] ? d->dof_number(s,v,0) : DofObject::invalid_id;
192  }
193  }
194 
195  libmesh_assert(communicator.semiverify(&n_sys));
196  libmesh_assert(communicator.semiverify(&n_vars));
197  libmesh_assert(communicator.semiverify(&n_comp));
198  libmesh_assert(communicator.semiverify(&first_dof));
199  }
200  else
201  {
202  const unsigned int * p_ui = libmesh_nullptr;
203  const std::vector<unsigned int> * p_vui = libmesh_nullptr;
204  const std::vector<dof_id_type> * p_vdid = libmesh_nullptr;
205 
206  libmesh_assert(communicator.semiverify(p_ui));
207  libmesh_assert(communicator.semiverify(p_vui));
208  libmesh_assert(communicator.semiverify(p_vui));
209  libmesh_assert(communicator.semiverify(p_vdid));
210  }
211 }
212 #endif // DEBUG
213 
214 }
215 
216 
217 namespace libMesh
218 {
219 
220 // ------------------------------------------------------------
221 // MeshTools functions
223 {
224  if (!mesh.is_serial())
225  {
226  libmesh_parallel_only(mesh.comm());
228  mesh.comm().sum(weight);
229  dof_id_type unpartitioned_weight =
231  return weight + unpartitioned_weight;
232  }
233 
234  SumElemWeight sew;
235 
237  mesh.elements_end()),
238  sew);
239  return sew.weight();
240 
241 }
242 
243 
244 
246 {
247  SumElemWeight sew;
248 
250  mesh.pid_elements_end(pid)),
251  sew);
252  return sew.weight();
253 }
254 
255 
256 
258  std::vector<std::vector<dof_id_type>> & nodes_to_elem_map)
259 {
260  nodes_to_elem_map.resize (mesh.n_nodes());
261 
262  for (const auto & elem : mesh.element_ptr_range())
263  for (auto & node : elem->node_ref_range())
264  {
265  libmesh_assert_less (node.id(), nodes_to_elem_map.size());
266  libmesh_assert_less (elem->id(), mesh.n_elem());
267 
268  nodes_to_elem_map[node.id()].push_back(elem->id());
269  }
270 }
271 
272 
273 
275  std::vector<std::vector<const Elem *>> & nodes_to_elem_map)
276 {
277  nodes_to_elem_map.resize (mesh.n_nodes());
278 
279  for (const auto & elem : mesh.element_ptr_range())
280  for (auto & node : elem->node_ref_range())
281  {
282  libmesh_assert_less (node.id(), nodes_to_elem_map.size());
283 
284  nodes_to_elem_map[node.id()].push_back(elem);
285  }
286 }
287 
288 
289 
291  std::vector<bool> & on_boundary)
292 {
293  // Resize the vector which holds boundary nodes and fill with false.
294  on_boundary.resize(mesh.max_node_id());
295  std::fill(on_boundary.begin(),
296  on_boundary.end(),
297  false);
298 
299  // Loop over elements, find those on boundary, and
300  // mark them as true in on_boundary.
301  for (const auto & elem : mesh.active_element_ptr_range())
302  for (auto s : elem->side_index_range())
303  if (elem->neighbor_ptr(s) == libmesh_nullptr) // on the boundary
304  {
305  UniquePtr<const Elem> side = elem->build_side_ptr(s);
306 
307  for (auto & node : side->node_ref_range())
308  on_boundary[node.id()] = true;
309  }
310 }
311 
312 
313 
314 #ifdef LIBMESH_ENABLE_DEPRECATED
317 {
318  // This function is deprecated. It simply calls
319  // create_bounding_box() and converts the result to a
320  // MeshTools::BoundingBox.
321  libmesh_deprecated();
322  return MeshTools::create_bounding_box(mesh);
323 }
324 #endif
325 
326 
327 
330 {
331  // This function must be run on all processors at once
332  libmesh_parallel_only(mesh.comm());
333 
334  FindBBox find_bbox;
335 
336  // Start with any unpartitioned elements we know about locally
339  find_bbox);
340 
341  // And combine with our local elements
342  find_bbox.bbox().union_with(MeshTools::create_local_bounding_box(mesh));
343 
344  // Compare the bounding boxes across processors
345  mesh.comm().min(find_bbox.min());
346  mesh.comm().max(find_bbox.max());
347 
348  return find_bbox.bbox();
349 }
350 
351 
352 
355 {
356  // This function must be run on all processors at once
357  libmesh_parallel_only(mesh.comm());
358 
359  FindBBox find_bbox;
360 
361  // Start with any unpartitioned nodes we know about locally
364  find_bbox);
365 
366  // Add our local nodes
368  mesh.local_nodes_end()),
369  find_bbox);
370 
371  // Compare the bounding boxes across processors
372  mesh.comm().min(find_bbox.min());
373  mesh.comm().max(find_bbox.max());
374 
375  return find_bbox.bbox();
376 }
377 
378 
379 
380 Sphere
382 {
384 
385  const Real diag = (bbox.second - bbox.first).norm();
386  const Point cent = (bbox.second + bbox.first)/2;
387 
388  return Sphere (cent, .5*diag);
389 }
390 
391 
392 
395 {
396  FindBBox find_bbox;
397 
399  mesh.local_elements_end()),
400  find_bbox);
401 
402  return find_bbox.bbox();
403 }
404 
405 
406 
407 #ifdef LIBMESH_ENABLE_DEPRECATED
410  const processor_id_type pid)
411 {
412  libmesh_deprecated();
414 }
415 #endif
416 
417 
418 
421  const processor_id_type pid)
422 {
423  // This can only be run in parallel, with consistent arguments.
424  libmesh_parallel_only(mesh.comm());
425  libmesh_assert(mesh.comm().verify(pid));
426 
427  libmesh_assert_less (pid, mesh.n_processors());
428 
429  FindBBox find_bbox;
430 
432  mesh.pid_elements_end(pid)),
433  find_bbox);
434 
435  // Compare the bounding boxes across processors
436  mesh.comm().min(find_bbox.min());
437  mesh.comm().max(find_bbox.max());
438 
439  return find_bbox.bbox();
440 }
441 
442 
443 
444 Sphere
446  const processor_id_type pid)
447 {
448  libMesh::BoundingBox bbox =
450 
451  const Real diag = (bbox.second - bbox.first).norm();
452  const Point cent = (bbox.second + bbox.first)/2;
453 
454  return Sphere (cent, .5*diag);
455 }
456 
457 
458 
459 #ifdef LIBMESH_ENABLE_DEPRECATED
462  const subdomain_id_type sid)
463 {
464  libmesh_deprecated();
466 }
467 #endif
468 
469 
470 
473  const subdomain_id_type sid)
474 {
475  // This can only be run in parallel, with consistent arguments.
476  libmesh_parallel_only(mesh.comm());
477  libmesh_assert(mesh.comm().verify(sid));
478 
479  FindBBox find_bbox;
480 
484  find_bbox);
485 
486  // Compare the bounding boxes across processors
487  mesh.comm().min(find_bbox.min());
488  mesh.comm().max(find_bbox.max());
489 
490  return find_bbox.bbox();
491 }
492 
493 
494 
495 Sphere
497  const subdomain_id_type sid)
498 {
499  libMesh::BoundingBox bbox =
501 
502  const Real diag = (bbox.second - bbox.first).norm();
503  const Point cent = (bbox.second + bbox.first)/2;
504 
505  return Sphere (cent, .5*diag);
506 }
507 
508 
509 
511  std::vector<ElemType> & et)
512 {
513  // Loop over the the elements. If the current element type isn't in
514  // the vector, insert it.
515  for (const auto & elem : mesh.element_ptr_range())
516  if (!std::count(et.begin(), et.end(), elem->type()))
517  et.push_back(elem->type());
518 }
519 
520 
521 
523  const ElemType type)
524 {
525  return static_cast<dof_id_type>(std::distance(mesh.type_elements_begin(type),
526  mesh.type_elements_end (type)));
527 }
528 
529 
530 
532  const ElemType type)
533 {
534  return static_cast<dof_id_type>(std::distance(mesh.active_type_elements_begin(type),
535  mesh.active_type_elements_end (type)));
536 }
537 
539  const ElemType type,
540  const unsigned int level)
541 {
542  dof_id_type cnt = 0;
543  // iterate over the elements of the specified type
546 
547  for (; el!=end; ++el)
548  if (((*el)->level() == level) && !(*el)->subactive())
549  cnt++;
550 
551  return cnt;
552 }
553 
554 
556 {
557  unsigned int nl = 0;
558 
559  for (auto & elem : mesh.active_local_element_ptr_range())
560  nl = std::max(elem->level() + 1, nl);
561 
562  return nl;
563 }
564 
565 
566 
568 {
569  libmesh_parallel_only(mesh.comm());
570 
571  unsigned int nl = MeshTools::n_active_local_levels(mesh);
572 
575  const MeshBase::const_element_iterator end_el =
577 
578  for ( ; el != end_el; ++el)
579  if ((*el)->active())
580  nl = std::max((*el)->level() + 1, nl);
581 
582  mesh.comm().max(nl);
583  return nl;
584 }
585 
586 
587 
589 {
590  unsigned int nl = 0;
591 
594 
595  for ( ; el != end_el; ++el)
596  nl = std::max((*el)->level() + 1, nl);
597 
598  return nl;
599 }
600 
601 
602 
603 unsigned int MeshTools::n_levels(const MeshBase & mesh)
604 {
605  libmesh_parallel_only(mesh.comm());
606 
607  unsigned int nl = MeshTools::n_local_levels(mesh);
608 
611  const MeshBase::const_element_iterator end_el =
613 
614  for ( ; el != end_el; ++el)
615  nl = std::max((*el)->level() + 1, nl);
616 
617  mesh.comm().max(nl);
618 
619  // n_levels() is only valid and should only be called in cases where
620  // the mesh is validly distributed (or serialized). Let's run an
621  // expensive test in debug mode to make sure this is such a case.
622 #ifdef DEBUG
623  const unsigned int paranoid_nl = MeshTools::paranoid_n_levels(mesh);
624  libmesh_assert_equal_to(nl, paranoid_nl);
625 #endif
626  return nl;
627 }
628 
629 
630 
632 {
633  libmesh_parallel_only(mesh.comm());
634 
635  unsigned int nl = 0;
636  for (const auto & elem : mesh.element_ptr_range())
637  nl = std::max(elem->level() + 1, nl);
638 
639  mesh.comm().max(nl);
640  return nl;
641 }
642 
643 
644 
646  std::set<dof_id_type> & not_subactive_node_ids)
647 {
648  for (const auto & elem : mesh.element_ptr_range())
649  if (!elem->subactive())
650  for (auto & n : elem->node_ref_range())
651  not_subactive_node_ids.insert(n.id());
652 }
653 
654 
655 
658 {
659  return cast_int<dof_id_type>(std::distance(begin, end));
660 }
661 
662 
663 
666 {
667  return cast_int<dof_id_type>(std::distance(begin, end));
668 }
669 
670 
671 
672 unsigned int MeshTools::n_p_levels (const MeshBase & mesh)
673 {
674  libmesh_parallel_only(mesh.comm());
675 
676  unsigned int max_p_level = 0;
677 
678  // first my local elements
680  el = mesh.local_elements_begin(),
681  end_el = mesh.local_elements_end();
682 
683  for ( ; el != end_el; ++el)
684  max_p_level = std::max((*el)->p_level(), max_p_level);
685 
686  // then any unpartitioned objects
687  el = mesh.unpartitioned_elements_begin();
688  end_el = mesh.unpartitioned_elements_end();
689 
690  for ( ; el != end_el; ++el)
691  max_p_level = std::max((*el)->p_level(), max_p_level);
692 
693  mesh.comm().max(max_p_level);
694  return max_p_level + 1;
695 }
696 
697 
698 
700  const Node & node,
701  const std::vector<std::vector<const Elem *>> & nodes_to_elem_map,
702  std::vector<const Node *> & neighbors)
703 {
704  // We'll refer back to the Node ID several times
705  dof_id_type global_id = node.id();
706 
707  // We'll construct a std::set<const Node *> for more efficient
708  // searching while finding the nodal neighbors, and return it to the
709  // user in a std::vector.
710  std::set<const Node *> neighbor_set;
711 
712  // Iterators to iterate through the elements that include this node
713  std::vector<const Elem *>::const_iterator
714  el = nodes_to_elem_map[global_id].begin(),
715  end_el = nodes_to_elem_map[global_id].end();
716 
717  // Look through the elements that contain this node
718  // find the local node id... then find the side that
719  // node lives on in the element
720  // next, look for the _other_ node on that side
721  // That other node is a "nodal_neighbor"... save it
722  for (; el != end_el; ++el)
723  {
724  // Grab an Elem pointer to use in the subsequent loop
725  const Elem * elem = *el;
726 
727  // We only care about active elements...
728  if (elem->active())
729  {
730  // Which local node number is global_id?
731  unsigned local_node_number = elem->local_node(global_id);
732 
733  // Make sure it was found
734  libmesh_assert_not_equal_to(local_node_number, libMesh::invalid_uint);
735 
736  const unsigned short n_edges = elem->n_edges();
737 
738  // If this element has no edges, the edge-based algorithm below doesn't make sense.
739  if (!n_edges)
740  {
741  switch (elem->type())
742  {
743  case EDGE2:
744  {
745  switch (local_node_number)
746  {
747  case 0:
748  // The other node is a nodal neighbor
749  neighbor_set.insert(elem->node_ptr(1));
750  break;
751 
752  case 1:
753  // The other node is a nodal neighbor
754  neighbor_set.insert(elem->node_ptr(0));
755  break;
756 
757  default:
758  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
759  }
760  break;
761  }
762 
763  case EDGE3:
764  {
765  switch (local_node_number)
766  {
767  // The outside nodes have node 2 as a neighbor
768  case 0:
769  case 1:
770  neighbor_set.insert(elem->node_ptr(2));
771  break;
772 
773  // The middle node has the outer nodes as neighbors
774  case 2:
775  neighbor_set.insert(elem->node_ptr(0));
776  neighbor_set.insert(elem->node_ptr(1));
777  break;
778 
779  default:
780  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
781  }
782  break;
783  }
784 
785  case EDGE4:
786  {
787  switch (local_node_number)
788  {
789  case 0:
790  // The left-middle node is a nodal neighbor
791  neighbor_set.insert(elem->node_ptr(2));
792  break;
793 
794  case 1:
795  // The right-middle node is a nodal neighbor
796  neighbor_set.insert(elem->node_ptr(3));
797  break;
798 
799  // The left-middle node
800  case 2:
801  neighbor_set.insert(elem->node_ptr(0));
802  neighbor_set.insert(elem->node_ptr(3));
803  break;
804 
805  // The right-middle node
806  case 3:
807  neighbor_set.insert(elem->node_ptr(1));
808  neighbor_set.insert(elem->node_ptr(2));
809  break;
810 
811  default:
812  libmesh_error_msg("Invalid local node number: " << local_node_number << " found." << std::endl);
813  }
814  break;
815  }
816 
817  default:
818  libmesh_error_msg("Unrecognized ElemType: " << Utility::enum_to_string(elem->type()) << std::endl);
819  }
820  }
821 
822  // Index of the current edge
823  unsigned current_edge = 0;
824 
825  const unsigned short n_nodes = elem->n_nodes();
826 
827  while (current_edge < n_edges)
828  {
829  // Find the edge the node is on
830  bool found_edge = false;
831  for (; current_edge<n_edges; ++current_edge)
832  if (elem->is_node_on_edge(local_node_number, current_edge))
833  {
834  found_edge = true;
835  break;
836  }
837 
838  // Did we find one?
839  if (found_edge)
840  {
841  const Node * node_to_save = libmesh_nullptr;
842 
843  // Find another node in this element on this edge
844  for (unsigned other_node_this_edge = 0; other_node_this_edge != n_nodes; other_node_this_edge++)
845  if ( (elem->is_node_on_edge(other_node_this_edge, current_edge)) && // On the current edge
846  (elem->node_id(other_node_this_edge) != global_id)) // But not the original node
847  {
848  // We've found a nodal neighbor! Save a pointer to it..
849  node_to_save = elem->node_ptr(other_node_this_edge);
850  break;
851  }
852 
853  // Make sure we found something
854  libmesh_assert(node_to_save != libmesh_nullptr);
855 
856  neighbor_set.insert(node_to_save);
857  }
858 
859  // Keep looking for edges, node may be on more than one edge
860  current_edge++;
861  }
862  } // if (elem->active())
863  } // for
864 
865  // Assign the entries from the set to the vector. Note: this
866  // replaces any existing contents in neighbors and modifies its size
867  // accordingly.
868  neighbors.assign(neighbor_set.begin(), neighbor_set.end());
869 }
870 
871 
872 
874  std::map<dof_id_type, std::vector<dof_id_type>> & hanging_nodes)
875 {
876  // Loop through all the elements
877  for (auto & elem : mesh.active_local_element_ptr_range())
878  if (elem->type() == QUAD4)
879  for (auto s : elem->side_index_range())
880  {
881  // Loop over the sides looking for sides that have hanging nodes
882  // This code is inspired by compute_proj_constraints()
883  const Elem * neigh = elem->neighbor_ptr(s);
884 
885  // If not a boundary side
886  if (neigh != libmesh_nullptr)
887  {
888  // Is there a coarser element next to this one?
889  if (neigh->level() < elem->level())
890  {
891  const Elem * ancestor = elem;
892  while (neigh->level() < ancestor->level())
893  ancestor = ancestor->parent();
894  unsigned int s_neigh = neigh->which_neighbor_am_i(ancestor);
895  libmesh_assert_less (s_neigh, neigh->n_neighbors());
896 
897  // Couple of helper uints...
898  unsigned int local_node1=0;
899  unsigned int local_node2=0;
900 
901  bool found_in_neighbor = false;
902 
903  // Find the two vertices that make up this side
904  while (!elem->is_node_on_side(local_node1++,s)) { }
905  local_node1--;
906 
907  // Start looking for the second one with the next node
908  local_node2=local_node1+1;
909 
910  // Find the other one
911  while (!elem->is_node_on_side(local_node2++,s)) { }
912  local_node2--;
913 
914  //Pull out their global ids:
915  dof_id_type node1 = elem->node_id(local_node1);
916  dof_id_type node2 = elem->node_id(local_node2);
917 
918  // Now find which node is present in the neighbor
919  // FIXME This assumes a level one rule!
920  // The _other_ one is the hanging node
921 
922  // First look for the first one
923  // FIXME could be streamlined a bit
924  for (unsigned int n=0;n<neigh->n_sides();n++)
925  if (neigh->node_id(n) == node1)
926  found_in_neighbor=true;
927 
928  dof_id_type hanging_node=0;
929 
930  if (!found_in_neighbor)
931  hanging_node=node1;
932  else // If it wasn't node1 then it must be node2!
933  hanging_node=node2;
934 
935  // Reset these for reuse
936  local_node1=0;
937  local_node2=0;
938 
939  // Find the first node that makes up the side in the neighbor (these should be the parent nodes)
940  while (!neigh->is_node_on_side(local_node1++,s_neigh)) { }
941  local_node1--;
942 
943  local_node2=local_node1+1;
944 
945  // Find the second node...
946  while (!neigh->is_node_on_side(local_node2++,s_neigh)) { }
947  local_node2--;
948 
949  // Save them if we haven't already found the parents for this one
950  if (hanging_nodes[hanging_node].size()<2)
951  {
952  hanging_nodes[hanging_node].push_back(neigh->node_id(local_node1));
953  hanging_nodes[hanging_node].push_back(neigh->node_id(local_node2));
954  }
955  }
956  }
957  }
958 }
959 
960 
961 
962 #ifdef DEBUG
964 {
965  LOG_SCOPE("libmesh_assert_equal_n_systems()", "MeshTools");
966 
967  unsigned int n_sys = libMesh::invalid_uint;
968 
969  for (const auto & elem : mesh.element_ptr_range())
970  {
971  if (n_sys == libMesh::invalid_uint)
972  n_sys = elem->n_systems();
973  else
974  libmesh_assert_equal_to (elem->n_systems(), n_sys);
975  }
976 
977  for (const auto & node : mesh.node_ptr_range())
978  {
979  if (n_sys == libMesh::invalid_uint)
980  n_sys = node->n_systems();
981  else
982  libmesh_assert_equal_to (node->n_systems(), n_sys);
983  }
984 }
985 
986 
987 
988 #ifdef LIBMESH_ENABLE_AMR
990 {
991  LOG_SCOPE("libmesh_assert_old_dof_objects()", "MeshTools");
992 
993  for (const auto & elem : mesh.element_ptr_range())
994  {
995  if (elem->refinement_flag() == Elem::JUST_REFINED ||
996  elem->refinement_flag() == Elem::INACTIVE)
997  continue;
998 
999  if (elem->has_dofs())
1000  libmesh_assert(elem->old_dof_object);
1001 
1002  for (auto & node : elem->node_ref_range())
1003  if (node.has_dofs())
1004  libmesh_assert(node.old_dof_object);
1005  }
1006 }
1007 #else
1009 #endif // LIBMESH_ENABLE_AMR
1010 
1011 
1012 
1014 {
1015  LOG_SCOPE("libmesh_assert_valid_node_pointers()", "MeshTools");
1016 
1017  // Here we specifically do not want "auto &" because we need to
1018  // reseat the (temporary) pointer variable in the loop below,
1019  // without modifying the original.
1020  for (const Elem * elem : mesh.element_ptr_range())
1021  {
1022  libmesh_assert (elem);
1023  while (elem)
1024  {
1025  elem->libmesh_assert_valid_node_pointers();
1026  for (auto n : elem->neighbor_ptr_range())
1027  if (n && n != remote_elem)
1028  n->libmesh_assert_valid_node_pointers();
1029 
1030  libmesh_assert_not_equal_to (elem->parent(), remote_elem);
1031  elem = elem->parent();
1032  }
1033  }
1034 }
1035 
1036 
1038 {
1039  LOG_SCOPE("libmesh_assert_valid_remote_elems()", "MeshTools");
1040 
1041  const MeshBase::const_element_iterator el_end =
1042  mesh.local_elements_end();
1044  mesh.local_elements_begin(); el != el_end; ++el)
1045  {
1046  const Elem * elem = *el;
1047  libmesh_assert (elem);
1048 
1049  // We currently don't allow active_local_elements to have
1050  // remote_elem neighbors
1051  if (elem->active())
1052  for (auto n : elem->neighbor_ptr_range())
1053  libmesh_assert_not_equal_to (n, remote_elem);
1054 
1055 #ifdef LIBMESH_ENABLE_AMR
1056  const Elem * parent = elem->parent();
1057  if (parent)
1058  libmesh_assert_not_equal_to (parent, remote_elem);
1059 
1060  // We can only be strict about active elements' subactive
1061  // children
1062  if (elem->active() && elem->has_children())
1063  for (auto & child : elem->child_ref_range())
1064  libmesh_assert_not_equal_to (&child, remote_elem);
1065 #endif
1066  }
1067 }
1068 
1069 
1071  const Elem * bad_elem)
1072 {
1073  for (const auto & elem : mesh.element_ptr_range())
1074  {
1075  libmesh_assert (elem);
1076  libmesh_assert_not_equal_to (elem->parent(), bad_elem);
1077  for (auto n : elem->neighbor_ptr_range())
1078  libmesh_assert_not_equal_to (n, bad_elem);
1079 
1080 #ifdef LIBMESH_ENABLE_AMR
1081  if (elem->has_children())
1082  for (auto & child : elem->child_ref_range())
1083  libmesh_assert_not_equal_to (&child, bad_elem);
1084 #endif
1085  }
1086 }
1087 
1088 
1089 
1091 {
1092  LOG_SCOPE("libmesh_assert_valid_elem_ids()", "MeshTools");
1093 
1094  processor_id_type lastprocid = 0;
1095  dof_id_type lastelemid = 0;
1096 
1097  for (const auto & elem : mesh.active_element_ptr_range())
1098  {
1099  libmesh_assert (elem);
1100  processor_id_type elemprocid = elem->processor_id();
1101  dof_id_type elemid = elem->id();
1102 
1103  libmesh_assert_greater_equal (elemid, lastelemid);
1104  libmesh_assert_greater_equal (elemprocid, lastprocid);
1105 
1106  lastelemid = elemid;
1107  lastprocid = elemprocid;
1108  }
1109 }
1110 
1111 
1112 
1114 {
1115  LOG_SCOPE("libmesh_assert_valid_amr_elem_ids()", "MeshTools");
1116 
1117  for (const auto & elem : mesh.element_ptr_range())
1118  {
1119  libmesh_assert (elem);
1120 
1121  const Elem * parent = elem->parent();
1122 
1123  if (parent)
1124  {
1125  libmesh_assert_greater_equal (elem->id(), parent->id());
1126  libmesh_assert_greater_equal (elem->processor_id(), parent->processor_id());
1127  }
1128  }
1129 }
1130 
1131 
1132 
1134 {
1135  LOG_SCOPE("libmesh_assert_valid_amr_interior_parents()", "MeshTools");
1136 
1137  for (const auto & elem : mesh.element_ptr_range())
1138  {
1139  libmesh_assert (elem);
1140 
1141  // We can skip to the next element if we're full-dimension
1142  // and therefore don't have any interior parents
1143  if (elem->dim() >= LIBMESH_DIM)
1144  continue;
1145 
1146  const Elem * ip = elem->interior_parent();
1147 
1148  const Elem * parent = elem->parent();
1149 
1150  if (ip && (ip != remote_elem) && parent)
1151  {
1152  libmesh_assert_equal_to (ip->top_parent(),
1153  elem->top_parent()->interior_parent());
1154 
1155  if (ip->level() == elem->level())
1156  libmesh_assert_equal_to (ip->parent(),
1157  parent->interior_parent());
1158  else
1159  {
1160  libmesh_assert_less (ip->level(), elem->level());
1161  libmesh_assert_equal_to (ip, parent->interior_parent());
1162  }
1163  }
1164  }
1165 }
1166 
1167 
1168 
1170 {
1171  LOG_SCOPE("libmesh_assert_connected_nodes()", "MeshTools");
1172 
1173  std::set<const Node *> used_nodes;
1174 
1175  for (const auto & elem : mesh.element_ptr_range())
1176  {
1177  libmesh_assert (elem);
1178 
1179  for (auto & n : elem->node_ref_range())
1180  used_nodes.insert(&n);
1181  }
1182 
1183  for (const auto & node : mesh.node_ptr_range())
1184  {
1185  libmesh_assert(node);
1186  libmesh_assert(used_nodes.count(node));
1187  }
1188 }
1189 
1190 
1191 
1192 namespace MeshTools {
1193 
1195 {
1196  LOG_SCOPE("libmesh_assert_valid_boundary_ids()", "MeshTools");
1197 
1198  if (mesh.n_processors() == 1)
1199  return;
1200 
1201  libmesh_parallel_only(mesh.comm());
1202 
1203  const BoundaryInfo & boundary_info = mesh.get_boundary_info();
1204 
1205  dof_id_type pmax_elem_id = mesh.max_elem_id();
1206  mesh.comm().max(pmax_elem_id);
1207 
1208  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1209  {
1210  const Elem * elem = mesh.query_elem_ptr(i);
1211  const unsigned int my_n_nodes = elem ? elem->n_nodes() : 0;
1212  const unsigned int my_n_edges = elem ? elem->n_edges() : 0;
1213  const unsigned int my_n_sides = elem ? elem->n_sides() : 0;
1214  unsigned int n_nodes = my_n_nodes,
1215  n_edges = my_n_edges,
1216  n_sides = my_n_sides;
1217 
1218  mesh.comm().max(n_nodes);
1219  mesh.comm().max(n_edges);
1220  mesh.comm().max(n_sides);
1221 
1222  if (elem)
1223  {
1224  libmesh_assert_equal_to(my_n_nodes, n_nodes);
1225  libmesh_assert_equal_to(my_n_edges, n_edges);
1226  libmesh_assert_equal_to(my_n_sides, n_sides);
1227  }
1228 
1229  // Let's test all IDs on the element with one communication
1230  // rather than n_nodes + n_edges + n_sides communications, to
1231  // cut down on latency in dbg modes.
1232  std::vector<boundary_id_type> all_bcids;
1233 
1234  for (unsigned int n=0; n != n_nodes; ++n)
1235  {
1236  std::vector<boundary_id_type> bcids;
1237  if (elem)
1238  {
1239  boundary_info.boundary_ids(elem->node_ptr(n), bcids);
1240 
1241  // Ordering of boundary ids shouldn't matter
1242  std::sort(bcids.begin(), bcids.end());
1243  }
1244 // libmesh_assert(mesh.comm().semiverify
1245 // (elem ? &bcids : libmesh_nullptr));
1246 
1247  all_bcids.insert(all_bcids.end(), bcids.begin(),
1248  bcids.end());
1249  // Separator
1250  all_bcids.push_back(BoundaryInfo::invalid_id);
1251  }
1252 
1253  for (unsigned short e=0; e != n_edges; ++e)
1254  {
1255  std::vector<boundary_id_type> bcids;
1256 
1257  if (elem)
1258  {
1259  boundary_info.edge_boundary_ids(elem, e, bcids);
1260 
1261  // Ordering of boundary ids shouldn't matter
1262  std::sort(bcids.begin(), bcids.end());
1263  }
1264 
1265 // libmesh_assert(mesh.comm().semiverify
1266 // (elem ? &bcids : libmesh_nullptr));
1267 
1268  all_bcids.insert(all_bcids.end(), bcids.begin(),
1269  bcids.end());
1270  // Separator
1271  all_bcids.push_back(BoundaryInfo::invalid_id);
1272 
1273  if (elem)
1274  {
1275  boundary_info.raw_edge_boundary_ids(elem, e, bcids);
1276 
1277  // Ordering of boundary ids shouldn't matter
1278  std::sort(bcids.begin(), bcids.end());
1279 
1280  all_bcids.insert(all_bcids.end(), bcids.begin(),
1281  bcids.end());
1282  // Separator
1283  all_bcids.push_back(BoundaryInfo::invalid_id);
1284  }
1285 
1286 // libmesh_assert(mesh.comm().semiverify
1287 // (elem ? &bcids : libmesh_nullptr));
1288  }
1289 
1290  for (unsigned short s=0; s != n_sides; ++s)
1291  {
1292  std::vector<boundary_id_type> bcids;
1293 
1294  if (elem)
1295  {
1296  boundary_info.boundary_ids(elem, s, bcids);
1297 
1298  // Ordering of boundary ids shouldn't matter
1299  std::sort(bcids.begin(), bcids.end());
1300 
1301  all_bcids.insert(all_bcids.end(), bcids.begin(),
1302  bcids.end());
1303  // Separator
1304  all_bcids.push_back(BoundaryInfo::invalid_id);
1305  }
1306 
1307 // libmesh_assert(mesh.comm().semiverify
1308 // (elem ? &bcids : libmesh_nullptr));
1309 
1310  if (elem)
1311  {
1312  boundary_info.raw_boundary_ids(elem, s, bcids);
1313 
1314  // Ordering of boundary ids shouldn't matter
1315  std::sort(bcids.begin(), bcids.end());
1316 
1317  all_bcids.insert(all_bcids.end(), bcids.begin(),
1318  bcids.end());
1319  // Separator
1320  all_bcids.push_back(BoundaryInfo::invalid_id);
1321  }
1322 
1323 // libmesh_assert(mesh.comm().semiverify
1324 // (elem ? &bcids : libmesh_nullptr));
1325  }
1326 
1327  for (unsigned short sf=0; sf != 2; ++sf)
1328  {
1329  std::vector<boundary_id_type> bcids;
1330 
1331  if (elem)
1332  {
1333  boundary_info.shellface_boundary_ids(elem, sf, bcids);
1334 
1335  // Ordering of boundary ids shouldn't matter
1336  std::sort(bcids.begin(), bcids.end());
1337 
1338  all_bcids.insert(all_bcids.end(), bcids.begin(),
1339  bcids.end());
1340  // Separator
1341  all_bcids.push_back(BoundaryInfo::invalid_id);
1342  }
1343 
1344 // libmesh_assert(mesh.comm().semiverify
1345 // (elem ? &bcids : libmesh_nullptr));
1346 
1347  if (elem)
1348  {
1349  boundary_info.raw_shellface_boundary_ids(elem, sf, bcids);
1350 
1351  // Ordering of boundary ids shouldn't matter
1352  std::sort(bcids.begin(), bcids.end());
1353 
1354  all_bcids.insert(all_bcids.end(), bcids.begin(),
1355  bcids.end());
1356  // Separator
1357  all_bcids.push_back(BoundaryInfo::invalid_id);
1358  }
1359 
1360 // libmesh_assert(mesh.comm().semiverify
1361 // (elem ? &bcids : libmesh_nullptr));
1362  }
1363 
1365  (elem ? &all_bcids : libmesh_nullptr));
1366  }
1367 }
1368 
1369 void libmesh_assert_valid_dof_ids(const MeshBase & mesh, unsigned int sysnum)
1370 {
1371  LOG_SCOPE("libmesh_assert_valid_dof_ids()", "MeshTools");
1372 
1373  if (mesh.n_processors() == 1)
1374  return;
1375 
1376  libmesh_parallel_only(mesh.comm());
1377 
1378  dof_id_type pmax_elem_id = mesh.max_elem_id();
1379  mesh.comm().max(pmax_elem_id);
1380 
1381  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1382  assert_semiverify_dofobj(mesh.comm(),
1383  mesh.query_elem_ptr(i),
1384  sysnum);
1385 
1386  dof_id_type pmax_node_id = mesh.max_node_id();
1387  mesh.comm().max(pmax_node_id);
1388 
1389  for (dof_id_type i=0; i != pmax_node_id; ++i)
1390  assert_semiverify_dofobj(mesh.comm(),
1391  mesh.query_node_ptr(i),
1392  sysnum);
1393 }
1394 
1395 
1396 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1398 {
1399  LOG_SCOPE("libmesh_assert_valid_unique_ids()", "MeshTools");
1400 
1401  libmesh_parallel_only(mesh.comm());
1402 
1403  dof_id_type pmax_elem_id = mesh.max_elem_id();
1404  mesh.comm().max(pmax_elem_id);
1405 
1406  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1407  {
1408  const Elem * elem = mesh.query_elem_ptr(i);
1409  const unique_id_type unique_id = elem ? elem->unique_id() : 0;
1410  const unique_id_type * uid_ptr = elem ? &unique_id : libmesh_nullptr;
1411  libmesh_assert(mesh.comm().semiverify(uid_ptr));
1412  }
1413 
1414  dof_id_type pmax_node_id = mesh.max_node_id();
1415  mesh.comm().max(pmax_node_id);
1416 
1417  for (dof_id_type i=0; i != pmax_node_id; ++i)
1418  {
1419  const Node * node = mesh.query_node_ptr(i);
1420  const unique_id_type unique_id = node ? node->unique_id() : 0;
1421  const unique_id_type * uid_ptr = node ? &unique_id : libmesh_nullptr;
1422  libmesh_assert(mesh.comm().semiverify(uid_ptr));
1423  }
1424 }
1425 #endif
1426 
1427 template <>
1429 {
1430  LOG_SCOPE("libmesh_assert_topology_consistent_procids()", "MeshTools");
1431 
1432  // This parameter is not used when !LIBMESH_ENABLE_AMR
1434 
1435  // If we're adaptively refining, check processor ids for consistency
1436  // between parents and children.
1437 #ifdef LIBMESH_ENABLE_AMR
1438 
1439  // Ancestor elements we won't worry about, but subactive and active
1440  // elements ought to have parents with consistent processor ids
1441  for (const auto & elem : mesh.element_ptr_range())
1442  {
1443  libmesh_assert(elem);
1444 
1445  if (!elem->active() && !elem->subactive())
1446  continue;
1447 
1448  const Elem * parent = elem->parent();
1449 
1450  if (parent)
1451  {
1452  libmesh_assert(parent->has_children());
1453  processor_id_type parent_procid = parent->processor_id();
1454  bool matching_child_id = false;
1455  // If we've got a remote_elem then we don't know whether
1456  // it's responsible for the parent's processor id; all
1457  // we can do is assume it is and let its processor fail
1458  // an assert if there's something wrong.
1459  for (auto & child : parent->child_ref_range())
1460  if (&child == remote_elem ||
1461  child.processor_id() == parent_procid)
1462  matching_child_id = true;
1463  libmesh_assert(matching_child_id);
1464  }
1465  }
1466 #endif
1467 }
1468 
1469 
1470 
1471 template <>
1473 {
1474  LOG_SCOPE("libmesh_assert_parallel_consistent_procids()", "MeshTools");
1475 
1476  if (mesh.n_processors() == 1)
1477  return;
1478 
1479  libmesh_parallel_only(mesh.comm());
1480 
1481  // We want this test to be valid even when called even after nodes
1482  // have been added asynchronously but before they're renumbered
1483  dof_id_type parallel_max_elem_id = mesh.max_elem_id();
1484  mesh.comm().max(parallel_max_elem_id);
1485 
1486  // Check processor ids for consistency between processors
1487 
1488  for (dof_id_type i=0; i != parallel_max_elem_id; ++i)
1489  {
1490  const Elem * elem = mesh.query_elem_ptr(i);
1491 
1492  processor_id_type min_id =
1493  elem ? elem->processor_id() :
1495  mesh.comm().min(min_id);
1496 
1497  processor_id_type max_id =
1498  elem ? elem->processor_id() :
1500  mesh.comm().max(max_id);
1501 
1502  if (elem)
1503  {
1504  libmesh_assert_equal_to (min_id, elem->processor_id());
1505  libmesh_assert_equal_to (max_id, elem->processor_id());
1506  }
1507 
1508  if (min_id == mesh.processor_id())
1509  libmesh_assert(elem);
1510  }
1511 }
1512 
1513 
1514 
1515 template <>
1517 {
1518  LOG_SCOPE("libmesh_assert_topology_consistent_procids()", "MeshTools");
1519 
1520  if (mesh.n_processors() == 1)
1521  return;
1522 
1523  libmesh_parallel_only(mesh.comm());
1524 
1525  // We want this test to be valid even when called even after nodes
1526  // have been added asynchronously but before they're renumbered
1527  dof_id_type parallel_max_node_id = mesh.max_node_id();
1528  mesh.comm().max(parallel_max_node_id);
1529 
1530  std::vector<bool> node_touched_by_me(parallel_max_node_id, false);
1531 
1532  const MeshBase::const_element_iterator el_end =
1535  mesh.local_elements_begin(); el != el_end; ++el)
1536  {
1537  const Elem * elem = *el;
1538  libmesh_assert (elem);
1539 
1540  for (auto & node : elem->node_ref_range())
1541  {
1542  dof_id_type nodeid = node.id();
1543  node_touched_by_me[nodeid] = true;
1544  }
1545  }
1546  std::vector<bool> node_touched_by_anyone(node_touched_by_me);
1547  mesh.comm().max(node_touched_by_anyone);
1548 
1549  for (const auto & node : mesh.local_node_ptr_range())
1550  {
1551  libmesh_assert(node);
1552  dof_id_type nodeid = node->id();
1553  libmesh_assert(!node_touched_by_anyone[nodeid] ||
1554  node_touched_by_me[nodeid]);
1555  }
1556 }
1557 
1558 
1559 
1560 template <>
1562 {
1563  LOG_SCOPE("libmesh_assert_parallel_consistent_procids()", "MeshTools");
1564 
1565  if (mesh.n_processors() == 1)
1566  return;
1567 
1568  libmesh_parallel_only(mesh.comm());
1569 
1570  // We want this test to be valid even when called even after nodes
1571  // have been added asynchronously but before they're renumbered
1572  dof_id_type parallel_max_node_id = mesh.max_node_id();
1573  mesh.comm().max(parallel_max_node_id);
1574 
1575  std::vector<bool> node_touched_by_anyone(parallel_max_node_id, false);
1576 
1577  const MeshBase::const_element_iterator el_end =
1580  mesh.local_elements_begin(); el != el_end; ++el)
1581  {
1582  const Elem * elem = *el;
1583  libmesh_assert (elem);
1584 
1585  for (auto & node : elem->node_ref_range())
1586  {
1587  dof_id_type nodeid = node.id();
1588  node_touched_by_anyone[nodeid] = true;
1589  }
1590  }
1591  mesh.comm().max(node_touched_by_anyone);
1592 
1593  // Check processor ids for consistency between processors
1594  // on any node an element touches
1595  for (dof_id_type i=0; i != parallel_max_node_id; ++i)
1596  {
1597  if (!node_touched_by_anyone[i])
1598  continue;
1599 
1600  const Node * node = mesh.query_node_ptr(i);
1601 
1602  processor_id_type min_id =
1603  node ? node->processor_id() :
1605  mesh.comm().min(min_id);
1606 
1607  processor_id_type max_id =
1608  node ? node->processor_id() :
1610  mesh.comm().max(max_id);
1611 
1612  if (node)
1613  {
1614  libmesh_assert_equal_to (min_id, node->processor_id());
1615  libmesh_assert_equal_to (max_id, node->processor_id());
1616  }
1617 
1618  if (min_id == mesh.processor_id())
1619  libmesh_assert(node);
1620  }
1621 }
1622 
1623 
1624 
1625 } // namespace MeshTools
1626 
1627 
1628 
1629 #ifdef LIBMESH_ENABLE_AMR
1631 {
1632  LOG_SCOPE("libmesh_assert_valid_refinement_flags()", "MeshTools");
1633 
1634  libmesh_parallel_only(mesh.comm());
1635  if (mesh.n_processors() == 1)
1636  return;
1637 
1638  dof_id_type pmax_elem_id = mesh.max_elem_id();
1639  mesh.comm().max(pmax_elem_id);
1640 
1641  std::vector<unsigned char> my_elem_h_state(pmax_elem_id, 255);
1642  std::vector<unsigned char> my_elem_p_state(pmax_elem_id, 255);
1643 
1644  for (const auto & elem : mesh.element_ptr_range())
1645  {
1646  libmesh_assert (elem);
1647  dof_id_type elemid = elem->id();
1648 
1649  my_elem_h_state[elemid] =
1650  static_cast<unsigned char>(elem->refinement_flag());
1651 
1652  my_elem_p_state[elemid] =
1653  static_cast<unsigned char>(elem->p_refinement_flag());
1654  }
1655  std::vector<unsigned char> min_elem_h_state(my_elem_h_state);
1656  mesh.comm().min(min_elem_h_state);
1657 
1658  std::vector<unsigned char> min_elem_p_state(my_elem_p_state);
1659  mesh.comm().min(min_elem_p_state);
1660 
1661  for (dof_id_type i=0; i!= pmax_elem_id; ++i)
1662  {
1663  libmesh_assert(my_elem_h_state[i] == 255 ||
1664  my_elem_h_state[i] == min_elem_h_state[i]);
1665  libmesh_assert(my_elem_p_state[i] == 255 ||
1666  my_elem_p_state[i] == min_elem_p_state[i]);
1667  }
1668 }
1669 #else
1671 {
1672 }
1673 #endif // LIBMESH_ENABLE_AMR
1674 
1675 
1676 
1677 #ifdef LIBMESH_ENABLE_AMR
1679 {
1680  LOG_SCOPE("libmesh_assert_valid_refinement_tree()", "MeshTools");
1681 
1682  for (const auto & elem : mesh.element_ptr_range())
1683  {
1684  libmesh_assert(elem);
1685  if (elem->has_children())
1686  for (auto & child : elem->child_ref_range())
1687  if (&child != remote_elem)
1688  libmesh_assert_equal_to (child.parent(), elem);
1689  if (elem->active())
1690  {
1691  libmesh_assert(!elem->ancestor());
1692  libmesh_assert(!elem->subactive());
1693  }
1694  else if (elem->ancestor())
1695  {
1696  libmesh_assert(!elem->subactive());
1697  }
1698  else
1699  libmesh_assert(elem->subactive());
1700 
1701  if (elem->p_refinement_flag() == Elem::JUST_REFINED)
1702  libmesh_assert_greater(elem->p_level(), 0);
1703  }
1704 }
1705 #else
1707 {
1708 }
1709 #endif // LIBMESH_ENABLE_AMR
1710 
1711 
1712 
1714  bool assert_valid_remote_elems)
1715 {
1716  LOG_SCOPE("libmesh_assert_valid_neighbors()", "MeshTools");
1717 
1718  for (const auto & elem : mesh.element_ptr_range())
1719  {
1720  libmesh_assert (elem);
1721  elem->libmesh_assert_valid_neighbors();
1722  }
1723 
1724  if (mesh.n_processors() == 1)
1725  return;
1726 
1727  libmesh_parallel_only(mesh.comm());
1728 
1729  dof_id_type pmax_elem_id = mesh.max_elem_id();
1730  mesh.comm().max(pmax_elem_id);
1731 
1732  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1733  {
1734  const Elem * elem = mesh.query_elem_ptr(i);
1735 
1736  const unsigned int my_n_neigh = elem ? elem->n_neighbors() : 0;
1737  unsigned int n_neigh = my_n_neigh;
1738  mesh.comm().max(n_neigh);
1739  if (elem)
1740  libmesh_assert_equal_to (my_n_neigh, n_neigh);
1741 
1742  for (unsigned int n = 0; n != n_neigh; ++n)
1743  {
1744  dof_id_type my_neighbor = DofObject::invalid_id;
1745  dof_id_type * p_my_neighbor = libmesh_nullptr;
1746 
1747  // If we have a non-remote_elem neighbor link, then we can
1748  // verify it.
1749  if (elem && elem->neighbor_ptr(n) != remote_elem)
1750  {
1751  p_my_neighbor = &my_neighbor;
1752  if (elem->neighbor_ptr(n))
1753  my_neighbor = elem->neighbor_ptr(n)->id();
1754 
1755  // But wait - if we haven't set remote_elem links yet then
1756  // some NULL links on ghost elements might be
1757  // future-remote_elem links, so we can't verify those.
1758  if (!assert_valid_remote_elems &&
1759  !elem->neighbor_ptr(n) &&
1760  elem->processor_id() != mesh.processor_id())
1761  p_my_neighbor = libmesh_nullptr;
1762  }
1763  libmesh_assert(mesh.comm().semiverify(p_my_neighbor));
1764  }
1765  }
1766 }
1767 
1768 
1769 
1770 #endif // DEBUG
1771 
1772 
1773 
1774 // Functors for correct_node_proc_ids
1775 namespace {
1776 
1777 typedef std::unordered_map<dof_id_type, processor_id_type> proc_id_map_type;
1778 
1779 struct SyncProcIdsFromMap
1780 {
1781  typedef processor_id_type datum;
1782 
1783  SyncProcIdsFromMap(const proc_id_map_type & _map,
1784  MeshBase & _mesh) :
1785  new_proc_ids(_map), mesh(_mesh) {}
1786 
1787  const proc_id_map_type & new_proc_ids;
1788 
1790 
1791  // ------------------------------------------------------------
1792  void gather_data (const std::vector<dof_id_type> & ids,
1793  std::vector<datum> & data)
1794  {
1795  // Find the new processor id of each requested node
1796  data.resize(ids.size());
1797 
1798  for (std::size_t i=0; i != ids.size(); ++i)
1799  {
1800  const dof_id_type id = ids[i];
1801  const proc_id_map_type::const_iterator it = new_proc_ids.find(id);
1802 
1803  // Return the node's new processor id if it has one, or its
1804  // old processor id if not.
1805  if (it != new_proc_ids.end())
1806  data[i] = it->second;
1807  else
1808  {
1809  // We'd better find every node we're asked for
1810  const Node & node = mesh.node_ref(id);
1811  data[i] = node.processor_id();
1812  }
1813  }
1814  }
1815 
1816  // ------------------------------------------------------------
1817  void act_on_data (const std::vector<dof_id_type> & ids,
1818  std::vector<datum> proc_ids)
1819  {
1820  // Set the node processor ids we've now been informed of
1821  for (std::size_t i=0; i != ids.size(); ++i)
1822  {
1823  Node & node = mesh.node_ref(ids[i]);
1824  node.processor_id() = proc_ids[i];
1825  }
1826  }
1827 };
1828 }
1829 
1830 
1831 
1833 {
1834  // This function must be run on all processors at once
1835  libmesh_parallel_only(mesh.comm());
1836 
1837  // Fix all nodes' processor ids. Coarsening may have left us with
1838  // nodes which are no longer touched by any elements of the same
1839  // processor id, and for DofMap to work we need to fix that.
1840 
1841  // This is harder now that libMesh no longer requires a distributed
1842  // mesh to ghost all nodal neighbors: it is possible for two active
1843  // elements on two different processors to share the same node in
1844  // such a way that neither processor knows the others' element
1845  // exists!
1846 
1847  // We require all processors to agree on nodal processor ids before
1848  // going into this algorithm.
1849 #ifdef DEBUG
1851 #endif
1852 
1853  // We build up a set of compatible processor ids for each node
1854  proc_id_map_type new_proc_ids;
1855 
1856  for (auto & elem : mesh.active_element_ptr_range())
1857  {
1858  processor_id_type pid = elem->processor_id();
1859 
1860  for (auto & node : elem->node_ref_range())
1861  {
1862  const dof_id_type id = node.id();
1863  const proc_id_map_type::iterator it = new_proc_ids.find(id);
1864  if (it == new_proc_ids.end())
1865  new_proc_ids.insert(std::make_pair(id,pid));
1866  else
1867  it->second = std::min(it->second, pid);
1868  }
1869  }
1870 
1871  // Sort the new pids to push to each processor
1872  std::vector<std::vector<std::pair<dof_id_type, processor_id_type>>>
1873  ids_to_push(mesh.n_processors());
1874 
1875  for (const auto & node : mesh.node_ptr_range())
1876  {
1877  const dof_id_type id = node->id();
1878  const proc_id_map_type::iterator it = new_proc_ids.find(id);
1879  if (it == new_proc_ids.end())
1880  continue;
1881  const processor_id_type pid = it->second;
1882  ids_to_push[node->processor_id()].push_back(std::make_pair(id, pid));
1883  }
1884 
1885  // Push using non-blocking I/O
1886  std::vector<Parallel::Request> push_requests(mesh.n_processors());
1887 
1888  for (processor_id_type p=1; p != mesh.n_processors(); ++p)
1889  {
1890  const processor_id_type procup =
1891  cast_int<processor_id_type>
1892  ((mesh.comm().rank() + p) % mesh.comm().size());
1893 
1894  mesh.comm().send(procup, ids_to_push[procup], push_requests[procup]);
1895  }
1896 
1897  for (processor_id_type p=0; p != mesh.n_processors(); ++p)
1898  {
1899  const processor_id_type procdown =
1900  cast_int<processor_id_type>
1901  ((mesh.comm().size() + mesh.comm().rank() - p) %
1902  mesh.comm().size());
1903 
1904  std::vector<std::pair<dof_id_type, processor_id_type>>
1905  ids_to_pull;
1906 
1907  if (p)
1908  mesh.comm().receive(procdown, ids_to_pull);
1909  else
1910  ids_to_pull.swap(ids_to_push[procdown]);
1911 
1912  std::vector<std::pair<dof_id_type, processor_id_type>>::iterator
1913  pulled_ids_it = ids_to_pull.begin(),
1914  pulled_ids_end = ids_to_pull.end();
1915  for (; pulled_ids_it != pulled_ids_end; ++pulled_ids_it)
1916  {
1917  const dof_id_type id = pulled_ids_it->first;
1918  const processor_id_type pid = pulled_ids_it->second;
1919  const proc_id_map_type::iterator it = new_proc_ids.find(id);
1920  if (it == new_proc_ids.end())
1921  new_proc_ids.insert(std::make_pair(id,pid));
1922  else
1923  it->second = std::min(it->second, pid);
1924  }
1925  }
1926 
1927  // Now new_proc_ids is correct for every node we used to own. Let's
1928  // ask every other processor about the nodes they used to own. But
1929  // first we'll need to keep track of which nodes we used to own,
1930  // lest we get them confused with nodes we newly own.
1931  std::unordered_set<Node *> ex_local_nodes;
1932  for (auto & node : mesh.local_node_ptr_range())
1933  {
1934  const proc_id_map_type::iterator it = new_proc_ids.find(node->id());
1935  if (it != new_proc_ids.end() && it->second != mesh.processor_id())
1936  ex_local_nodes.insert(node);
1937  }
1938 
1939  // Let's finish with previous I/O before we start more.
1940  Parallel::wait(push_requests);
1941 
1942  SyncProcIdsFromMap sync(new_proc_ids, mesh);
1944  (mesh.comm(), mesh.nodes_begin(), mesh.nodes_end(), sync);
1945 
1946  // And finally let's update the nodes we used to own.
1947  for (std::unordered_set<Node *>::iterator
1948  n_it = ex_local_nodes.begin(),
1949  n_end = ex_local_nodes.end();
1950  n_it != n_end; ++n_it)
1951  {
1952  Node * node = *n_it;
1953  const dof_id_type id = node->id();
1954  const proc_id_map_type::iterator it = new_proc_ids.find(id);
1955  libmesh_assert(it != new_proc_ids.end());
1956  node->processor_id() = it->second;
1957  }
1958 
1959  // We should still have consistent nodal processor ids coming out of
1960  // this algorithm.
1961 #ifdef DEBUG
1962  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
1963 #endif
1964 }
1965 
1966 
1967 
1969 {
1971 }
1972 
1973 } // namespace libMesh
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const =0
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
unsigned int n_active_local_levels(const MeshBase &mesh)
Definition: mesh_tools.C:555
bool has_children() const
Definition: elem.h:2295
void libmesh_assert_topology_consistent_procids< Node >(const MeshBase &mesh)
Definition: mesh_tools.C:1516
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:117
bool verify(const T &r) const
Verify that a local variable has the same value on all processors.
Status wait(Request &r)
Wait for a non-blocking send or receive to finish.
Definition: parallel.h:565
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:510
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:664
void assign_global_indices(MeshBase &) const
This method assigns globally unique, partition-agnostic indices to the nodes and elements in the mesh...
A Node is like a Point, but with more information.
Definition: node.h:52
Encapsulates the MPI_Comm object.
Definition: parallel.h:657
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:1133
virtual bool is_serial() const
Definition: mesh_base.h:140
bool active() const
Definition: elem.h:2257
bool semiverify(const T *r) const
Verify that a local pointer points to the same value on all processors where it is not NULL...
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value.
Definition: libmesh.h:184
virtual SimpleRange< node_iterator > local_node_ptr_range()=0
virtual node_iterator pid_nodes_end(processor_id_type proc_id)=0
virtual ElemType type() const =0
This class defines a sphere.
Definition: sphere.h:72
void libmesh_assert_valid_remote_elems(const MeshBase &mesh)
A function for verifying that active local elements&#39; neighbors are never remote elements.
Definition: mesh_tools.C:1037
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:1832
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:745
unsigned int size() const
Definition: parallel.h:726
void max(T &r) const
Take a local variable and replace it with the maximum of it&#39;s values on all processors.
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:656
libMesh::BoundingBox create_bounding_box(const MeshBase &mesh)
The same functionality as the deprecated MeshTools::bounding_box().
Definition: mesh_tools.C:329
The definition of the const_element_iterator struct.
Definition: mesh_base.h:1494
void min(T &r) const
Take a local variable and replace it with the minimum of it&#39;s values on all processors.
virtual unsigned int n_edges() const =0
Sphere processor_bounding_sphere(const MeshBase &mesh, const processor_id_type pid)
Definition: mesh_tools.C:445
MPI_Comm communicator
Communicator object for talking with subsets of processors.
Definition: parallel.h:181
virtual element_iterator local_elements_begin()=0
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:420
Dummy "splitting object" used to distinguish splitting constructors from copy constructors.
Definition: threads_none.h:63
ElemType
Defines an enum for geometric element types.
virtual element_iterator unpartitioned_elements_begin()=0
Iterate over unpartitioned elements in the Mesh.
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:1678
const Elem * parent() const
Definition: elem.h:2346
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
Definition: elem.h:2181
unsigned short int side
Definition: xdr_io.C:49
processor_id_type n_processors() const
virtual dof_id_type max_node_id() const =0
const Elem * interior_parent() const
Definition: elem.C:951
This is the base class from which all geometric element types are derived.
Definition: elem.h:89
unsigned int n_neighbors() const
Definition: elem.h:613
uint8_t processor_id_type
Definition: id_types.h:99
const class libmesh_nullptr_t libmesh_nullptr
unsigned int n_local_levels(const MeshBase &mesh)
Definition: mesh_tools.C:588
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:810
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:257
IterBase * end
Also have a polymorphic pointer to the end object, this prevents iterating past the end...
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
The StoredRange class defines a contiguous, divisible set of objects.
Definition: stored_range.h:52
Backwards compatibility with forward declarations.
Definition: mesh_tools.h:60
const unsigned int n_vars
Definition: tecplot_io.C:68
The libMesh namespace provides an interface to certain functionality in the library.
MeshBase & mesh
Definition: mesh_tools.C:1789
const_iterator begin() const
Beginning of the range.
Definition: stored_range.h:261
virtual element_iterator active_local_subdomain_elements_end(subdomain_id_type subdomain_id)=0
long double max(long double a, double b)
Real distance(const Point &p)
dof_id_type n_elem_of_type(const MeshBase &mesh, const ElemType type)
Definition: mesh_tools.C:522
libMesh::BoundingBox create_local_bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:394
This is the MeshBase class.
Definition: mesh_base.h:68
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
Definition: elem.h:1699
unsigned int paranoid_n_levels(const MeshBase &mesh)
Definition: mesh_tools.C:631
libmesh_assert(j)
std::unique_ptr< T > UniquePtr
Definition: auto_ptr.h:46
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:963
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:1369
virtual unsigned int n_nodes() const =0
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:1967
virtual node_iterator nodes_begin()=0
Iterate over all the nodes in the Mesh.
virtual element_iterator elements_begin()=0
Iterate over all the elements in the Mesh.
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
BoundingBox bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:316
virtual dof_id_type max_elem_id() const =0
const dof_id_type n_nodes
Definition: tecplot_io.C:67
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:1013
virtual element_iterator active_local_subdomain_elements_begin(subdomain_id_type subdomain_id)=0
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:699
static const boundary_id_type invalid_id
Number used for internal use.
This is the MeshCommunication class.
virtual SimpleRange< element_iterator > element_ptr_range()=0
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:1874
virtual node_iterator local_nodes_end()=0
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:335
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:1070
dof_id_type weight(const MeshBase &mesh, const processor_id_type pid)
Definition: mesh_tools.C:245
virtual element_iterator type_elements_end(ElemType type)=0
virtual element_iterator elements_end()=0
unsigned int n_levels(const MeshBase &mesh)
Definition: mesh_tools.C:603
virtual SimpleRange< node_iterator > node_ptr_range()=0
virtual const Node * query_node_ptr(const dof_id_type i) const =0
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:56
virtual element_iterator local_elements_end()=0
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:324
void libmesh_assert_valid_boundary_ids(const MeshBase &mesh)
A function for verifying that boundary condition ids match across processors.
Definition: mesh_tools.C:1194
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:1113
void libmesh_assert_parallel_consistent_procids< Elem >(const MeshBase &mesh)
Definition: mesh_tools.C:1472
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.
virtual unsigned int n_sides() const =0
Sphere subdomain_bounding_sphere(const MeshBase &mesh, const subdomain_id_type sid)
Definition: mesh_tools.C:496
const proc_id_map_type & new_proc_ids
Definition: mesh_tools.C:1787
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.
const_iterator end() const
End of the range.
Definition: stored_range.h:266
void globally_renumber_nodes_and_elements(MeshBase &)
There is no reason for a user to ever call this function.
Definition: mesh_tools.C:1968
BoundingBox processor_bounding_box(const MeshBase &mesh, const processor_id_type pid)
Definition: mesh_tools.C:409
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:873
dof_id_type total_weight(const MeshBase &mesh)
Definition: mesh_tools.C:222
void libmesh_assert_parallel_consistent_procids< Node >(const MeshBase &mesh)
Definition: mesh_tools.C:1561
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:472
std::string enum_to_string(const T e)
Sphere bounding_sphere(const MeshBase &mesh)
Definition: mesh_tools.C:381
std::vector< object_type >::const_iterator const_iterator
Allows an StoredRange to behave like an STL container.
Definition: stored_range.h:58
void libmesh_ignore(const T &)
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2047
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
virtual element_iterator pid_elements_begin(processor_id_type proc_id)=0
Iterate over all elements with a specified processor id.
virtual node_iterator local_nodes_begin()=0
Iterate over local nodes (nodes whose processor_id() matches the current processor).
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual node_iterator nodes_end()=0
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:1169
virtual element_iterator type_elements_begin(ElemType type)=0
Iterate over all elements with a specified geometric type.
const Parallel::Communicator & comm() const
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:645
The definition of the const_node_iterator struct.
Definition: mesh_base.h:1548
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
Definition: dof_object.h:51
unsigned int level() const
Definition: elem.h:2388
dof_id_type n_active_elem_of_type(const MeshBase &mesh, const ElemType type)
Definition: mesh_tools.C:531
void parallel_reduce(const Range &range, Body &body)
Execute the provided reduction operation in parallel on the specified range.
Definition: threads_none.h:101
virtual element_iterator unpartitioned_elements_end()=0
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.
unsigned int rank() const
Definition: parallel.h:724
const Elem * top_parent() const
Definition: elem.h:2370
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
Definition: elem.h:2855
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1831
unsigned int local_node(const dof_id_type i) const
Definition: elem.h:1854
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:1713
libMesh::BoundingBox create_nodal_bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:354
IterBase * data
Ideally this private member data should have protected access.
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:780
void libmesh_assert_valid_unique_ids(const MeshBase &mesh)
A function for verifying that unique ids match across processors.
Definition: mesh_tools.C:1397
dof_id_type id() const
Definition: dof_object.h:632
unsigned int n_systems() const
Definition: dof_object.h:726
virtual element_iterator active_type_elements_end(ElemType type)=0
virtual dof_id_type n_nodes() const =0
virtual dof_id_type n_elem() const =0
unique_id_type unique_id() const
Definition: dof_object.h:649
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:420
void sum(T &r) const
Take a local variable and replace it with the sum of it&#39;s values on all processors.
unsigned int n_p_levels(const MeshBase &mesh)
Definition: mesh_tools.C:672
virtual node_iterator pid_nodes_begin(processor_id_type proc_id)=0
Iterate over nodes with processor_id() == proc_id.
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:989
long double min(long double a, double b)
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
uint8_t unique_id_type
Definition: id_types.h:79
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:538
void libmesh_assert_topology_consistent_procids< Elem >(const MeshBase &mesh)
Definition: mesh_tools.C:1428
virtual element_iterator active_type_elements_begin(ElemType type)=0
void find_boundary_nodes(const MeshBase &mesh, std::vector< bool > &on_boundary)
Calling this function on a 2D mesh will convert all the elements to triangles.
Definition: mesh_tools.C:290
BoundingBox subdomain_bounding_box(const MeshBase &mesh, const subdomain_id_type sid)
Definition: mesh_tools.C:461
virtual BoundingBox loose_bounding_box() const
Definition: elem.C:2997
processor_id_type processor_id() const
uint8_t dof_id_type
Definition: id_types.h:64
unsigned int n_active_levels(const MeshBase &mesh)
Definition: mesh_tools.C:567
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:1090
processor_id_type processor_id() const
Definition: dof_object.h:694
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:1630
const RemoteElem * remote_elem
Definition: remote_elem.C:57
virtual element_iterator pid_elements_end(processor_id_type proc_id)=0