libMesh
distributed_mesh.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/distributed_mesh.h"
22 
23 // libMesh includes
24 #include "libmesh/boundary_info.h"
25 #include "libmesh/elem.h"
26 #include "libmesh/libmesh_logging.h"
27 #include "libmesh/mesh_communication.h"
28 #include "libmesh/parmetis_partitioner.h"
29 
30 // TIMPI includes
32 #include "timpi/parallel_sync.h"
33 
34 
35 namespace libMesh
36 {
37 
38 // ------------------------------------------------------------
39 // DistributedMesh class member functions
40 DistributedMesh::DistributedMesh (const Parallel::Communicator & comm_in,
41  unsigned char d) :
42  UnstructuredMesh (comm_in,d), _is_serial(true),
43  _is_serial_on_proc_0(true),
44  _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0),
45  _next_free_local_node_id(this->processor_id()),
46  _next_free_local_elem_id(this->processor_id()),
47  _next_free_unpartitioned_node_id(this->n_processors()),
48  _next_free_unpartitioned_elem_id(this->n_processors())
49 #ifdef LIBMESH_ENABLE_UNIQUE_ID
50  , _next_unpartitioned_unique_id(this->n_processors())
51 #endif
52 {
53 #ifdef LIBMESH_ENABLE_UNIQUE_ID
54  _next_unique_id = this->processor_id();
55 #endif
56 
57  // FIXME: give parmetis the communicator!
58  _partitioner = libmesh_make_unique<ParmetisPartitioner>();
59 }
60 
61 
62 
64 {
65  this->clear(); // Free nodes and elements
66 }
67 
68 
69 // This might be specialized later, but right now it's just here to
70 // make sure the compiler doesn't give us a default (non-deep) copy
71 // constructor instead.
73  UnstructuredMesh (other_mesh), _is_serial(other_mesh._is_serial),
74  _is_serial_on_proc_0(other_mesh._is_serial_on_proc_0),
75  _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0),
76  _next_free_local_node_id(this->processor_id()),
77  _next_free_local_elem_id(this->processor_id()),
78  _next_free_unpartitioned_node_id(this->n_processors()),
79  _next_free_unpartitioned_elem_id(this->n_processors())
80 {
81  this->copy_nodes_and_elements(other_mesh, true);
82  _n_nodes = other_mesh.n_nodes();
83  _n_elem = other_mesh.n_elem();
84  _max_node_id = other_mesh.max_node_id();
85  _max_elem_id = other_mesh.max_elem_id();
87  other_mesh._next_free_local_node_id;
89  other_mesh._next_free_local_elem_id;
94 #ifdef LIBMESH_ENABLE_UNIQUE_ID
96  other_mesh._next_unique_id;
99 #endif
100 
101  auto & this_boundary_info = this->get_boundary_info();
102  const auto & other_boundary_info = other_mesh.get_boundary_info();
103 
104  this_boundary_info = other_boundary_info;
105 
106  this->set_subdomain_name_map() = other_mesh.get_subdomain_name_map();
107 
108  // Use the first BoundaryInfo object to build the list of side boundary ids
109  std::vector<boundary_id_type> side_boundaries;
110  other_boundary_info.build_side_boundary_ids(side_boundaries);
111 
112  // Assign those boundary ids in our BoundaryInfo object
113  for (const auto & side_bnd_id : side_boundaries)
114  this_boundary_info.sideset_name(side_bnd_id) =
115  other_boundary_info.get_sideset_name(side_bnd_id);
116 
117  // Do the same thing for node boundary ids
118  std::vector<boundary_id_type> node_boundaries;
119  other_boundary_info.build_node_boundary_ids(node_boundaries);
120 
121  for (const auto & node_bnd_id : node_boundaries)
122  this_boundary_info.nodeset_name(node_bnd_id) =
123  other_boundary_info.get_nodeset_name(node_bnd_id);
124 
125  // Need to copy extra_ghost_elems
126  for (auto & elem : other_mesh._extra_ghost_elems)
127  _extra_ghost_elems.insert(this->elem_ptr(elem->id()));
128 }
129 
130 
131 
133  UnstructuredMesh (other_mesh), _is_serial(other_mesh.is_serial()),
134  _is_serial_on_proc_0(other_mesh.is_serial()),
135  _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0),
136  _next_free_local_node_id(this->processor_id()),
137  _next_free_local_elem_id(this->processor_id()),
138  _next_free_unpartitioned_node_id(this->n_processors()),
139  _next_free_unpartitioned_elem_id(this->n_processors())
140 {
141  this->copy_nodes_and_elements(other_mesh, true);
142 
143  auto & this_boundary_info = this->get_boundary_info();
144  const auto & other_boundary_info = other_mesh.get_boundary_info();
145 
146  this_boundary_info = other_boundary_info;
147 
148  this->set_subdomain_name_map() = other_mesh.get_subdomain_name_map();
149 
150  // Use the first BoundaryInfo object to build the list of side boundary ids
151  std::vector<boundary_id_type> side_boundaries;
152  other_boundary_info.build_side_boundary_ids(side_boundaries);
153 
154  // Assign those boundary ids in our BoundaryInfo object
155  for (const auto & side_bnd_id : side_boundaries)
156  this_boundary_info.sideset_name(side_bnd_id) =
157  other_boundary_info.get_sideset_name(side_bnd_id);
158 
159  // Do the same thing for node boundary ids
160  std::vector<boundary_id_type> node_boundaries;
161  other_boundary_info.build_node_boundary_ids(node_boundaries);
162 
163  for (const auto & node_bnd_id : node_boundaries)
164  this_boundary_info.nodeset_name(node_bnd_id) =
165  other_boundary_info.get_nodeset_name(node_bnd_id);
166 
167 #ifdef LIBMESH_ENABLE_UNIQUE_ID
169 #endif
171 }
172 
173 
174 // We use cached values for these so they can be called
175 // from one processor without bothering the rest, but
176 // we may need to update those caches before doing a full
177 // renumbering
179 {
180  // This function must be run on all processors at once
181  parallel_object_only();
182 
183  _n_elem = this->parallel_n_elem();
184  _n_nodes = this->parallel_n_nodes();
187 
190  ((_max_elem_id-1) / (this->n_processors() + 1) + 1) *
191  (this->n_processors() + 1) + this->n_processors();
194  ((_max_elem_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
195  (this->n_processors() + 1) + this->processor_id();
196 
199  ((_max_node_id-1) / (this->n_processors() + 1) + 1) *
200  (this->n_processors() + 1) + this->n_processors();
203  ((_max_node_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
204  (this->n_processors() + 1) + this->processor_id();
205 
206 #ifdef LIBMESH_ENABLE_UNIQUE_ID
209  ((_next_unique_id-1) / (this->n_processors() + 1) + 1) *
210  (this->n_processors() + 1) + this->n_processors();
212  ((_next_unique_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
213  (this->n_processors() + 1) + this->processor_id();
214 #endif
215 }
216 
217 
218 // Or in debug mode we may want to test the uncached values without
219 // changing the cache
221 {
222  // This function must be run on all processors at once
223  parallel_object_only();
224 
225  dof_id_type n_local = this->n_local_elem();
226  this->comm().sum(n_local);
227  n_local += this->n_unpartitioned_elem();
228  return n_local;
229 }
230 
231 
232 
234 {
235  // This function must be run on all processors at once
236  parallel_object_only();
237 
238  dof_id_type max_local = 0;
239 
241  rit = _elements.rbegin();
242 
244  rend = _elements.rend();
245 
246  // Look for the maximum element id. Search backwards through
247  // elements so we can break out early. Beware of nullptr entries that
248  // haven't yet been cleared from _elements.
249  for (; rit != rend; ++rit)
250  if (rit->second)
251  {
252  libmesh_assert_equal_to(rit->second->id(), rit->first);
253  max_local = rit->first + 1;
254  break;
255  }
256 
257  this->comm().max(max_local);
258  return max_local;
259 }
260 
261 
262 
263 #ifdef LIBMESH_ENABLE_UNIQUE_ID
265 {
266  // This function must be run on all processors at once
267  parallel_object_only();
268 
269  unique_id_type max_local = std::max(_next_unique_id,
271  this->comm().max(max_local);
272  return max_local;
273 }
274 #endif
275 
276 
277 
279 {
280  // This function must be run on all processors at once
281  parallel_object_only();
282 
283  dof_id_type n_local = this->n_local_nodes();
284  this->comm().sum(n_local);
285  n_local += this->n_unpartitioned_nodes();
286  return n_local;
287 }
288 
289 
290 
292 {
293  // This function must be run on all processors at once
294  parallel_object_only();
295 
296  dof_id_type max_local = 0;
297 
299  rit = _nodes.rbegin();
300 
302  rend = _nodes.rend();
303 
304  // Look for the maximum element id. Search backwards through
305  // elements so we can break out early. Beware of nullptr entries that
306  // haven't yet been cleared from _elements.
307  for (; rit != rend; ++rit)
308  if (rit->second)
309  {
310  libmesh_assert_equal_to(rit->second->id(), rit->first);
311  max_local = rit->first + 1;
312  break;
313  }
314 
315  this->comm().max(max_local);
316  return max_local;
317 }
318 
319 
320 
321 const Point & DistributedMesh::point (const dof_id_type i) const
322 {
323  return this->node_ref(i);
324 }
325 
326 
327 
329 {
331  libmesh_assert_equal_to (_nodes[i]->id(), i);
332 
333  return _nodes[i];
334 }
335 
336 
337 
338 
340 {
342  libmesh_assert_equal_to (_nodes[i]->id(), i);
343 
344  return _nodes[i];
345 }
346 
347 
348 
349 
351 {
352  std::map<dof_id_type, Node *>::const_iterator it = _nodes.find(i);
353  if (it != _nodes.end().it)
354  {
355  const Node * n = it->second;
356  libmesh_assert (!n || n->id() == i);
357  return n;
358  }
359 
360  return nullptr;
361 }
362 
363 
364 
365 
367 {
368  std::map<dof_id_type, Node *>::const_iterator it = _nodes.find(i);
369  if (it != _nodes.end().it)
370  {
371  Node * n = it->second;
372  libmesh_assert (!n || n->id() == i);
373  return n;
374  }
375 
376  return nullptr;
377 }
378 
379 
380 
381 
383 {
385  libmesh_assert_equal_to (_elements[i]->id(), i);
386 
387  return _elements[i];
388 }
389 
390 
391 
392 
394 {
396  libmesh_assert_equal_to (_elements[i]->id(), i);
397 
398  return _elements[i];
399 }
400 
401 
402 
403 
405 {
406  std::map<dof_id_type, Elem *>::const_iterator it = _elements.find(i);
407  if (it != _elements.end().it)
408  {
409  const Elem * e = it->second;
410  libmesh_assert (!e || e->id() == i);
411  return e;
412  }
413 
414  return nullptr;
415 }
416 
417 
418 
419 
421 {
422  std::map<dof_id_type, Elem *>::const_iterator it = _elements.find(i);
423  if (it != _elements.end().it)
424  {
425  Elem * e = _elements[i];
426  libmesh_assert (!e || e->id() == i);
427  return e;
428  }
429 
430  return nullptr;
431 }
432 
433 
434 
435 
437 {
438  // Don't try to add nullptrs!
439  libmesh_assert(e);
440 
441  // Trying to add an existing element is a no-op
442  if (e->valid_id() && _elements[e->id()] == e)
443  return e;
444 
445  const processor_id_type elem_procid = e->processor_id();
446 
447  if (!e->valid_id())
448  {
449  // We should only be creating new ids past the end of the range
450  // of existing ids
451  libmesh_assert_greater_equal(_next_free_unpartitioned_elem_id,
452  _max_elem_id);
453  libmesh_assert_greater_equal(_next_free_local_elem_id, _max_elem_id);
454 
455  // Use the unpartitioned ids for unpartitioned elems, and
456  // temporarily for ghost elems
458  if (elem_procid == this->processor_id())
459  next_id = &_next_free_local_elem_id;
460  e->set_id (*next_id);
461  }
462 
463  {
464  // Advance next_ids up high enough that each is pointing to an
465  // unused id and any subsequent increments will still point us
466  // to unused ids
467  _max_elem_id = std::max(_max_elem_id,
468  static_cast<dof_id_type>(e->id()+1));
469 
472  ((_max_elem_id-1) / (this->n_processors() + 1) + 1) *
473  (this->n_processors() + 1) + this->n_processors();
476  ((_max_elem_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
477  (this->n_processors() + 1) + this->processor_id();
478 
479 #ifndef NDEBUG
480  // We need a const mapvector so we don't inadvertently create
481  // nullptr entries when testing for non-nullptr ones
482  const mapvector<Elem *, dof_id_type> & const_elements = _elements;
483 #endif
485  libmesh_assert(!const_elements[_next_free_local_elem_id]);
486  }
487 
488  // Don't try to overwrite existing elems
489  libmesh_assert (!_elements[e->id()]);
490 
491  _elements[e->id()] = e;
492 
493  // Try to make the cached elem data more accurate
494  if (elem_procid == this->processor_id() ||
495  elem_procid == DofObject::invalid_processor_id)
496  _n_elem++;
497 
498 #ifdef LIBMESH_ENABLE_UNIQUE_ID
499  if (!e->valid_unique_id())
500  {
501  if (processor_id() == e->processor_id())
502  {
504  _next_unique_id += this->n_processors() + 1;
505  }
506  else
507  {
510  }
511  }
512 #endif
513 
514  // Unpartitioned elems should be added on every processor
515  // And shouldn't be added in the same batch as ghost elems
516  // But we might be just adding on processor 0 to
517  // broadcast later
518  // #ifdef DEBUG
519  // if (elem_procid == DofObject::invalid_processor_id)
520  // {
521  // dof_id_type elem_id = e->id();
522  // this->comm().max(elem_id);
523  // libmesh_assert_equal_to (elem_id, e->id());
524  // }
525  // #endif
526 
527  // Make sure any new element is given space for any extra integers
528  // we've requested
530 
531  // And set mapping type and data on any new element
534 
535  return e;
536 }
537 
538 
539 
541 {
542  if (_elements[e->id()])
543  this->delete_elem(_elements[e->id()]);
544 
545 #ifdef LIBMESH_ENABLE_UNIQUE_ID
546  if (!e->valid_unique_id())
547  {
548  if (processor_id() == e->processor_id())
549  {
551  _next_unique_id += this->n_processors() + 1;
552  }
553  else
554  {
557  }
558  }
559 #endif
560 
561  // Try to make the cached elem data more accurate
562  processor_id_type elem_procid = e->processor_id();
563  if (elem_procid == this->processor_id() ||
564  elem_procid == DofObject::invalid_processor_id)
565  _n_elem++;
566 
567  _elements[e->id()] = e;
568 
569  // Make sure any new element is given space for any extra integers
570  // we've requested
572 
573  // And set mapping type and data on any new element
576 
577  return e;
578 }
579 
580 
581 
583 {
584  libmesh_assert (e);
585 
586  // Try to make the cached elem data more accurate
587  processor_id_type elem_procid = e->processor_id();
588  if (elem_procid == this->processor_id() ||
589  elem_procid == DofObject::invalid_processor_id)
590  _n_elem--;
591 
592  // Delete the element from the BoundaryInfo object
593  this->get_boundary_info().remove(e);
594 
595  // But not yet from the container; we might invalidate
596  // an iterator that way!
597 
598  //_elements.erase(e->id());
599 
600  // Instead, we set it to nullptr for now
601 
602  _elements[e->id()] = nullptr;
603 
604  // delete the element
605  delete e;
606 }
607 
608 
609 
611  const dof_id_type new_id)
612 {
613  Elem * el = _elements[old_id];
614  libmesh_assert (el);
615  libmesh_assert_equal_to (el->id(), old_id);
616 
617  el->set_id(new_id);
618  libmesh_assert (!_elements[new_id]);
619  _elements[new_id] = el;
620  _elements.erase(old_id);
621 }
622 
623 
624 
626  const dof_id_type id,
627  const processor_id_type proc_id)
628 {
629  auto n_it = _nodes.find(id);
630  if (n_it != _nodes.end().it)
631  {
632  Node * n = n_it->second;
633  libmesh_assert (n);
634  libmesh_assert_equal_to (n->id(), id);
635 
636  *n = p;
637  n->processor_id() = proc_id;
638 
639  return n;
640  }
641 
642  Node * n = Node::build(p, id).release();
643  n->processor_id() = proc_id;
644 
645  return DistributedMesh::add_node(n);
646 }
647 
648 
650 {
651  // This had better be a node in our mesh
652  libmesh_assert(_nodes[n.id()] == &n);
653 
654  _nodes[n.id()] = nullptr;
655 
657  n.processor_id() = this->processor_id();
658 
659  this->add_node(&n);
660 }
661 
662 
664 {
665  // Don't try to add nullptrs!
666  libmesh_assert(n);
667 
668  // Trying to add an existing node is a no-op
669  if (n->valid_id() && _nodes[n->id()] == n)
670  return n;
671 
672  const processor_id_type node_procid = n->processor_id();
673 
674  if (!n->valid_id())
675  {
676  // We should only be creating new ids past the end of the range
677  // of existing ids
678  libmesh_assert_greater_equal(_next_free_unpartitioned_node_id,
679  _max_node_id);
680  libmesh_assert_greater_equal(_next_free_local_node_id, _max_node_id);
681 
682  // Use the unpartitioned ids for unpartitioned nodes,
683  // and temporarily for ghost nodes
685  if (node_procid == this->processor_id())
686  next_id = &_next_free_local_node_id;
687  n->set_id (*next_id);
688  }
689 
690  {
691  // Advance next_ids up high enough that each is pointing to an
692  // unused id and any subsequent increments will still point us
693  // to unused ids
694  _max_node_id = std::max(_max_node_id,
695  static_cast<dof_id_type>(n->id()+1));
696 
699  ((_max_node_id-1) / (this->n_processors() + 1) + 1) *
700  (this->n_processors() + 1) + this->n_processors();
703  ((_max_node_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
704  (this->n_processors() + 1) + this->processor_id();
705 
706 #ifndef NDEBUG
707  // We need a const mapvector so we don't inadvertently create
708  // nullptr entries when testing for non-nullptr ones
709  const mapvector<Node *,dof_id_type> & const_nodes = _nodes;
710 #endif
713  }
714 
715  // Don't try to overwrite existing nodes
716  libmesh_assert (!_nodes[n->id()]);
717 
718  _nodes[n->id()] = n;
719 
720  // Try to make the cached node data more accurate
721  if (node_procid == this->processor_id() ||
722  node_procid == DofObject::invalid_processor_id)
723  _n_nodes++;
724 
725 #ifdef LIBMESH_ENABLE_UNIQUE_ID
726  if (!n->valid_unique_id())
727  {
728  if (processor_id() == n->processor_id())
729  {
731  _next_unique_id += this->n_processors();
732  }
733  else
734  {
737  }
738  }
739 #endif
740 
742 
743  // Unpartitioned nodes should be added on every processor
744  // And shouldn't be added in the same batch as ghost nodes
745  // But we might be just adding on processor 0 to
746  // broadcast later
747  // #ifdef DEBUG
748  // if (node_procid == DofObject::invalid_processor_id)
749  // {
750  // dof_id_type node_id = n->id();
751  // this->comm().max(node_id);
752  // libmesh_assert_equal_to (node_id, n->id());
753  // }
754  // #endif
755 
756  return n;
757 }
758 
759 
760 
762 {
763  return DistributedMesh::add_node(n);
764 }
765 
766 
767 
769 {
770  libmesh_assert(n);
771  libmesh_assert(_nodes[n->id()]);
772 
773  // Try to make the cached elem data more accurate
774  processor_id_type node_procid = n->processor_id();
775  if (node_procid == this->processor_id() ||
776  node_procid == DofObject::invalid_processor_id)
777  _n_nodes--;
778 
779  // Delete the node from the BoundaryInfo object
780  this->get_boundary_info().remove(n);
781 
782  // But not yet from the container; we might invalidate
783  // an iterator that way!
784 
785  //_nodes.erase(n->id());
786 
787  // Instead, we set it to nullptr for now
788 
789  _nodes[n->id()] = nullptr;
790 
791  // delete the node
792  delete n;
793 }
794 
795 
796 
798  const dof_id_type new_id)
799 {
800  Node * nd = _nodes[old_id];
801  libmesh_assert (nd);
802  libmesh_assert_equal_to (nd->id(), old_id);
803 
804  nd->set_id(new_id);
805 
806  // If we have nodes shipped to this processor for NodeConstraints
807  // use, then those nodes will exist in _nodes, but may not be
808  // locatable via a TopologyMap due to the insufficiency of elements
809  // connecting to them. If local refinement then wants to create a
810  // *new* node in the same location, it will initially get a temporary
811  // id, and then make_node_ids_parallel_consistent() will try to move
812  // it to the canonical id. We need to account for this case to
813  // avoid false positives and memory leaks.
814 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
815  if (_nodes[new_id])
816  {
817  libmesh_assert_equal_to (*(Point *)_nodes[new_id],
818  *(Point *)_nodes[old_id]);
819  _nodes.erase(new_id);
820  }
821 #else
822  // If we aren't shipping nodes for NodeConstraints, there should be
823  // no reason for renumbering one node onto another.
824  libmesh_assert (!_nodes[new_id]);
825 #endif
826  _nodes[new_id] = nd;
827  _nodes.erase(old_id);
828 }
829 
830 
831 
833 {
834  // Call parent clear function
835  MeshBase::clear();
836 
837  // Clear our elements and nodes
838  // There is no need to remove the elements from
839  // the BoundaryInfo data structure since we
840  // already cleared it.
841  for (auto & elem : _elements)
842  delete elem;
843 
844  // clear the nodes data structure
845  // There is no need to remove the nodes from
846  // the BoundaryInfo data structure since we
847  // already cleared it.
848  for (auto & node : _nodes)
849  delete node;
850 
851  _elements.clear();
852  _nodes.clear();
853 
854  // We're no longer distributed if we were before
855  _is_serial = true;
856  _is_serial_on_proc_0 = true;
857 
858  // Correct our caches
859  _n_nodes = 0;
860  _n_elem = 0;
861  _max_node_id = 0;
862  _max_elem_id = 0;
867 }
868 
869 
870 
872 {
873  // If this is a truly parallel mesh, go through the redistribution/gather/delete remote steps
874  if (!this->is_serial())
875  {
876  // Construct a MeshCommunication object to actually redistribute the nodes
877  // and elements according to the partitioner, and then to re-gather the neighbors.
879  mc.redistribute(*this);
880 
882 
883  // We probably had valid neighbors previously, so that a quality
884  // new partitioning could be found, but we might not have valid
885  // neighbor links on the newly-redistributed elements
886  this->find_neighbors();
887 
888  // Is this necessary? If we are called from prepare_for_use(), this will be called
889  // anyway... but users can always call partition directly, in which case we do need
890  // to call delete_remote_elements()...
891  //
892  // Regardless of whether it's necessary, it isn't safe. We
893  // haven't communicated new node processor_ids yet, and we can't
894  // delete nodes until we do.
895  // this->delete_remote_elements();
896  }
897 }
898 
899 
900 
902 {
903  // this->recalculate_n_partitions();
904 
905  // Partitioning changes our numbers of unpartitioned objects
907 }
908 
909 
910 
911 template <typename T>
913 {
914  // This function must be run on all processors at once
915  parallel_object_only();
916 
917  const dof_id_type pmax_node_id = this->parallel_max_node_id();
918  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
919  const dof_id_type pmax_id = std::max(pmax_node_id, pmax_elem_id);
920 
921  for (dof_id_type i=0; i != pmax_id; ++i)
922  {
923  T * obj = objects[i]; // Returns nullptr if there's no map entry
924 
925  // Local lookups by id should return the requested object
926  libmesh_assert(!obj || obj->id() == i);
927 
928  // All processors with an object should agree on id
929 #ifndef NDEBUG
930  const dof_id_type dofid = obj && obj->valid_id() ?
931  obj->id() : DofObject::invalid_id;
932  libmesh_assert(this->comm().semiverify(obj ? &dofid : nullptr));
933 #endif
934 
935  // All processors with an object should agree on processor id
936  const dof_id_type procid = obj && obj->valid_processor_id() ?
937  obj->processor_id() : DofObject::invalid_processor_id;
938  libmesh_assert(this->comm().semiverify(obj ? &procid : nullptr));
939 
940  dof_id_type min_procid = procid;
941  this->comm().min(min_procid);
942 
943  // Either:
944  // 1.) I own this elem (min_procid == this->processor_id()) *and* I have a valid pointer to it (obj != nullptr)
945  // or
946  // 2.) I don't own this elem (min_procid != this->processor_id()). (In this case I may or may not have a valid pointer to it.)
947 
948  // Original assert logic
949  // libmesh_assert (min_procid != this->processor_id() || obj);
950 
951  // More human-understandable logic...
953  ((min_procid == this->processor_id()) && obj)
954  ||
955  (min_procid != this->processor_id())
956  );
957 
958 #if defined(LIBMESH_ENABLE_UNIQUE_ID) && !defined(NDEBUG)
959  // All processors with an object should agree on unique id
960  const unique_id_type uniqueid = obj ? obj->unique_id() : 0;
961  libmesh_assert(this->comm().semiverify(obj ? &uniqueid : nullptr));
962 #endif
963  }
964 }
965 
966 
967 
969 {
972 }
973 
974 
975 
977 {
978 #ifndef NDEBUG
979  // This function must be run on all processors at once
980  parallel_object_only();
981 
982  dof_id_type pmax_elem_id = this->parallel_max_elem_id();
983 
984  for (dof_id_type i=0; i != pmax_elem_id; ++i)
985  {
986  Elem * el = _elements[i]; // Returns nullptr if there's no map entry
987 
988  unsigned int p_level = el ? (el->p_level()) : libMesh::invalid_uint;
989 
990  // All processors with an active element should agree on p level
991  libmesh_assert(this->comm().semiverify((el && el->active()) ? &p_level : nullptr));
992  }
993 #endif
994 }
995 
996 
997 
998 
1000 {
1001 #if defined(LIBMESH_ENABLE_AMR) && !defined(NDEBUG)
1002  // This function must be run on all processors at once
1003  parallel_object_only();
1004 
1005  dof_id_type pmax_elem_id = this->parallel_max_elem_id();
1006 
1007  for (dof_id_type i=0; i != pmax_elem_id; ++i)
1008  {
1009  Elem * el = _elements[i]; // Returns nullptr if there's no map entry
1010 
1011  unsigned int refinement_flag = el ?
1012  static_cast<unsigned int> (el->refinement_flag()) : libMesh::invalid_uint;
1013  unsigned int p_refinement_flag = el ?
1014  static_cast<unsigned int> (el->p_refinement_flag()) : libMesh::invalid_uint;
1015 
1016  libmesh_assert(this->comm().semiverify(el ? &refinement_flag : nullptr));
1017 
1018  // p refinement flags aren't always kept correct on inactive
1019  // ghost elements
1020  libmesh_assert(this->comm().semiverify((el && el->active()) ? &p_refinement_flag : nullptr));
1021  }
1022 #endif // LIBMESH_ENABLE_AMR
1023 }
1024 
1025 
1026 
1027 template <typename T>
1030 {
1031  // This function must be run on all processors at once
1032  parallel_object_only();
1033 
1034  typedef typename mapvector<T *,dof_id_type>::veclike_iterator object_iterator;
1035 
1036  // In parallel we may not know what objects other processors have.
1037  // Start by figuring out how many
1038  dof_id_type unpartitioned_objects = 0;
1039 
1040  std::unordered_map<processor_id_type, dof_id_type>
1041  ghost_objects_from_proc;
1042 
1043  object_iterator it = objects.begin();
1044  object_iterator end = objects.end();
1045 
1046  while (it != end)
1047  {
1048  T * obj = *it;
1049 
1050  // Remove any nullptr container entries while we're here.
1051  if (!obj)
1052  it = objects.erase(it);
1053  else
1054  {
1055  processor_id_type obj_procid = obj->processor_id();
1056  if (obj_procid == DofObject::invalid_processor_id)
1057  unpartitioned_objects++;
1058  else
1059  ghost_objects_from_proc[obj_procid]++;
1060 
1061  // Finally, increment the iterator
1062  ++it;
1063  }
1064  }
1065 
1066  std::vector<dof_id_type> objects_on_proc(this->n_processors(), 0);
1067  auto this_it = ghost_objects_from_proc.find(this->processor_id());
1068  this->comm().allgather
1069  ((this_it == ghost_objects_from_proc.end()) ?
1070  dof_id_type(0) : this_it->second, objects_on_proc);
1071 
1072 #ifndef NDEBUG
1073  libmesh_assert(this->comm().verify(unpartitioned_objects));
1074  for (processor_id_type p=0, np=this->n_processors(); p != np; ++p)
1075  if (ghost_objects_from_proc.count(p))
1076  libmesh_assert_less_equal (ghost_objects_from_proc[p], objects_on_proc[p]);
1077  else
1078  libmesh_assert_less_equal (0, objects_on_proc[p]);
1079 #endif
1080 
1081  // We'll renumber objects in blocks by processor id
1082  std::vector<dof_id_type> first_object_on_proc(this->n_processors());
1083  for (processor_id_type i=1, np=this->n_processors(); i != np; ++i)
1084  first_object_on_proc[i] = first_object_on_proc[i-1] +
1085  objects_on_proc[i-1];
1086  dof_id_type next_id = first_object_on_proc[this->processor_id()];
1087  dof_id_type first_free_id =
1088  first_object_on_proc[this->n_processors()-1] +
1089  objects_on_proc[this->n_processors()-1] +
1090  unpartitioned_objects;
1091 
1092  // First set new local object ids and build request sets
1093  // for non-local object ids
1094 
1095  // Request sets to send to each processor
1096  std::map<processor_id_type, std::vector<dof_id_type>>
1097  requested_ids;
1098 
1099  // We know how many objects live on each processor, so reserve() space for
1100  // each.
1101  auto ghost_end = ghost_objects_from_proc.end();
1102  for (auto p : IntRange<processor_id_type>(0, this->n_processors()))
1103  if (p != this->processor_id())
1104  {
1105  const auto p_it = ghost_objects_from_proc.find(p);
1106  if (p_it != ghost_end)
1107  requested_ids[p].reserve(p_it->second);
1108  }
1109 
1110  end = objects.end();
1111  for (it = objects.begin(); it != end; ++it)
1112  {
1113  T * obj = *it;
1114  if (obj->processor_id() == this->processor_id())
1115  obj->set_id(next_id++);
1116  else if (obj->processor_id() != DofObject::invalid_processor_id)
1117  requested_ids[obj->processor_id()].push_back(obj->id());
1118  }
1119 
1120  // Next set ghost object ids from other processors
1121 
1122  auto gather_functor =
1123  [
1124 #ifndef NDEBUG
1125  this,
1126  &first_object_on_proc,
1127  &objects_on_proc,
1128 #endif
1129  &objects]
1130  (processor_id_type, const std::vector<dof_id_type> & ids,
1131  std::vector<dof_id_type> & new_ids)
1132  {
1133  std::size_t ids_size = ids.size();
1134  new_ids.resize(ids_size);
1135 
1136  for (std::size_t i=0; i != ids_size; ++i)
1137  {
1138  T * obj = objects[ids[i]];
1139  libmesh_assert(obj);
1140  libmesh_assert_equal_to (obj->processor_id(), this->processor_id());
1141  new_ids[i] = obj->id();
1142 
1143  libmesh_assert_greater_equal (new_ids[i],
1144  first_object_on_proc[this->processor_id()]);
1145  libmesh_assert_less (new_ids[i],
1146  first_object_on_proc[this->processor_id()] +
1147  objects_on_proc[this->processor_id()]);
1148  }
1149  };
1150 
1151  auto action_functor =
1152  [
1153 #ifndef NDEBUG
1154  &first_object_on_proc,
1155  &objects_on_proc,
1156 #endif
1157  &objects]
1158  (processor_id_type libmesh_dbg_var(pid),
1159  const std::vector<dof_id_type> & ids,
1160  const std::vector<dof_id_type> & data)
1161  {
1162  // Copy the id changes we've now been informed of
1163  for (auto i : index_range(ids))
1164  {
1165  T * obj = objects[ids[i]];
1166  libmesh_assert (obj);
1167  libmesh_assert_equal_to (obj->processor_id(), pid);
1168  libmesh_assert_greater_equal (data[i],
1169  first_object_on_proc[pid]);
1170  libmesh_assert_less (data[i],
1171  first_object_on_proc[pid] +
1172  objects_on_proc[pid]);
1173  obj->set_id(data[i]);
1174  }
1175  };
1176 
1177  const dof_id_type * ex = nullptr;
1178  Parallel::pull_parallel_vector_data
1179  (this->comm(), requested_ids, gather_functor, action_functor, ex);
1180 
1181 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1182  auto unique_gather_functor =
1183  [
1184 #ifndef NDEBUG
1185  this,
1186 #endif
1187  &objects]
1188  (processor_id_type, const std::vector<dof_id_type> & ids,
1189  std::vector<unique_id_type> & data)
1190  {
1191  std::size_t ids_size = ids.size();
1192  data.resize(ids_size);
1193 
1194  for (std::size_t i=0; i != ids_size; ++i)
1195  {
1196  T * obj = objects[ids[i]];
1197  libmesh_assert(obj);
1198  libmesh_assert_equal_to (obj->processor_id(), this->processor_id());
1199  data[i] = obj->valid_unique_id() ? obj->unique_id() : DofObject::invalid_unique_id;
1200  }
1201  };
1202 
1203  auto unique_action_functor =
1204  [&objects]
1205  (processor_id_type libmesh_dbg_var(pid),
1206  const std::vector<dof_id_type> & ids,
1207  const std::vector<unique_id_type> & data)
1208  {
1209  for (auto i : index_range(ids))
1210  {
1211  T * obj = objects[ids[i]];
1212  libmesh_assert (obj);
1213  libmesh_assert_equal_to (obj->processor_id(), pid);
1214  if (!obj->valid_unique_id() && data[i] != DofObject::invalid_unique_id)
1215  obj->set_unique_id() = (data[i]);
1216  }
1217  };
1218 
1219  const unique_id_type * unique_ex = nullptr;
1220  Parallel::pull_parallel_vector_data
1221  (this->comm(), requested_ids, unique_gather_functor,
1222  unique_action_functor, unique_ex);
1223 #endif
1224 
1225  // Next set unpartitioned object ids
1226  next_id = 0;
1227  for (auto i : IntRange<processor_id_type>(0, this->n_processors()))
1228  next_id += objects_on_proc[i];
1229  for (it = objects.begin(); it != end; ++it)
1230  {
1231  T * obj = *it;
1232  if (obj->processor_id() == DofObject::invalid_processor_id)
1233  obj->set_id(next_id++);
1234  }
1235 
1236  // Finally shuffle around objects so that container indices
1237  // match ids
1238  it = objects.begin();
1239  end = objects.end();
1240  while (it != end)
1241  {
1242  T * obj = *it;
1243  if (obj) // don't try shuffling already-nullptr entries
1244  {
1245  T * next = objects[obj->id()];
1246  // If we have to move this object
1247  if (next != obj)
1248  {
1249  // nullptr out its original position for now
1250  // (our shuffling may put another object there shortly)
1251  *it = nullptr;
1252 
1253  // There may already be another object with this id that
1254  // needs to be moved itself
1255  while (next)
1256  {
1257  // We shouldn't be trying to give two objects the
1258  // same id
1259  libmesh_assert_not_equal_to (next->id(), obj->id());
1260  objects[obj->id()] = obj;
1261  obj = next;
1262  next = objects[obj->id()];
1263  }
1264  objects[obj->id()] = obj;
1265  }
1266  }
1267 
1268  // Remove any container entries that were left as nullptr.
1269  if (!obj)
1270  it = objects.erase(it);
1271  else
1272  ++it;
1273  }
1274 
1275  return first_free_id;
1276 }
1277 
1278 
1280 {
1281  parallel_object_only();
1282 
1283 #ifdef DEBUG
1284  // Make sure our ids and flags are consistent
1288 #endif
1289 
1290  LOG_SCOPE("renumber_nodes_and_elements()", "DistributedMesh");
1291 
1292  std::set<dof_id_type> used_nodes;
1293 
1294  // flag the nodes we need
1295  for (auto & elem : this->element_ptr_range())
1296  for (const Node & node : elem->node_ref_range())
1297  used_nodes.insert(node.id());
1298 
1299  // Nodes not connected to any local elements, and nullptr node entries
1300  // in our container, are deleted
1301  {
1302  node_iterator_imp it = _nodes.begin();
1303  node_iterator_imp end = _nodes.end();
1304 
1305  while (it != end)
1306  {
1307  Node * nd = *it;
1308  if (!nd)
1309  it = _nodes.erase(it);
1310  else if (!used_nodes.count(nd->id()))
1311  {
1312  // remove any boundary information associated with
1313  // this node
1314  this->get_boundary_info().remove (nd);
1315 
1316  // delete the node
1317  delete nd;
1318 
1319  it = _nodes.erase(it);
1320  }
1321  else
1322  ++it;
1323  }
1324  }
1325 
1327  {
1328  this->update_parallel_id_counts();
1329  return;
1330  }
1331 
1332  // Finally renumber all the elements
1333  _n_elem = this->renumber_dof_objects (this->_elements);
1334 
1335  // and all the remaining nodes
1336  _n_nodes = this->renumber_dof_objects (this->_nodes);
1337 
1338  // And figure out what IDs we should use when adding new nodes and
1339  // new elements
1340  this->update_parallel_id_counts();
1341 
1342  // Make sure our caches are up to date and our
1343  // DofObjects are well packed
1344 #ifdef DEBUG
1345  libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes());
1346  libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem());
1347  const dof_id_type pmax_node_id = this->parallel_max_node_id();
1348  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
1349  libmesh_assert_equal_to (this->max_node_id(), pmax_node_id);
1350  libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id);
1351  libmesh_assert_equal_to (this->n_nodes(), this->max_node_id());
1352  libmesh_assert_equal_to (this->n_elem(), this->max_elem_id());
1353 
1354  // Make sure our ids and flags are consistent
1357 
1358  // And make sure we've made our numbering monotonic
1360 #endif
1361 }
1362 
1363 
1364 
1366 {
1367  // We need access to iterators for the underlying containers,
1368  // not the mapvector<> reimplementations.
1371 
1372  // Nodes first
1373  for (auto & pr : nodes)
1374  if (pr.second != nullptr)
1375  pr.second->set_id() = pr.first;
1376 
1377  // Elements next
1378  for (const auto & pr : elems)
1379  if (pr.second != nullptr)
1380  pr.second->set_id() = pr.first;
1381 }
1382 
1383 
1384 
1386 {
1387  parallel_object_only();
1388 
1389  // Get local active elements first
1390  dof_id_type active_elements =
1391  static_cast<dof_id_type>(std::distance (this->active_local_elements_begin(),
1392  this->active_local_elements_end()));
1393  this->comm().sum(active_elements);
1394 
1395  // Then add unpartitioned active elements, which should exist on
1396  // every processor
1397  active_elements +=
1398  static_cast<dof_id_type>(std::distance
1401  return active_elements;
1402 }
1403 
1404 
1405 
1407 {
1408 #ifdef DEBUG
1409  // Make sure our neighbor links are all fine
1411 
1412  // And our child/parent links, and our flags
1414 
1415  // Make sure our ids and flags are consistent
1418 
1419  libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes());
1420  libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem());
1421  const dof_id_type pmax_node_id = this->parallel_max_node_id();
1422  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
1423  libmesh_assert_equal_to (this->max_node_id(), pmax_node_id);
1424  libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id);
1425 #endif
1426 
1427  _is_serial = false;
1428  _is_serial_on_proc_0 = false;
1429 
1430  MeshCommunication().delete_remote_elements(*this, _extra_ghost_elems);
1431 
1432  libmesh_assert_equal_to (this->max_elem_id(), this->parallel_max_elem_id());
1433 
1434  // Now make sure the containers actually shrink - strip
1435  // any newly-created nullptr voids out of the element array
1438  while (e_it != e_end)
1439  if (!*e_it)
1440  e_it = _elements.erase(e_it);
1441  else
1442  ++e_it;
1443 
1446  while (n_it != n_end)
1447  if (!*n_it)
1448  n_it = _nodes.erase(n_it);
1449  else
1450  ++n_it;
1451 
1452  // We may have deleted no-longer-connected nodes or coarsened-away
1453  // elements; let's update our caches.
1454  this->update_parallel_id_counts();
1455 
1456 #ifdef DEBUG
1457  // We might not have well-packed objects if the user didn't allow us
1458  // to renumber
1459  // libmesh_assert_equal_to (this->n_nodes(), this->max_node_id());
1460  // libmesh_assert_equal_to (this->n_elem(), this->max_elem_id());
1461 
1462  // Make sure our neighbor links are all fine
1464 
1465  // And our child/parent links, and our flags
1467 
1468  // Make sure our ids and flags are consistent
1471 #endif
1472 }
1473 
1474 
1476 {
1477  // First add the elem like normal
1478  add_elem(e);
1479 
1480  // Now add it to the set that won't be deleted when we call
1481  // delete_remote_elements()
1482  _extra_ghost_elems.insert(e);
1483 }
1484 
1485 void
1486 DistributedMesh::clear_extra_ghost_elems(const std::set<Elem *> & extra_ghost_elems)
1487 {
1488  std::set<Elem *> tmp;
1489  std::set_difference(_extra_ghost_elems.begin(), _extra_ghost_elems.end(),
1490  extra_ghost_elems.begin(), extra_ghost_elems.end(),
1491  std::inserter(tmp, tmp.begin()));
1492  _extra_ghost_elems = tmp;
1493 }
1494 
1496 {
1497  if (_is_serial)
1498  return;
1499  MeshCommunication().allgather(*this);
1500  _is_serial = true;
1501  _is_serial_on_proc_0 = true;
1502 
1503  // Make sure our caches are up to date and our
1504  // DofObjects are well packed
1505 #ifdef DEBUG
1506  libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes());
1507  libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem());
1508  const dof_id_type pmax_node_id = this->parallel_max_node_id();
1509  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
1510  libmesh_assert_equal_to (this->max_node_id(), pmax_node_id);
1511  libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id);
1512 
1513  // If we've disabled renumbering we can't be sure we're contiguous
1514  // libmesh_assert_equal_to (this->n_nodes(), this->max_node_id());
1515  // libmesh_assert_equal_to (this->n_elem(), this->max_elem_id());
1516 
1517  // Make sure our neighbor links are all fine
1519 
1520  // Make sure our ids and flags are consistent
1523 #endif
1524 }
1525 
1527 {
1529  return;
1530 
1531  _is_serial_on_proc_0 = true;
1532  MeshCommunication().gather(0, *this);
1533 }
1534 
1535 
1536 } // namespace libMesh
libMesh::DistributedMesh::_nodes
mapvector< Node *, dof_id_type > _nodes
The vertices (spatial coordinates) of the mesh.
Definition: distributed_mesh.h:550
libMesh::MeshBase::MeshCommunication
friend class MeshCommunication
Make the MeshCommunication class a friend so that it can directly broadcast *_integer_names.
Definition: mesh_base.h:1857
libMesh::DofObject::valid_id
bool valid_id() const
Definition: dof_object.h:809
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::MeshTools::Subdivision::next
static const unsigned int next[3]
A lookup table for the increment modulo 3 operation, for iterating through the three nodes per elemen...
Definition: mesh_subdivision_support.h:102
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::DistributedMesh::_max_elem_id
dof_id_type _max_elem_id
Definition: distributed_mesh.h:570
libMesh::DistributedMesh::_extra_ghost_elems
std::set< Elem * > _extra_ghost_elems
These are extra ghost elements that we want to make sure not to delete when we call delete_remote_ele...
Definition: distributed_mesh.h:592
libMesh::mapvector::veclike_iterator
Definition: mapvector.h:54
libMesh::MeshBase::default_mapping_type
ElemMappingType default_mapping_type() const
Returns the default master space to physical space mapping basis functions to be used on newly added ...
Definition: mesh_base.h:708
libMesh::UnstructuredMesh::find_neighbors
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true) override
Other functions from MeshBase requiring re-definition.
Definition: unstructured_mesh.C:257
libMesh::DistributedMesh::delete_node
virtual void delete_node(Node *n) override
Removes the Node n from the mesh.
Definition: distributed_mesh.C:768
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::DistributedMesh::max_elem_id
virtual dof_id_type max_elem_id() const override
Definition: distributed_mesh.h:234
libMesh::DistributedMesh::parallel_max_elem_id
dof_id_type parallel_max_elem_id() const
Definition: distributed_mesh.C:233
libMesh::DistributedMesh::query_node_ptr
virtual const Node * query_node_ptr(const dof_id_type i) const override
Definition: distributed_mesh.C:350
libMesh::DistributedMesh::parallel_max_node_id
dof_id_type parallel_max_node_id() const
Definition: distributed_mesh.C:291
libMesh::DofObject::set_id
dof_id_type & set_id()
Definition: dof_object.h:776
libMesh::DistributedMesh::add_point
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id) override
functions for adding /deleting nodes elements.
Definition: distributed_mesh.C:625
libMesh::DistributedMesh::_max_node_id
dof_id_type _max_node_id
Definition: distributed_mesh.h:570
libMesh::DistributedMesh::libmesh_assert_valid_parallel_object_ids
void libmesh_assert_valid_parallel_object_ids(const mapvector< T *, dof_id_type > &) const
Verify id, processor_id, and if applicable unique_id consistency of a parallel objects container.
Definition: distributed_mesh.C:912
libMesh::DistributedMesh::parallel_max_unique_id
virtual unique_id_type parallel_max_unique_id() const override
Definition: distributed_mesh.C:264
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::DistributedMesh::fix_broken_node_and_element_numbering
virtual void fix_broken_node_and_element_numbering() override
There is no reason for a user to ever call this function.
Definition: distributed_mesh.C:1365
libMesh::UnstructuredMesh::copy_nodes_and_elements
virtual void copy_nodes_and_elements(const UnstructuredMesh &other_mesh, const bool skip_find_neighbors=false, dof_id_type element_id_offset=0, dof_id_type node_id_offset=0, unique_id_type unique_id_offset=0)
Deep copy of nodes and elements from another unstructured mesh class (used by subclass copy construct...
Definition: unstructured_mesh.C:61
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::DistributedMesh::own_node
virtual void own_node(Node &n) override
Takes ownership of node n on this partition of a distributed mesh, by setting n.processor_id() to thi...
Definition: distributed_mesh.C:649
libMesh::DistributedMesh::active_pid_elements_end
virtual element_iterator active_pid_elements_end(processor_id_type proc_id) override
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::Elem::set_mapping_data
void set_mapping_data(const unsigned char data)
Sets the value of the mapping data for the element.
Definition: elem.h:2548
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::DofObject::add_extra_integers
void add_extra_integers(const unsigned int n_integers)
Assigns a set of extra integers to this DofObject.
Definition: dof_object.C:503
libMesh::ParallelObject::comm
const Parallel::Communicator & comm() const
Definition: parallel_object.h:94
libMesh::MeshBase::set_subdomain_name_map
std::map< subdomain_id_type, std::string > & set_subdomain_name_map()
Definition: mesh_base.h:1631
libMesh::DistributedMesh::max_node_id
virtual dof_id_type max_node_id() const override
Definition: distributed_mesh.h:230
libMesh::Elem::p_level
unsigned int p_level() const
Definition: elem.h:2512
libMesh::DofObject::set_unique_id
unique_id_type & set_unique_id()
Definition: dof_object.h:797
libMesh::DofObject::valid_unique_id
bool valid_unique_id() const
Definition: dof_object.h:817
libMesh::DistributedMesh::active_pid_elements_begin
virtual element_iterator active_pid_elements_begin(processor_id_type proc_id) override
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::DofObject::processor_id
processor_id_type processor_id() const
Definition: dof_object.h:829
libMesh::Elem::active
bool active() const
Definition: elem.h:2345
parallel_sync.h
libMesh::mapvector::maptype
std::map< index_t, Val > maptype
Definition: mapvector.h:42
libMesh::BoundaryInfo::remove
void remove(const Node *node)
Removes the boundary conditions associated with node node, if any exist.
Definition: boundary_info.C:1358
libMesh::mapvector::erase
void erase(index_t i)
Definition: mapvector.h:116
libMesh::DistributedMesh::libmesh_assert_valid_parallel_flags
void libmesh_assert_valid_parallel_flags() const
Verify refinement_flag and p_refinement_flag consistency of our elements containers.
Definition: distributed_mesh.C:999
libMesh::DistributedMesh::active_local_elements_end
virtual element_iterator active_local_elements_end() override
libMesh::DistributedMesh::_next_free_unpartitioned_node_id
dof_id_type _next_free_unpartitioned_node_id
Definition: distributed_mesh.h:578
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::DistributedMesh::parallel_n_elem
virtual dof_id_type parallel_n_elem() const override
Definition: distributed_mesh.C:220
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::DistributedMesh::renumber_nodes_and_elements
virtual void renumber_nodes_and_elements() override
Remove nullptr elements from arrays.
Definition: distributed_mesh.C:1279
libMesh::DofObject::invalid_unique_id
static const unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
Definition: dof_object.h:426
libMesh::DistributedMesh::redistribute
virtual void redistribute() override
Redistribute elements between processors.
Definition: distributed_mesh.C:871
libMesh::DistributedMesh::n_nodes
virtual dof_id_type n_nodes() const override
Definition: distributed_mesh.h:229
libMesh::MeshBase::n_local_nodes
dof_id_type n_local_nodes() const
Definition: mesh_base.h:303
libMesh::MeshCommunication::redistribute
void redistribute(DistributedMesh &mesh, bool newly_coarsened_only=false) const
This method takes a parallel distributed mesh and redistributes the elements.
Definition: mesh_communication.C:285
libMesh::DistributedMesh::renumber_elem
virtual void renumber_elem(dof_id_type old_id, dof_id_type new_id) override
Changes the id of element old_id, both by changing elem(old_id)->id() and by moving elem(old_id) in t...
Definition: distributed_mesh.C:610
libMesh::Elem::node_ref_range
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2152
libMesh::DistributedMesh::clear
virtual void clear() override
Clear all internal data.
Definition: distributed_mesh.C:832
libMesh::DistributedMesh::renumber_node
virtual void renumber_node(dof_id_type old_id, dof_id_type new_id) override
Changes the id of node old_id, both by changing node(old_id)->id() and by moving node(old_id) in the ...
Definition: distributed_mesh.C:797
libMesh::MeshBase::_elem_integer_names
std::vector< std::string > _elem_integer_names
The array of names for integer data associated with each element in the mesh.
Definition: mesh_base.h:1780
libMesh::ParallelObject::n_processors
processor_id_type n_processors() const
Definition: parallel_object.h:100
libMesh::Elem::set_mapping_type
void set_mapping_type(const ElemMappingType type)
Sets the value of the mapping type for the element.
Definition: elem.h:2532
libMesh::DistributedMesh::delete_elem
virtual void delete_elem(Elem *e) override
Removes element e from the mesh.
Definition: distributed_mesh.C:582
libMesh::Elem::p_refinement_flag
RefinementState p_refinement_flag() const
Definition: elem.h:2630
libMesh::MeshBase::_next_unique_id
unique_id_type _next_unique_id
The next available unique id for assigning ids to DOF objects.
Definition: mesh_base.h:1727
libMesh::DistributedMesh::allgather
virtual void allgather() override
Gathers all elements and nodes of the mesh onto every processor.
Definition: distributed_mesh.C:1495
libMesh::DistributedMesh::_is_serial
bool _is_serial
A boolean remembering whether we're serialized or not.
Definition: distributed_mesh.h:560
libMesh::MeshBase::elem
virtual const Elem * elem(const dof_id_type i) const
Definition: mesh_base.h:554
libMesh::DistributedMesh::n_elem
virtual dof_id_type n_elem() const override
Definition: distributed_mesh.h:232
libMesh::DistributedMesh::clear_extra_ghost_elems
virtual void clear_extra_ghost_elems()
Clears extra ghost elements.
Definition: distributed_mesh.h:216
libMesh::ParallelObject::processor_id
processor_id_type processor_id() const
Definition: parallel_object.h:106
libMesh::DistributedMesh::gather_to_zero
virtual void gather_to_zero() override
Gathers all elements and nodes of the mesh onto processor zero.
Definition: distributed_mesh.C:1526
libMesh::DofObject::invalid_id
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:421
parallel_implementation.h
libMesh::DistributedMesh::insert_elem
virtual Elem * insert_elem(Elem *e) override
Insert elem e to the element array, preserving its id and replacing/deleting any existing element wit...
Definition: distributed_mesh.C:540
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
libMesh::processor_id_type
uint8_t processor_id_type
Definition: id_types.h:104
libMesh::DistributedMesh::add_extra_ghost_elem
virtual void add_extra_ghost_elem(Elem *e)
Inserts the element and adds it to a list of elements that should not get deleted or have their desce...
Definition: distributed_mesh.C:1475
libMesh::Node::build
static std::unique_ptr< Node > build(const Node &n)
Definition: node.h:314
libMesh::DistributedMesh::add_elem
virtual Elem * add_elem(Elem *e) override
Add elem e to the end of the element array.
Definition: distributed_mesh.C:436
libMesh::Node
A Node is like a Point, but with more information.
Definition: node.h:52
libMesh::DistributedMesh::update_post_partitioning
virtual void update_post_partitioning() override
Recalculate cached data after elements and nodes have been repartitioned.
Definition: distributed_mesh.C:901
libMesh::DistributedMesh::_next_free_local_elem_id
dof_id_type _next_free_local_elem_id
Definition: distributed_mesh.h:576
libMesh::DistributedMesh::delete_remote_elements
virtual void delete_remote_elements() override
Deletes all nonlocal elements of the mesh except for "ghosts" which touch a local element,...
Definition: distributed_mesh.C:1406
libMesh::MeshBase::node
virtual const Node & node(const dof_id_type i) const
Definition: mesh_base.h:471
libMesh::DistributedMesh::DistributedMesh
DistributedMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
Constructor.
Definition: distributed_mesh.C:40
libMesh::MeshBase::n_local_elem
dof_id_type n_local_elem() const
Definition: mesh_base.h:403
libMesh::MeshBase::get_subdomain_name_map
const std::map< subdomain_id_type, std::string > & get_subdomain_name_map() const
Definition: mesh_base.h:1633
libMesh::mapvector
This mapvector templated class is intended to provide the performance characteristics of a std::map w...
Definition: mapvector.h:39
libMesh::DistributedMesh::active_local_elements_begin
virtual element_iterator active_local_elements_begin() override
libMesh::DistributedMesh::~DistributedMesh
virtual ~DistributedMesh()
Destructor.
libMesh::MeshBase::_node_integer_names
std::vector< std::string > _node_integer_names
The array of names for integer data associated with each node in the mesh.
Definition: mesh_base.h:1786
libMesh::MeshBase::node_ref
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:451
libMesh::UnstructuredMesh
The UnstructuredMesh class is derived from the MeshBase class.
Definition: unstructured_mesh.h:48
libMesh::MeshBase::_partitioner
std::unique_ptr< Partitioner > _partitioner
A partitioner to use at each prepare_for_use().
Definition: mesh_base.h:1721
libMesh::DistributedMesh::_next_free_unpartitioned_elem_id
dof_id_type _next_free_unpartitioned_elem_id
Definition: distributed_mesh.h:578
libMesh::DistributedMesh::_n_nodes
dof_id_type _n_nodes
Cached data from the last renumber_nodes_and_elements call.
Definition: distributed_mesh.h:570
libMesh::Elem::refinement_flag
RefinementState refinement_flag() const
Definition: elem.h:2614
distance
Real distance(const Point &p)
Definition: subdomains_ex3.C:50
libMesh::DistributedMesh::renumber_dof_objects
dof_id_type renumber_dof_objects(mapvector< T *, dof_id_type > &)
Renumber a parallel objects container.
Definition: distributed_mesh.C:1029
libMesh::DistributedMesh::query_elem_ptr
virtual const Elem * query_elem_ptr(const dof_id_type i) const override
Definition: distributed_mesh.C:404
libMesh::MeshBase::_skip_renumber_nodes_and_elements
bool _skip_renumber_nodes_and_elements
If this is true then renumbering will be kept to a minimum.
Definition: mesh_base.h:1746
libMesh::DistributedMesh::elem_ptr
virtual const Elem * elem_ptr(const dof_id_type i) const override
Definition: distributed_mesh.C:382
libMesh::DistributedMesh::element_ptr_range
virtual SimpleRange< element_iterator > element_ptr_range() override
Definition: distributed_mesh.h:308
libMesh::MeshBase::n_unpartitioned_elem
dof_id_type n_unpartitioned_elem() const
Definition: mesh_base.h:409
libMesh::DistributedMesh::libmesh_assert_valid_parallel_p_levels
void libmesh_assert_valid_parallel_p_levels() const
Verify p_level consistency of our elements containers.
Definition: distributed_mesh.C:976
libMesh::DofObject::id
dof_id_type id() const
Definition: dof_object.h:767
libMesh::DistributedMesh::libmesh_assert_valid_parallel_ids
virtual void libmesh_assert_valid_parallel_ids() const override
Verify id and processor_id consistency of our elements and nodes containers.
Definition: distributed_mesh.C:968
libMesh::DistributedMesh::extra_ghost_elems
const std::set< Elem * > & extra_ghost_elems() const
Const accessor to the ghosted elements.
Definition: distributed_mesh.h:226
libMesh::MeshBase::n_unpartitioned_nodes
dof_id_type n_unpartitioned_nodes() const
Definition: mesh_base.h:309
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::DistributedMesh::point
virtual const Point & point(const dof_id_type i) const override
Definition: distributed_mesh.C:321
libMesh::DistributedMesh::update_parallel_id_counts
virtual void update_parallel_id_counts() override
Updates parallel caches so that methods like n_elem() accurately reflect changes on other processors.
Definition: distributed_mesh.C:178
libMesh::DistributedMesh::is_serial
virtual bool is_serial() const override
Definition: distributed_mesh.h:119
data
IterBase * data
Ideally this private member data should have protected access.
Definition: variant_filter_iterator.h:337
libMesh::DistributedMesh::_next_unpartitioned_unique_id
unique_id_type _next_unpartitioned_unique_id
The next available unique id for assigning ids to unpartitioned DOF objects.
Definition: distributed_mesh.h:585
libMesh::DistributedMesh::_is_serial_on_proc_0
bool _is_serial_on_proc_0
A boolean remembering whether we're serialized to proc 0 or not.
Definition: distributed_mesh.h:565
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::MeshBase::parallel_max_unique_id
virtual unique_id_type parallel_max_unique_id() const =0
libMesh::MeshBase::default_mapping_data
unsigned char default_mapping_data() const
Returns any default data value used by the master space to physical space mapping.
Definition: mesh_base.h:724
libMesh::DistributedMesh::_elements
mapvector< Elem *, dof_id_type > _elements
The elements in the mesh.
Definition: distributed_mesh.h:555
libMesh::DistributedMesh::add_node
virtual Node * add_node(Node *n) override
Add Node n to the end of the vertex array.
Definition: distributed_mesh.C:663
libMesh::MeshCommunication
This is the MeshCommunication class.
Definition: mesh_communication.h:50
libMesh::MeshBase::clear
virtual void clear()
Deletes all the element and node data that is currently stored.
Definition: mesh_base.C:429
libMesh::DistributedMesh::parallel_n_nodes
virtual dof_id_type parallel_n_nodes() const override
Definition: distributed_mesh.C:278
libMesh::mapvector::end
veclike_iterator end()
Definition: mapvector.h:132
libMesh::DistributedMesh::insert_node
virtual Node * insert_node(Node *n) override
Calls add_node().
Definition: distributed_mesh.C:761
libMesh::mapvector::begin
veclike_iterator begin()
Definition: mapvector.h:124
libMesh::DistributedMesh::_next_free_local_node_id
dof_id_type _next_free_local_node_id
Guaranteed globally unused IDs for use when adding new nodes or elements.
Definition: distributed_mesh.h:576
libMesh::DistributedMesh
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
Definition: distributed_mesh.h:50
libMesh::DistributedMesh::n_active_elem
virtual dof_id_type n_active_elem() const override
Definition: distributed_mesh.C:1385
libMesh::DistributedMesh::_n_elem
dof_id_type _n_elem
Definition: distributed_mesh.h:570
libMesh::DistributedMesh::node_ptr
virtual const Node * node_ptr(const dof_id_type i) const override
Definition: distributed_mesh.C:328