libMesh
distributed_mesh.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/boundary_info.h"
22 #include "libmesh/distributed_mesh.h"
23 #include "libmesh/elem.h"
24 #include "libmesh/libmesh_logging.h"
25 #include "libmesh/mesh_communication.h"
26 #include "libmesh/parallel.h"
27 #include "libmesh/parmetis_partitioner.h"
28 
29 namespace libMesh
30 {
31 
32 // ------------------------------------------------------------
33 // DistributedMesh class member functions
35  unsigned char d) :
36  UnstructuredMesh (comm_in,d), _is_serial(true),
37  _is_serial_on_proc_0(true),
38  _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0),
39  _next_free_local_node_id(this->processor_id()),
40  _next_free_local_elem_id(this->processor_id()),
41  _next_free_unpartitioned_node_id(this->n_processors()),
42  _next_free_unpartitioned_elem_id(this->n_processors())
43 #ifdef LIBMESH_ENABLE_UNIQUE_ID
44  , _next_unpartitioned_unique_id(this->n_processors())
45 #endif
46 {
47 #ifdef LIBMESH_ENABLE_UNIQUE_ID
48  _next_unique_id = this->processor_id();
49 #endif
50 
51  // FIXME: give parmetis the communicator!
53 }
54 
55 
56 #ifndef LIBMESH_DISABLE_COMMWORLD
57 #ifdef LIBMESH_ENABLE_DEPRECATED
58 DistributedMesh::DistributedMesh (unsigned char d) :
65 #ifdef LIBMESH_ENABLE_UNIQUE_ID
67 #endif
68 {
69  libmesh_deprecated();
70 
71 #ifdef LIBMESH_ENABLE_UNIQUE_ID
72  _next_unique_id = this->processor_id();
73 #endif
74 
75  // FIXME: give parmetis the communicator!
77 }
78 #endif
79 #endif
80 
81 
83 {
84  this->clear(); // Free nodes and elements
85 }
86 
87 
88 // This might be specialized later, but right now it's just here to
89 // make sure the compiler doesn't give us a default (non-deep) copy
90 // constructor instead.
92  UnstructuredMesh (other_mesh), _is_serial(other_mesh._is_serial),
99 {
100  this->copy_nodes_and_elements(other_mesh);
101  _n_nodes = other_mesh.n_nodes();
102  _n_elem = other_mesh.n_elem();
103  _max_node_id = other_mesh.max_node_id();
104  _max_elem_id = other_mesh.max_elem_id();
106  other_mesh._next_free_local_node_id;
108  other_mesh._next_free_local_elem_id;
113 #ifdef LIBMESH_ENABLE_UNIQUE_ID
115  other_mesh._next_unique_id;
118 #endif
119  this->get_boundary_info() = other_mesh.get_boundary_info();
120 
121  // Need to copy extra_ghost_elems
122  for (std::set<Elem *>::iterator it = other_mesh._extra_ghost_elems.begin();
123  it != other_mesh._extra_ghost_elems.end();
124  ++it)
125  _extra_ghost_elems.insert(this->elem_ptr((*it)->id()));
126 }
127 
128 
129 
131  UnstructuredMesh (other_mesh), _is_serial(other_mesh.is_serial()),
132  _is_serial_on_proc_0(other_mesh.is_serial()),
133  _n_nodes(0), _n_elem(0), _max_node_id(0), _max_elem_id(0),
138 {
139  this->copy_nodes_and_elements(other_mesh);
140  this->get_boundary_info() = other_mesh.get_boundary_info();
141 
142 #ifdef LIBMESH_ENABLE_UNIQUE_ID
144 #endif
146 }
147 
148 
149 // We use cached values for these so they can be called
150 // from one processor without bothering the rest, but
151 // we may need to update those caches before doing a full
152 // renumbering
154 {
155  // This function must be run on all processors at once
156  parallel_object_only();
157 
158  _n_elem = this->parallel_n_elem();
159  _n_nodes = this->parallel_n_nodes();
162 
165  ((_max_elem_id-1) / (this->n_processors() + 1) + 1) *
166  (this->n_processors() + 1) + this->n_processors();
169  ((_max_elem_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
170  (this->n_processors() + 1) + this->processor_id();
171 
174  ((_max_node_id-1) / (this->n_processors() + 1) + 1) *
175  (this->n_processors() + 1) + this->n_processors();
178  ((_max_node_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
179  (this->n_processors() + 1) + this->processor_id();
180 
181 #ifdef LIBMESH_ENABLE_UNIQUE_ID
184  ((_next_unique_id-1) / (this->n_processors() + 1) + 1) *
185  (this->n_processors() + 1) + this->n_processors();
187  ((_next_unique_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
188  (this->n_processors() + 1) + this->processor_id();
189 #endif
190 }
191 
192 
193 // Or in debug mode we may want to test the uncached values without
194 // changing the cache
196 {
197  // This function must be run on all processors at once
198  parallel_object_only();
199 
200  dof_id_type n_local = this->n_local_elem();
201  this->comm().sum(n_local);
202  n_local += this->n_unpartitioned_elem();
203  return n_local;
204 }
205 
206 
207 
209 {
210  // This function must be run on all processors at once
211  parallel_object_only();
212 
213  dof_id_type max_local = 0;
214 
216  rit = _elements.rbegin();
217 
219  rend = _elements.rend();
220 
221  // Look for the maximum element id. Search backwards through
222  // elements so we can break out early. Beware of NULL entries that
223  // haven't yet been cleared from _elements.
224  for (; rit != rend; ++rit)
225  if (rit->second)
226  {
227  libmesh_assert_equal_to(rit->second->id(), rit->first);
228  max_local = rit->first + 1;
229  break;
230  }
231 
232  this->comm().max(max_local);
233  return max_local;
234 }
235 
236 
237 
238 #ifdef LIBMESH_ENABLE_UNIQUE_ID
240 {
241  // This function must be run on all processors at once
242  parallel_object_only();
243 
246  this->comm().max(max_local);
247  return max_local;
248 }
249 #endif
250 
251 
252 
254 {
255  // This function must be run on all processors at once
256  parallel_object_only();
257 
258  dof_id_type n_local = this->n_local_nodes();
259  this->comm().sum(n_local);
260  n_local += this->n_unpartitioned_nodes();
261  return n_local;
262 }
263 
264 
265 
267 {
268  // This function must be run on all processors at once
269  parallel_object_only();
270 
271  dof_id_type max_local = 0;
272 
274  rit = _nodes.rbegin();
275 
277  rend = _nodes.rend();
278 
279  // Look for the maximum element id. Search backwards through
280  // elements so we can break out early. Beware of NULL entries that
281  // haven't yet been cleared from _elements.
282  for (; rit != rend; ++rit)
283  if (rit->second)
284  {
285  libmesh_assert_equal_to(rit->second->id(), rit->first);
286  max_local = rit->first + 1;
287  break;
288  }
289 
290  this->comm().max(max_local);
291  return max_local;
292 }
293 
294 
295 
296 const Point & DistributedMesh::point (const dof_id_type i) const
297 {
298  return this->node_ref(i);
299 }
300 
301 
302 
304 {
306  libmesh_assert_equal_to (_nodes[i]->id(), i);
307 
308  return _nodes[i];
309 }
310 
311 
312 
313 
315 {
317  libmesh_assert_equal_to (_nodes[i]->id(), i);
318 
319  return _nodes[i];
320 }
321 
322 
323 
324 
326 {
327  std::map<dof_id_type, Node *>::const_iterator it = _nodes.find(i);
328  if (it != _nodes.end().it)
329  {
330  const Node * n = it->second;
331  libmesh_assert (!n || n->id() == i);
332  return n;
333  }
334 
335  return libmesh_nullptr;
336 }
337 
338 
339 
340 
342 {
343  std::map<dof_id_type, Node *>::const_iterator it = _nodes.find(i);
344  if (it != _nodes.end().it)
345  {
346  Node * n = it->second;
347  libmesh_assert (!n || n->id() == i);
348  return n;
349  }
350 
351  return libmesh_nullptr;
352 }
353 
354 
355 
356 
358 {
360  libmesh_assert_equal_to (_elements[i]->id(), i);
361 
362  return _elements[i];
363 }
364 
365 
366 
367 
369 {
371  libmesh_assert_equal_to (_elements[i]->id(), i);
372 
373  return _elements[i];
374 }
375 
376 
377 
378 
380 {
381  std::map<dof_id_type, Elem *>::const_iterator it = _elements.find(i);
382  if (it != _elements.end().it)
383  {
384  const Elem * e = it->second;
385  libmesh_assert (!e || e->id() == i);
386  return e;
387  }
388 
389  return libmesh_nullptr;
390 }
391 
392 
393 
394 
396 {
397  std::map<dof_id_type, Elem *>::const_iterator it = _elements.find(i);
398  if (it != _elements.end().it)
399  {
400  Elem * e = _elements[i];
401  libmesh_assert (!e || e->id() == i);
402  return e;
403  }
404 
405  return libmesh_nullptr;
406 }
407 
408 
409 
410 
412 {
413  // Don't try to add NULLs!
414  libmesh_assert(e);
415 
416  // Trying to add an existing element is a no-op
417  if (e->valid_id() && _elements[e->id()] == e)
418  return e;
419 
420  const processor_id_type elem_procid = e->processor_id();
421 
422  if (!e->valid_id())
423  {
424  // We should only be creating new ids past the end of the range
425  // of existing ids
426  libmesh_assert_greater_equal(_next_free_unpartitioned_elem_id,
427  _max_elem_id);
428  libmesh_assert_greater_equal(_next_free_local_elem_id, _max_elem_id);
429 
430  // Use the unpartitioned ids for unpartitioned elems, and
431  // temporarily for ghost elems
433  if (elem_procid == this->processor_id())
434  next_id = &_next_free_local_elem_id;
435  e->set_id (*next_id);
436  }
437 
438  {
439  // Advance next_ids up high enough that each is pointing to an
440  // unused id and any subsequent increments will still point us
441  // to unused ids
443  static_cast<dof_id_type>(e->id()+1));
444 
447  ((_max_elem_id-1) / (this->n_processors() + 1) + 1) *
448  (this->n_processors() + 1) + this->n_processors();
451  ((_max_elem_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
452  (this->n_processors() + 1) + this->processor_id();
453 
454 #ifndef NDEBUG
455  // We need a const mapvector so we don't inadvertently create
456  // NULL entries when testing for non-NULL ones
457  const mapvector<Elem *, dof_id_type> & const_elements = _elements;
458 #endif
460  libmesh_assert(!const_elements[_next_free_local_elem_id]);
461  }
462 
463  // Don't try to overwrite existing elems
464  libmesh_assert (!_elements[e->id()]);
465 
466  _elements[e->id()] = e;
467 
468  // Try to make the cached elem data more accurate
469  if (elem_procid == this->processor_id() ||
470  elem_procid == DofObject::invalid_processor_id)
471  _n_elem++;
472 
473 #ifdef LIBMESH_ENABLE_UNIQUE_ID
474  if (!e->valid_unique_id())
475  {
476  if (processor_id() == e->processor_id())
477  {
479  _next_unique_id += this->n_processors() + 1;
480  }
481  else
482  {
485  }
486  }
487 #endif
488 
489  // Unpartitioned elems should be added on every processor
490  // And shouldn't be added in the same batch as ghost elems
491  // But we might be just adding on processor 0 to
492  // broadcast later
493  // #ifdef DEBUG
494  // if (elem_procid == DofObject::invalid_processor_id)
495  // {
496  // dof_id_type elem_id = e->id();
497  // this->comm().max(elem_id);
498  // libmesh_assert_equal_to (elem_id, e->id());
499  // }
500  // #endif
501 
502  return e;
503 }
504 
505 
506 
508 {
509  if (_elements[e->id()])
510  this->delete_elem(_elements[e->id()]);
511 
512 #ifdef LIBMESH_ENABLE_UNIQUE_ID
513  if (!e->valid_unique_id())
514  {
515  if (processor_id() == e->processor_id())
516  {
518  _next_unique_id += this->n_processors() + 1;
519  }
520  else
521  {
524  }
525  }
526 #endif
527 
528  // Try to make the cached elem data more accurate
529  processor_id_type elem_procid = e->processor_id();
530  if (elem_procid == this->processor_id() ||
531  elem_procid == DofObject::invalid_processor_id)
532  _n_elem++;
533 
534  _elements[e->id()] = e;
535 
536  return e;
537 }
538 
539 
540 
542 {
543  libmesh_assert (e);
544 
545  // Try to make the cached elem data more accurate
546  processor_id_type elem_procid = e->processor_id();
547  if (elem_procid == this->processor_id() ||
548  elem_procid == DofObject::invalid_processor_id)
549  _n_elem--;
550 
551  // Delete the element from the BoundaryInfo object
552  this->get_boundary_info().remove(e);
553 
554  // But not yet from the container; we might invalidate
555  // an iterator that way!
556 
557  //_elements.erase(e->id());
558 
559  // Instead, we set it to NULL for now
560 
561  _elements[e->id()] = libmesh_nullptr;
562 
563  // delete the element
564  delete e;
565 }
566 
567 
568 
570  const dof_id_type new_id)
571 {
572  Elem * el = _elements[old_id];
573  libmesh_assert (el);
574  libmesh_assert_equal_to (el->id(), old_id);
575 
576  el->set_id(new_id);
577  libmesh_assert (!_elements[new_id]);
578  _elements[new_id] = el;
579  _elements.erase(old_id);
580 }
581 
582 
583 
585  const dof_id_type id,
586  const processor_id_type proc_id)
587 {
588  if (_nodes.count(id))
589  {
590  Node * n = _nodes[id];
591  libmesh_assert (n);
592  libmesh_assert_equal_to (n->id(), id);
593 
594  *n = p;
595  n->processor_id() = proc_id;
596 
597  return n;
598  }
599 
600  Node * n = Node::build(p, id).release();
601  n->processor_id() = proc_id;
602 
603  return DistributedMesh::add_node(n);
604 }
605 
606 
607 
609 {
610  // Don't try to add NULLs!
611  libmesh_assert(n);
612 
613  // Trying to add an existing node is a no-op
614  if (n->valid_id() && _nodes[n->id()] == n)
615  return n;
616 
617  const processor_id_type node_procid = n->processor_id();
618 
619  if (!n->valid_id())
620  {
621  // We should only be creating new ids past the end of the range
622  // of existing ids
623  libmesh_assert_greater_equal(_next_free_unpartitioned_node_id,
624  _max_node_id);
625  libmesh_assert_greater_equal(_next_free_local_node_id, _max_node_id);
626 
627  // Use the unpartitioned ids for unpartitioned nodes,
628  // and temporarily for ghost nodes
630  if (node_procid == this->processor_id())
631  next_id = &_next_free_local_node_id;
632  n->set_id (*next_id);
633  }
634 
635  {
636  // Advance next_ids up high enough that each is pointing to an
637  // unused id and any subsequent increments will still point us
638  // to unused ids
640  static_cast<dof_id_type>(n->id()+1));
641 
644  ((_max_node_id-1) / (this->n_processors() + 1) + 1) *
645  (this->n_processors() + 1) + this->n_processors();
648  ((_max_node_id + this->n_processors() - 1) / (this->n_processors() + 1) + 1) *
649  (this->n_processors() + 1) + this->processor_id();
650 
651 #ifndef NDEBUG
652  // We need a const mapvector so we don't inadvertently create
653  // NULL entries when testing for non-NULL ones
654  const mapvector<Node *,dof_id_type> & const_nodes = _nodes;
655 #endif
658  }
659 
660  // Don't try to overwrite existing nodes
661  libmesh_assert (!_nodes[n->id()]);
662 
663  _nodes[n->id()] = n;
664 
665  // Try to make the cached node data more accurate
666  if (node_procid == this->processor_id() ||
667  node_procid == DofObject::invalid_processor_id)
668  _n_nodes++;
669 
670 #ifdef LIBMESH_ENABLE_UNIQUE_ID
671  if (!n->valid_unique_id())
672  {
673  if (processor_id() == n->processor_id())
674  {
676  _next_unique_id += this->n_processors();
677  }
678  else
679  {
682  }
683  }
684 #endif
685 
686 
687  // Unpartitioned nodes should be added on every processor
688  // And shouldn't be added in the same batch as ghost nodes
689  // But we might be just adding on processor 0 to
690  // broadcast later
691  // #ifdef DEBUG
692  // if (node_procid == DofObject::invalid_processor_id)
693  // {
694  // dof_id_type node_id = n->id();
695  // this->comm().max(node_id);
696  // libmesh_assert_equal_to (node_id, n->id());
697  // }
698  // #endif
699 
700  return n;
701 }
702 
703 
704 
706 {
707  return DistributedMesh::add_node(n);
708 }
709 
710 
711 
713 {
714  libmesh_assert(n);
715  libmesh_assert(_nodes[n->id()]);
716 
717  // Try to make the cached elem data more accurate
718  processor_id_type node_procid = n->processor_id();
719  if (node_procid == this->processor_id() ||
720  node_procid == DofObject::invalid_processor_id)
721  _n_nodes--;
722 
723  // Delete the node from the BoundaryInfo object
724  this->get_boundary_info().remove(n);
725 
726  // But not yet from the container; we might invalidate
727  // an iterator that way!
728 
729  //_nodes.erase(n->id());
730 
731  // Instead, we set it to NULL for now
732 
733  _nodes[n->id()] = libmesh_nullptr;
734 
735  // delete the node
736  delete n;
737 }
738 
739 
740 
742  const dof_id_type new_id)
743 {
744  Node * nd = _nodes[old_id];
745  libmesh_assert (nd);
746  libmesh_assert_equal_to (nd->id(), old_id);
747 
748  nd->set_id(new_id);
749 
750  // If we have nodes shipped to this processor for NodeConstraints
751  // use, then those nodes will exist in _nodes, but may not be
752  // locatable via a TopologyMap due to the insufficiency of elements
753  // connecting to them. If local refinement then wants to create a
754  // *new* node in the same location, it will initially get a temporary
755  // id, and then make_node_ids_parallel_consistent() will try to move
756  // it to the canonical id. We need to account for this case to
757  // avoid false positives and memory leaks.
758 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
759  if (_nodes[new_id])
760  {
761  libmesh_assert_equal_to (*(Point *)_nodes[new_id],
762  *(Point *)_nodes[old_id]);
763  _nodes.erase(new_id);
764  }
765 #else
766  // If we aren't shipping nodes for NodeConstraints, there should be
767  // no reason for renumbering one node onto another.
768  libmesh_assert (!_nodes[new_id]);
769 #endif
770  _nodes[new_id] = nd;
771  _nodes.erase(old_id);
772 }
773 
774 
775 
777 {
778  // Call parent clear function
779  MeshBase::clear();
780 
781 
782  // Clear our elements and nodes
783  {
784  elem_iterator_imp it = _elements.begin();
785  const elem_iterator_imp end = _elements.end();
786 
787  // There is no need to remove the elements from
788  // the BoundaryInfo data structure since we
789  // already cleared it.
790  for (; it != end; ++it)
791  delete *it;
792 
793  _elements.clear();
794  }
795 
796  // clear the nodes data structure
797  {
798  node_iterator_imp it = _nodes.begin();
799  node_iterator_imp end = _nodes.end();
800 
801  // There is no need to remove the nodes from
802  // the BoundaryInfo data structure since we
803  // already cleared it.
804  for (; it != end; ++it)
805  delete *it;
806 
807  _nodes.clear();
808  }
809 
810  // We're no longer distributed if we were before
811  _is_serial = true;
812  _is_serial_on_proc_0 = true;
813 
814  // Correct our caches
815  _n_nodes = 0;
816  _n_elem = 0;
817  _max_node_id = 0;
818  _max_elem_id = 0;
823 }
824 
825 
826 
828 {
829  // If this is a truly parallel mesh, go through the redistribution/gather/delete remote steps
830  if (!this->is_serial())
831  {
832  // Construct a MeshCommunication object to actually redistribute the nodes
833  // and elements according to the partitioner, and then to re-gather the neighbors.
835  mc.redistribute(*this);
836 
838 
839  // We probably had valid neighbors previously, so that a quality
840  // new partitioning could be found, but we might not have valid
841  // neighbor links on the newly-redistributed elements
842  this->find_neighbors();
843 
844  // Is this necessary? If we are called from prepare_for_use(), this will be called
845  // anyway... but users can always call partition directly, in which case we do need
846  // to call delete_remote_elements()...
847  //
848  // Regardless of whether it's necessary, it isn't safe. We
849  // haven't communicated new node processor_ids yet, and we can't
850  // delete nodes until we do.
851  // this->delete_remote_elements();
852  }
853 }
854 
855 
856 
858 {
859  // this->recalculate_n_partitions();
860 
861  // Partitioning changes our numbers of unpartitioned objects
863 }
864 
865 
866 
867 template <typename T>
869 {
870  // This function must be run on all processors at once
871  parallel_object_only();
872 
873  const dof_id_type pmax_node_id = this->parallel_max_node_id();
874  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
875  const dof_id_type pmax_id = std::max(pmax_node_id, pmax_elem_id);
876 
877  for (dof_id_type i=0; i != pmax_id; ++i)
878  {
879  T * obj = objects[i]; // Returns NULL if there's no map entry
880 
881  // Local lookups by id should return the requested object
882  libmesh_assert(!obj || obj->id() == i);
883 
884  // All processors with an object should agree on id
885 #ifndef NDEBUG
886  const dof_id_type dofid = obj && obj->valid_id() ?
887  obj->id() : DofObject::invalid_id;
888  libmesh_assert(this->comm().semiverify(obj ? &dofid : libmesh_nullptr));
889 #endif
890 
891  // All processors with an object should agree on processor id
892  const dof_id_type procid = obj && obj->valid_processor_id() ?
893  obj->processor_id() : DofObject::invalid_processor_id;
894  libmesh_assert(this->comm().semiverify(obj ? &procid : libmesh_nullptr));
895 
896  dof_id_type min_procid = procid;
897  this->comm().min(min_procid);
898 
899  // Either:
900  // 1.) I own this elem (min_procid == this->processor_id()) *and* I have a valid pointer to it (obj != NULL)
901  // or
902  // 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.)
903 
904  // Original assert logic
905  // libmesh_assert (min_procid != this->processor_id() || obj);
906 
907  // More human-understandable logic...
909  ((min_procid == this->processor_id()) && obj)
910  ||
911  (min_procid != this->processor_id())
912  );
913 
914 #if defined(LIBMESH_ENABLE_UNIQUE_ID) && !defined(NDEBUG)
915  // All processors with an object should agree on unique id
916  const unique_id_type uniqueid = obj ? obj->unique_id() : 0;
917  libmesh_assert(this->comm().semiverify(obj ? &uniqueid : libmesh_nullptr));
918 #endif
919  }
920 }
921 
922 
923 
925 {
928 }
929 
930 
931 
933 {
934 #ifndef NDEBUG
935  // This function must be run on all processors at once
936  parallel_object_only();
937 
938  dof_id_type pmax_elem_id = this->parallel_max_elem_id();
939 
940  for (dof_id_type i=0; i != pmax_elem_id; ++i)
941  {
942  Elem * el = _elements[i]; // Returns NULL if there's no map entry
943 
944  unsigned int p_level = el ? (el->p_level()) : libMesh::invalid_uint;
945 
946  // All processors with an active element should agree on p level
947  libmesh_assert(this->comm().semiverify((el && el->active()) ? &p_level : libmesh_nullptr));
948  }
949 #endif
950 }
951 
952 
953 
954 
956 {
957 #if defined(LIBMESH_ENABLE_AMR) && !defined(NDEBUG)
958  // This function must be run on all processors at once
959  parallel_object_only();
960 
961  dof_id_type pmax_elem_id = this->parallel_max_elem_id();
962 
963  for (dof_id_type i=0; i != pmax_elem_id; ++i)
964  {
965  Elem * el = _elements[i]; // Returns NULL if there's no map entry
966 
967  unsigned int refinement_flag = el ?
968  static_cast<unsigned int> (el->refinement_flag()) : libMesh::invalid_uint;
969  unsigned int p_refinement_flag = el ?
970  static_cast<unsigned int> (el->p_refinement_flag()) : libMesh::invalid_uint;
971 
972  libmesh_assert(this->comm().semiverify(el ? &refinement_flag : libmesh_nullptr));
973 
974  // p refinement flags aren't always kept correct on inactive
975  // ghost elements
976  libmesh_assert(this->comm().semiverify((el && el->active()) ? &p_refinement_flag : libmesh_nullptr));
977  }
978 #endif // LIBMESH_ENABLE_AMR
979 }
980 
981 
982 
983 template <typename T>
986 {
987  // This function must be run on all processors at once
988  parallel_object_only();
989 
990  typedef typename mapvector<T *,dof_id_type>::veclike_iterator object_iterator;
991 
992  // In parallel we may not know what objects other processors have.
993  // Start by figuring out how many
994  dof_id_type unpartitioned_objects = 0;
995 
996  std::vector<dof_id_type>
997  ghost_objects_from_proc(this->n_processors(), 0);
998 
999  object_iterator it = objects.begin();
1000  object_iterator end = objects.end();
1001 
1002  for (; it != end;)
1003  {
1004  T * obj = *it;
1005 
1006  // Remove any NULL container entries while we're here,
1007  // being careful not to invalidate our iterator
1008  if (!*it)
1009  objects.erase(it++);
1010  else
1011  {
1012  processor_id_type obj_procid = obj->processor_id();
1013  if (obj_procid == DofObject::invalid_processor_id)
1014  unpartitioned_objects++;
1015  else
1016  ghost_objects_from_proc[obj_procid]++;
1017  ++it;
1018  }
1019  }
1020 
1021  std::vector<dof_id_type> objects_on_proc(this->n_processors(), 0);
1022  this->comm().allgather(ghost_objects_from_proc[this->processor_id()],
1023  objects_on_proc);
1024 
1025 #ifndef NDEBUG
1026  libmesh_assert(this->comm().verify(unpartitioned_objects));
1027  for (processor_id_type p=0; p != this->n_processors(); ++p)
1028  libmesh_assert_less_equal (ghost_objects_from_proc[p], objects_on_proc[p]);
1029 #endif
1030 
1031  // We'll renumber objects in blocks by processor id
1032  std::vector<dof_id_type> first_object_on_proc(this->n_processors());
1033  for (processor_id_type i=1; i != this->n_processors(); ++i)
1034  first_object_on_proc[i] = first_object_on_proc[i-1] +
1035  objects_on_proc[i-1];
1036  dof_id_type next_id = first_object_on_proc[this->processor_id()];
1037  dof_id_type first_free_id =
1038  first_object_on_proc[this->n_processors()-1] +
1039  objects_on_proc[this->n_processors()-1] +
1040  unpartitioned_objects;
1041 
1042  // First set new local object ids and build request sets
1043  // for non-local object ids
1044 
1045  // Request sets to send to each processor
1046  std::vector<std::vector<dof_id_type>>
1047  requested_ids(this->n_processors());
1048 
1049 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1050  std::vector<std::vector<unique_id_type>>
1051  requested_unique_ids(this->n_processors());
1052 #endif
1053 
1054  // We know how many objects live on each processor, so reserve() space for
1055  // each.
1056  for (processor_id_type p=0; p != this->n_processors(); ++p)
1057  if (p != this->processor_id())
1058  {
1059  requested_ids[p].reserve(ghost_objects_from_proc[p]);
1060 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1061  requested_unique_ids[p].reserve(ghost_objects_from_proc[p]);
1062 #endif
1063  }
1064 
1065  end = objects.end();
1066  for (it = objects.begin(); it != end; ++it)
1067  {
1068  T * obj = *it;
1069  if (obj->processor_id() == this->processor_id())
1070  obj->set_id(next_id++);
1071  else if (obj->processor_id() != DofObject::invalid_processor_id)
1072  {
1073  requested_ids[obj->processor_id()].push_back(obj->id());
1074 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1075  // It's possible to have an invalid id for dofs not owned by this process.
1076  // We'll assert that they match on the receiving end.
1077  requested_unique_ids[obj->processor_id()].push_back(obj->valid_unique_id() ? obj-> unique_id() : DofObject::invalid_unique_id);
1078 #endif
1079  }
1080  }
1081 
1082  // Next set ghost object ids from other processors
1083  if (this->n_processors() > 1)
1084  {
1085  for (processor_id_type p=1; p != this->n_processors(); ++p)
1086  {
1087  // Trade my requests with processor procup and procdown
1088  processor_id_type procup = cast_int<processor_id_type>
1089  ((this->processor_id() + p) % this->n_processors());
1090  processor_id_type procdown = cast_int<processor_id_type>
1091  ((this->n_processors() + this->processor_id() - p) %
1092  this->n_processors());
1093  std::vector<dof_id_type> request_to_fill;
1094  this->comm().send_receive(procup, requested_ids[procup],
1095  procdown, request_to_fill);
1096 
1097 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1098  std::vector<unique_id_type> unique_request_to_fill;
1099  this->comm().send_receive(procup, requested_unique_ids[procup],
1100  procdown, unique_request_to_fill);
1101  std::vector<unique_id_type> new_unique_ids(unique_request_to_fill.size());
1102 #endif
1103 
1104  // Fill those requests
1105  std::vector<dof_id_type> new_ids(request_to_fill.size());
1106  for (std::size_t i=0; i != request_to_fill.size(); ++i)
1107  {
1108  T * obj = objects[request_to_fill[i]];
1109  libmesh_assert(obj);
1110  libmesh_assert_equal_to (obj->processor_id(), this->processor_id());
1111  new_ids[i] = obj->id();
1112 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1113  new_unique_ids[i] = obj->valid_unique_id() ? obj->unique_id() : DofObject::invalid_unique_id;
1114 #endif
1115 
1116  libmesh_assert_greater_equal (new_ids[i],
1117  first_object_on_proc[this->processor_id()]);
1118  libmesh_assert_less (new_ids[i],
1119  first_object_on_proc[this->processor_id()] +
1120  objects_on_proc[this->processor_id()]);
1121  }
1122 
1123  // Trade back the results
1124  std::vector<dof_id_type> filled_request;
1125  this->comm().send_receive(procdown, new_ids,
1126  procup, filled_request);
1127 
1128 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1129  std::vector<unique_id_type> unique_filled_request;
1130  this->comm().send_receive(procdown, new_unique_ids,
1131  procup, unique_filled_request);
1132 #endif
1133 
1134  // And copy the id changes we've now been informed of
1135  for (std::size_t i=0; i != filled_request.size(); ++i)
1136  {
1137  T * obj = objects[requested_ids[procup][i]];
1138  libmesh_assert (obj);
1139  libmesh_assert_equal_to (obj->processor_id(), procup);
1140  libmesh_assert_greater_equal (filled_request[i],
1141  first_object_on_proc[procup]);
1142  libmesh_assert_less (filled_request[i],
1143  first_object_on_proc[procup] +
1144  objects_on_proc[procup]);
1145  obj->set_id(filled_request[i]);
1146 
1147 #ifdef LIBMESH_ENABLE_UNIQUE_ID
1148  if (!obj->valid_unique_id() && unique_filled_request[i] != DofObject::invalid_unique_id)
1149  obj->set_unique_id() = unique_filled_request[i];
1150 #endif
1151  }
1152  }
1153  }
1154 
1155  // Next set unpartitioned object ids
1156  next_id = 0;
1157  for (processor_id_type i=0; i != this->n_processors(); ++i)
1158  next_id += objects_on_proc[i];
1159  for (it = objects.begin(); it != end; ++it)
1160  {
1161  T * obj = *it;
1162  if (obj->processor_id() == DofObject::invalid_processor_id)
1163  obj->set_id(next_id++);
1164  }
1165 
1166  // Finally shuffle around objects so that container indices
1167  // match ids
1168  end = objects.end();
1169  for (it = objects.begin(); it != end;)
1170  {
1171  T * obj = *it;
1172  if (obj) // don't try shuffling already-NULL entries
1173  {
1174  T * next = objects[obj->id()];
1175  // If we have to move this object
1176  if (next != obj)
1177  {
1178  // NULL out its original position for now
1179  // (our shuffling may put another object there shortly)
1180  *it = libmesh_nullptr;
1181 
1182  // There may already be another object with this id that
1183  // needs to be moved itself
1184  while (next)
1185  {
1186  // We shouldn't be trying to give two objects the
1187  // same id
1188  libmesh_assert_not_equal_to (next->id(), obj->id());
1189  objects[obj->id()] = obj;
1190  obj = next;
1191  next = objects[obj->id()];
1192  }
1193  objects[obj->id()] = obj;
1194  }
1195  }
1196  // Remove any container entries that were left as NULL,
1197  // being careful not to invalidate our iterator
1198  if (!*it)
1199  objects.erase(it++);
1200  else
1201  ++it;
1202  }
1203 
1204  return first_free_id;
1205 }
1206 
1207 
1209 {
1210  parallel_object_only();
1211 
1212 #ifdef DEBUG
1213  // Make sure our ids and flags are consistent
1217 #endif
1218 
1219  LOG_SCOPE("renumber_nodes_and_elements()", "DistributedMesh");
1220 
1221  std::set<dof_id_type> used_nodes;
1222 
1223  // flag the nodes we need
1224  {
1227 
1228  for (; it != end; ++it)
1229  {
1230  Elem * el = *it;
1231 
1232  for (unsigned int n=0; n != el->n_nodes(); ++n)
1233  used_nodes.insert(el->node_id(n));
1234  }
1235  }
1236 
1237  // Nodes not connected to any local elements, and NULL node entries
1238  // in our container, are deleted
1239  {
1240  node_iterator_imp it = _nodes.begin();
1241  node_iterator_imp end = _nodes.end();
1242 
1243  for (; it != end;)
1244  {
1245  Node * nd = *it;
1246  if (!nd)
1247  _nodes.erase(it++);
1248  else if (!used_nodes.count(nd->id()))
1249  {
1250  // remove any boundary information associated with
1251  // this node
1252  this->get_boundary_info().remove (nd);
1253 
1254  // delete the node
1255  delete nd;
1256 
1257  _nodes.erase(it++);
1258  }
1259  else
1260  ++it;
1261  }
1262  }
1263 
1265  {
1266  this->update_parallel_id_counts();
1267  return;
1268  }
1269 
1270  // Finally renumber all the elements
1271  _n_elem = this->renumber_dof_objects (this->_elements);
1272 
1273  // and all the remaining nodes
1274  _n_nodes = this->renumber_dof_objects (this->_nodes);
1275 
1276  // And figure out what IDs we should use when adding new nodes and
1277  // new elements
1278  this->update_parallel_id_counts();
1279 
1280  // Make sure our caches are up to date and our
1281  // DofObjects are well packed
1282 #ifdef DEBUG
1283  libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes());
1284  libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem());
1285  const dof_id_type pmax_node_id = this->parallel_max_node_id();
1286  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
1287  libmesh_assert_equal_to (this->max_node_id(), pmax_node_id);
1288  libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id);
1289  libmesh_assert_equal_to (this->n_nodes(), this->max_node_id());
1290  libmesh_assert_equal_to (this->n_elem(), this->max_elem_id());
1291 
1292  // Make sure our ids and flags are consistent
1295 
1296  // And make sure we've made our numbering monotonic
1298 #endif
1299 }
1300 
1301 
1302 
1304 {
1305  // We need access to iterators for the underlying containers,
1306  // not the mapvector<> reimplementations.
1309 
1310  // Nodes first
1311  {
1313  it = nodes.begin(),
1314  end = nodes.end();
1315 
1316  for (; it != end; ++it)
1317  if (it->second != libmesh_nullptr)
1318  it->second->set_id() = it->first;
1319  }
1320 
1321  // Elements next
1322  {
1324  it = elems.begin(),
1325  end = elems.end();
1326 
1327  for (; it != end; ++it)
1328  if (it->second != libmesh_nullptr)
1329  it->second->set_id() = it->first;
1330  }
1331 }
1332 
1333 
1334 
1336 {
1337  parallel_object_only();
1338 
1339  // Get local active elements first
1340  dof_id_type active_elements =
1342  this->active_local_elements_end()));
1343  this->comm().sum(active_elements);
1344 
1345  // Then add unpartitioned active elements, which should exist on
1346  // every processor
1347  active_elements +=
1348  static_cast<dof_id_type>(std::distance
1351  return active_elements;
1352 }
1353 
1354 
1355 
1357 {
1358 #ifdef DEBUG
1359  // Make sure our neighbor links are all fine
1361 
1362  // And our child/parent links, and our flags
1364 
1365  // Make sure our ids and flags are consistent
1368 
1369  libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes());
1370  libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem());
1371  const dof_id_type pmax_node_id = this->parallel_max_node_id();
1372  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
1373  libmesh_assert_equal_to (this->max_node_id(), pmax_node_id);
1374  libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id);
1375 #endif
1376 
1377  _is_serial = false;
1378  _is_serial_on_proc_0 = false;
1379 
1381 
1382  libmesh_assert_equal_to (this->max_elem_id(), this->parallel_max_elem_id());
1383 
1384  // Now make sure the containers actually shrink - strip
1385  // any newly-created NULL voids out of the element array
1388  for (; e_it != e_end;)
1389  if (!*e_it)
1390  _elements.erase(e_it++);
1391  else
1392  ++e_it;
1393 
1396  for (; n_it != n_end;)
1397  if (!*n_it)
1398  _nodes.erase(n_it++);
1399  else
1400  ++n_it;
1401 
1402  // We may have deleted no-longer-connected nodes or coarsened-away
1403  // elements; let's update our caches.
1404  this->update_parallel_id_counts();
1405 
1406 #ifdef DEBUG
1407  // We might not have well-packed objects if the user didn't allow us
1408  // to renumber
1409  // libmesh_assert_equal_to (this->n_nodes(), this->max_node_id());
1410  // libmesh_assert_equal_to (this->n_elem(), this->max_elem_id());
1411 
1412  // Make sure our neighbor links are all fine
1414 
1415  // And our child/parent links, and our flags
1417 
1418  // Make sure our ids and flags are consistent
1421 #endif
1422 }
1423 
1424 
1426 {
1427  // First add the elem like normal
1428  add_elem(e);
1429 
1430  // Now add it to the set that won't be deleted when we call
1431  // delete_remote_elements()
1432  _extra_ghost_elems.insert(e);
1433 }
1434 
1435 
1437 {
1438  if (_is_serial)
1439  return;
1440  MeshCommunication().allgather(*this);
1441  _is_serial = true;
1442  _is_serial_on_proc_0 = true;
1443 
1444  // Make sure our caches are up to date and our
1445  // DofObjects are well packed
1446 #ifdef DEBUG
1447  libmesh_assert_equal_to (this->n_nodes(), this->parallel_n_nodes());
1448  libmesh_assert_equal_to (this->n_elem(), this->parallel_n_elem());
1449  const dof_id_type pmax_node_id = this->parallel_max_node_id();
1450  const dof_id_type pmax_elem_id = this->parallel_max_elem_id();
1451  libmesh_assert_equal_to (this->max_node_id(), pmax_node_id);
1452  libmesh_assert_equal_to (this->max_elem_id(), pmax_elem_id);
1453 
1454  // If we've disabled renumbering we can't be sure we're contiguous
1455  // libmesh_assert_equal_to (this->n_nodes(), this->max_node_id());
1456  // libmesh_assert_equal_to (this->n_elem(), this->max_elem_id());
1457 
1458  // Make sure our neighbor links are all fine
1460 
1461  // Make sure our ids and flags are consistent
1464 #endif
1465 }
1466 
1468 {
1470  return;
1471 
1472  _is_serial_on_proc_0 = true;
1473  MeshCommunication().gather(0, *this);
1474 }
1475 
1476 
1477 } // namespace libMesh
virtual const Node * query_node_ptr(const dof_id_type i) const libmesh_override
virtual const Elem * elem_ptr(const dof_id_type i) const libmesh_override
The definition of the element_iterator struct.
Definition: mesh_base.h:1476
This mapvector templated class is intended to provide the performance characteristics of a std::map w...
Definition: mapvector.h:39
virtual unique_id_type parallel_max_unique_id() const =0
virtual element_iterator active_local_elements_begin() libmesh_override
std::map< index_t, Val > maptype
Definition: mapvector.h:42
void redistribute(DistributedMesh &mesh, bool newly_coarsened_only=false) const
This method takes a parallel distributed mesh and redistributes the elements.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:117
unique_id_type & set_unique_id()
Definition: dof_object.h:662
bool _skip_renumber_nodes_and_elements
If this is true then renumbering will be kept to a minimum.
Definition: mesh_base.h:1389
bool valid_id() const
Definition: dof_object.h:674
mapvector< Elem *, dof_id_type > _elements
The 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
bool active() const
Definition: elem.h:2257
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value.
Definition: libmesh.h:184
virtual dof_id_type n_elem() const libmesh_override
virtual void copy_nodes_and_elements(const UnstructuredMesh &other_mesh, const bool skip_find_neighbors=false)
Deep copy of another unstructured mesh class (used by subclass copy constructors) ...
unsigned int p_level() const
Definition: elem.h:2422
void max(T &r) const
Take a local variable and replace it with the maximum of it&#39;s values on all processors.
void min(T &r) const
Take a local variable and replace it with the minimum of it&#39;s values on all processors.
dof_id_type n_local_nodes() const
Definition: mesh_base.h:272
bool _is_serial_on_proc_0
A boolean remembering whether we&#39;re serialized to proc 0 or not.
dof_id_type _n_nodes
Cached data from the last renumber_nodes_and_elements call.
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:420
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
dof_id_type _next_free_local_node_id
Guaranteed globally unused IDs for use when adding new nodes or elements.
void remove(const Node *node)
Removes the boundary conditions associated with node node, if any exist.
dof_id_type n_unpartitioned_elem() const
Definition: mesh_base.h:378
processor_id_type n_processors() const
This is the base class from which all geometric element types are derived.
Definition: elem.h:89
uint8_t processor_id_type
Definition: id_types.h:99
virtual void redistribute() libmesh_override
Redistribute elements between processors.
virtual element_iterator active_local_elements_end() libmesh_override
const class libmesh_nullptr_t libmesh_nullptr
static UniquePtr< Node > build(const Node &n)
Definition: node.h:298
bool _is_serial
A boolean remembering whether we&#39;re serialized or not.
dof_id_type parallel_max_elem_id() const
UniquePtr< Partitioner > _partitioner
A partitioner to use at each prepare_for_use().
Definition: mesh_base.h:1370
IterBase * end
Also have a polymorphic pointer to the end object, this prevents iterating past the end...
The libMesh namespace provides an interface to certain functionality in the library.
virtual void gather_to_zero() libmesh_override
Gathers all elements and nodes of the mesh onto processor zero.
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...
long double max(long double a, double b)
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true) libmesh_override
Other functions from MeshBase requiring re-definition.
The ParmetisPartitioner uses the Parmetis graph partitioner to partition the elements.
Real distance(const Point &p)
void gather(const processor_id_type root_id, DistributedMesh &) const
This method takes an input DistributedMesh which may be distributed among all the processors...
void libmesh_assert_valid_parallel_flags() const
Verify refinement_flag and p_refinement_flag consistency of our elements containers.
virtual Node * insert_node(Node *n) libmesh_override
Calls add_node().
virtual const Point & point(const dof_id_type i) const libmesh_override
virtual void update_parallel_id_counts() libmesh_override
Updates parallel caches so that methods like n_elem() accurately reflect changes on other processors...
dof_id_type & set_id()
Definition: dof_object.h:641
bool valid_unique_id() const
Definition: dof_object.h:682
libmesh_assert(j)
std::unique_ptr< T > UniquePtr
Definition: auto_ptr.h:46
virtual unsigned int n_nodes() const =0
dof_id_type parallel_max_node_id() const
unique_id_type _next_unique_id
The next available unique id for assigning ids to DOF objects.
Definition: mesh_base.h:1376
virtual void fix_broken_node_and_element_numbering() libmesh_override
There is no reason for a user to ever call this function.
virtual Node * add_node(Node *n) libmesh_override
Add Node n to the end of the vertex array.
void send_receive(const unsigned int dest_processor_id, const T1 &send, const unsigned int source_processor_id, T2 &recv, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag) const
Send data send to one processor while simultaneously receiving other data recv from a (potentially di...
dof_id_type renumber_dof_objects(mapvector< T *, dof_id_type > &)
Renumber a parallel objects container.
This is the MeshCommunication class.
mapvector< Node *, dof_id_type > _nodes
The vertices (spatial coordinates) of the mesh.
virtual dof_id_type n_active_elem() const libmesh_override
static const unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
Definition: dof_object.h:329
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
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...
The UnstructuredMesh class is derived from the MeshBase class.
virtual const Elem * query_elem_ptr(const dof_id_type i) const libmesh_override
virtual dof_id_type n_nodes() const libmesh_override
void erase(index_t i)
Definition: mapvector.h:117
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:324
virtual dof_id_type max_node_id() const libmesh_override
dof_id_type n_unpartitioned_nodes() const
Definition: mesh_base.h:278
virtual bool is_serial() const libmesh_override
RefinementState p_refinement_flag() const
Definition: elem.h:2521
virtual const Node * node_ptr(const dof_id_type i) const libmesh_override
veclike_iterator end()
Definition: mapvector.h:133
virtual ~DistributedMesh()
Destructor.
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
virtual void clear()
Deletes all the data that are currently stored.
Definition: mesh_base.C:285
dof_id_type _next_free_unpartitioned_node_id
virtual void allgather() libmesh_override
Gathers all elements and nodes of the mesh onto every processor.
virtual Elem * insert_elem(Elem *e) libmesh_override
Insert elem e to the element array, preserving its id and replacing/deleting any existing element wit...
virtual Elem * add_elem(Elem *e) libmesh_override
Add elem e to the end of the element array.
UnstructuredMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
Constructor.
virtual void renumber_nodes_and_elements() libmesh_override
Remove NULL elements from arrays.
static const unsigned int next[3]
A lookup table for the increment modulo 3 operation, for iterating through the three nodes per elemen...
dof_id_type n_local_elem() const
Definition: mesh_base.h:372
virtual element_iterator active_pid_elements_begin(processor_id_type proc_id) libmesh_override
virtual void renumber_node(dof_id_type old_id, dof_id_type new_id) libmesh_override
Changes the id of node old_id, both by changing node(old_id)->id() and by moving node(old_id) in the ...
void libmesh_assert_valid_parallel_p_levels() const
Verify p_level consistency of our elements containers.
dof_id_type _next_free_unpartitioned_elem_id
bool verify(const T &r, const Communicator &comm=Communicator_World)
virtual dof_id_type parallel_n_nodes() const libmesh_override
DistributedMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
Constructor.
veclike_iterator begin()
Definition: mapvector.h:125
const Parallel::Communicator & comm() const
virtual void renumber_elem(dof_id_type old_id, dof_id_type new_id) libmesh_override
Changes the id of element old_id, both by changing elem(old_id)->id() and by moving elem(old_id) in t...
void allgather(DistributedMesh &mesh) const
This method takes an input DistributedMesh which may be distributed among all the processors...
virtual void update_post_partitioning() libmesh_override
Recalculate cached data after elements and nodes have been repartitioned.
RefinementState refinement_flag() const
Definition: elem.h:2505
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...
unique_id_type _next_unpartitioned_unique_id
The next available unique id for assigning ids to unpartitioned DOF objects.
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1831
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
void delete_remote_elements(DistributedMesh &, const std::set< Elem * > &) const
This method takes an input DistributedMesh which may be distributed among all the processors...
dof_id_type id() const
Definition: dof_object.h:632
void sum(T &r) const
Take a local variable and replace it with the sum of it&#39;s values on all processors.
virtual dof_id_type parallel_n_elem() const libmesh_override
virtual element_iterator elements_begin() libmesh_override
Elem iterator accessor functions.
dof_id_type _next_free_local_elem_id
processor_id_type processor_id()
Definition: libmesh_base.h:96
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
virtual void delete_elem(Elem *e) libmesh_override
Removes element e from the mesh.
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) libmesh_override
functions for adding /deleting nodes elements.
virtual dof_id_type max_elem_id() const libmesh_override
virtual void clear() libmesh_override
Clear all internal data.
virtual unique_id_type parallel_max_unique_id() const libmesh_override
uint8_t dof_id_type
Definition: id_types.h:64
processor_id_type processor_id() const
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
virtual void libmesh_assert_valid_parallel_ids() const libmesh_override
Verify id and processor_id consistency of our elements and nodes containers.
processor_id_type n_processors()
Definition: libmesh_base.h:88
virtual element_iterator active_pid_elements_end(processor_id_type proc_id) libmesh_override
virtual void delete_node(Node *n) libmesh_override
Removes the Node n from the mesh.
void allgather(const T &send, std::vector< T > &recv) const
Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that proc...
virtual element_iterator elements_end() libmesh_override
virtual void delete_remote_elements() libmesh_override
Deletes all nonlocal elements of the mesh except for "ghosts" which touch a local element...