libMesh
unstructured_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 // C++ includes
21 #include <fstream>
22 #include <sstream>
23 #include <iomanip>
24 #include <unordered_map>
25 
26 // C includes
27 #include <sys/types.h> // for pid_t
28 #include <unistd.h> // for getpid(), unlink()
29 
30 // Local includes
31 #include "libmesh/boundary_info.h"
32 #include "libmesh/ghosting_functor.h"
33 #include "libmesh/unstructured_mesh.h"
34 #include "libmesh/libmesh_logging.h"
35 #include "libmesh/elem.h"
36 #include "libmesh/mesh_tools.h" // For n_levels
37 #include "libmesh/parallel.h"
38 #include "libmesh/remote_elem.h"
39 
40 // For most I/O
41 #include "libmesh/namebased_io.h"
42 
43 
44 
45 namespace libMesh
46 {
47 
48 
49 // ------------------------------------------------------------
50 // UnstructuredMesh class member functions
52  unsigned char d) :
53  MeshBase (comm_in,d)
54 {
56 }
57 
58 
59 
60 #ifndef LIBMESH_DISABLE_COMMWORLD
61 #ifdef LIBMESH_ENABLE_DEPRECATED
63  MeshBase (d)
64 {
65  libmesh_deprecated();
67 }
68 #endif
69 #endif
70 
71 
72 
74  const bool skip_find_neighbors)
75 {
76  LOG_SCOPE("copy_nodes_and_elements()", "UnstructuredMesh");
77 
78  // We're assuming our subclass data needs no copy
79  libmesh_assert_equal_to (_n_parts, other_mesh._n_parts);
80  libmesh_assert_equal_to (_is_prepared, other_mesh._is_prepared);
81 
82  // We're assuming the other mesh has proper element number ordering,
83  // so that we add parents before their children.
84 #ifdef DEBUG
86 #endif
87 
88  //Copy in Nodes
89  {
90  //Preallocate Memory if necessary
91  this->reserve_nodes(other_mesh.n_nodes());
92 
93  for (const auto & oldn : other_mesh.node_ptr_range())
94  {
95  // Add new nodes in old node Point locations
96 #ifdef LIBMESH_ENABLE_UNIQUE_ID
97  Node * newn =
98 #endif
99  this->add_point(*oldn, oldn->id(), oldn->processor_id());
100 
101 #ifdef LIBMESH_ENABLE_UNIQUE_ID
102  newn->set_unique_id() = oldn->unique_id();
103 #endif
104  }
105  }
106 
107  //Copy in Elements
108  {
109  //Preallocate Memory if necessary
110  this->reserve_elem(other_mesh.n_elem());
111 
112  // Declare a map linking old and new elements, needed to copy the neighbor lists
113  typedef std::unordered_map<const Elem *, Elem *> map_type;
114  map_type old_elems_to_new_elems;
115 
116  // Loop over the elements
117  for (const auto & old : other_mesh.element_ptr_range())
118  {
119  // Build a new element
120  Elem * newparent = old->parent() ?
121  this->elem_ptr(old->parent()->id()) : libmesh_nullptr;
122  UniquePtr<Elem> ap = Elem::build(old->type(), newparent);
123  Elem * el = ap.release();
124 
125  el->subdomain_id() = old->subdomain_id();
126 
127  for (auto s : old->side_index_range())
128  if (old->neighbor_ptr(s) == remote_elem)
129  el->set_neighbor(s, const_cast<RemoteElem *>(remote_elem));
130 
131 #ifdef LIBMESH_ENABLE_AMR
132  if (old->has_children())
133  for (unsigned int c = 0, nc = old->n_children(); c != nc; ++c)
134  if (old->child_ptr(c) == remote_elem)
135  el->add_child(const_cast<RemoteElem *>(remote_elem), c);
136 
137  //Create the parent's child pointers if necessary
138  if (newparent)
139  {
140  unsigned int oldc = old->parent()->which_child_am_i(old);
141  newparent->add_child(el, oldc);
142  }
143 
144  // Copy the refinement flags
145  el->set_refinement_flag(old->refinement_flag());
146 
147  // Use hack_p_level since we may not have sibling elements
148  // added yet
149  el->hack_p_level(old->p_level());
150 
151  el->set_p_refinement_flag(old->p_refinement_flag());
152 #endif // #ifdef LIBMESH_ENABLE_AMR
153 
154  //Assign all the nodes
155  for (auto i : el->node_index_range())
156  el->set_node(i) = this->node_ptr(old->node_id(i));
157 
158  // And start it off in the same subdomain
159  el->processor_id() = old->processor_id();
160 
161  // Give it the same element and unique ids
162  el->set_id(old->id());
163 
164 #ifdef LIBMESH_ENABLE_UNIQUE_ID
165  el->set_unique_id() = old->unique_id();
166 #endif
167 
168  //Hold onto it
169  if (!skip_find_neighbors)
170  {
171  this->add_elem(el);
172  }
173  else
174  {
175  Elem * new_el = this->add_elem(el);
176  old_elems_to_new_elems[old] = new_el;
177  }
178 
179  // Add the link between the original element and this copy to the map
180  if (skip_find_neighbors)
181  old_elems_to_new_elems[old] = el;
182  }
183 
184  // Loop (again) over the elements to fill in the neighbors
185  if (skip_find_neighbors)
186  {
187  for (const auto & old_elem : other_mesh.element_ptr_range())
188  {
189  Elem * new_elem = old_elems_to_new_elems[old_elem];
190  for (auto s : old_elem->side_index_range())
191  {
192  const Elem * old_neighbor = old_elem->neighbor_ptr(s);
193  Elem * new_neighbor = old_elems_to_new_elems[old_neighbor];
194  new_elem->set_neighbor(s, new_neighbor);
195  }
196  }
197  }
198  }
199 
200  //Finally prepare the new Mesh for use. Keep the same numbering and
201  //partitioning for now.
202  this->allow_renumbering(false);
203  this->allow_remote_element_removal(false);
204  this->skip_partitioning(true);
205 
206  this->prepare_for_use(false, skip_find_neighbors);
207 
208  //But in the long term, use the same renumbering and partitioning
209  //policies as our source mesh.
210  this->allow_renumbering(other_mesh.allow_renumbering());
212  this->skip_partitioning(other_mesh.skip_partitioning());
213 }
214 
215 
216 
218 {
219  // this->clear (); // Nothing to clear at this level
220 
221  libmesh_exceptionless_assert (!libMesh::closed());
222 }
223 
224 
225 
226 
227 
228 void UnstructuredMesh::find_neighbors (const bool reset_remote_elements,
229  const bool reset_current_list)
230 {
231  // We might actually want to run this on an empty mesh
232  // (e.g. the boundary mesh for a nonexistent bcid!)
233  // libmesh_assert_not_equal_to (this->n_nodes(), 0);
234  // libmesh_assert_not_equal_to (this->n_elem(), 0);
235 
236  // This function must be run on all processors at once
237  parallel_object_only();
238 
239  LOG_SCOPE("find_neighbors()", "Mesh");
240 
241  const element_iterator el_end = this->elements_end();
242 
243  //TODO:[BSK] This should be removed later?!
244  if (reset_current_list)
245  for (element_iterator el = this->elements_begin(); el != el_end; ++el)
246  {
247  Elem * e = *el;
248  for (auto s : e->side_index_range())
249  if (e->neighbor_ptr(s) != remote_elem ||
250  reset_remote_elements)
252  }
253 
254  // Find neighboring elements by first finding elements
255  // with identical side keys and then check to see if they
256  // are neighbors
257  {
258  // data structures -- Use the hash_multimap if available
259  typedef unsigned int key_type;
260  typedef std::pair<Elem *, unsigned char> val_type;
261  typedef std::pair<key_type, val_type> key_val_pair;
262 
263  typedef std::unordered_multimap<key_type, val_type> map_type;
264 
265  // A map from side keys to corresponding elements & side numbers
266  map_type side_to_elem_map;
267 
268 
269 
270  for (element_iterator el = this->elements_begin(); el != el_end; ++el)
271  {
272  Elem * element = *el;
273 
274  for (auto ms : element->side_index_range())
275  {
276  next_side:
277  // If we haven't yet found a neighbor on this side, try.
278  // Even if we think our neighbor is remote, that
279  // information may be out of date.
280  if (element->neighbor_ptr(ms) == libmesh_nullptr ||
281  element->neighbor_ptr(ms) == remote_elem)
282  {
283  // Get the key for the side of this element
284  const unsigned int key = element->key(ms);
285 
286  // Look for elements that have an identical side key
287  std::pair <map_type::iterator, map_type::iterator>
288  bounds = side_to_elem_map.equal_range(key);
289 
290  // May be multiple keys, check all the possible
291  // elements which _might_ be neighbors.
292  if (bounds.first != bounds.second)
293  {
294  // Get the side for this element
295  const UniquePtr<Elem> my_side(element->side_ptr(ms));
296 
297  // Look at all the entries with an equivalent key
298  while (bounds.first != bounds.second)
299  {
300  // Get the potential element
301  Elem * neighbor = bounds.first->second.first;
302 
303  // Get the side for the neighboring element
304  const unsigned int ns = bounds.first->second.second;
305  const UniquePtr<Elem> their_side(neighbor->side_ptr(ns));
306  //libmesh_assert(my_side.get());
307  //libmesh_assert(their_side.get());
308 
309  // If found a match with my side
310  //
311  // We need special tests here for 1D:
312  // since parents and children have an equal
313  // side (i.e. a node), we need to check
314  // ns != ms, and we also check level() to
315  // avoid setting our neighbor pointer to
316  // any of our neighbor's descendants
317  if ((*my_side == *their_side) &&
318  (element->level() == neighbor->level()) &&
319  ((element->dim() != 1) || (ns != ms)))
320  {
321  // So share a side. Is this a mixed pair
322  // of subactive and active/ancestor
323  // elements?
324  // If not, then we're neighbors.
325  // If so, then the subactive's neighbor is
326 
327  if (element->subactive() ==
328  neighbor->subactive())
329  {
330  // an element is only subactive if it has
331  // been coarsened but not deleted
332  element->set_neighbor (ms,neighbor);
333  neighbor->set_neighbor(ns,element);
334  }
335  else if (element->subactive())
336  {
337  element->set_neighbor(ms,neighbor);
338  }
339  else if (neighbor->subactive())
340  {
341  neighbor->set_neighbor(ns,element);
342  }
343  side_to_elem_map.erase (bounds.first);
344 
345  // get out of this nested crap
346  goto next_side;
347  }
348 
349  ++bounds.first;
350  }
351  }
352 
353  // didn't find a match...
354  // Build the map entry for this element
355  key_val_pair kvp;
356 
357  kvp.first = key;
358  kvp.second.first = element;
359  kvp.second.second = ms;
360  side_to_elem_map.insert (kvp);
361  }
362  }
363  }
364  }
365 
366 #ifdef LIBMESH_ENABLE_AMR
367 
395  const unsigned int n_levels = MeshTools::n_levels(*this);
396  for (unsigned int level = 1; level < n_levels; ++level)
397  {
398  element_iterator end = this->level_elements_end(level);
399  for (element_iterator el = this->level_elements_begin(level);
400  el != end; ++el)
401  {
402  Elem * current_elem = *el;
403  libmesh_assert(current_elem);
404  Elem * parent = current_elem->parent();
405  libmesh_assert(parent);
406  const unsigned int my_child_num = parent->which_child_am_i(current_elem);
407 
408  for (auto s : current_elem->side_index_range())
409  {
410  if (current_elem->neighbor_ptr(s) == libmesh_nullptr ||
411  (current_elem->neighbor_ptr(s) == remote_elem &&
412  parent->is_child_on_side(my_child_num, s)))
413  {
414  Elem * neigh = parent->neighbor_ptr(s);
415 
416  // If neigh was refined and had non-subactive children
417  // made remote earlier, then our current elem should
418  // actually have one of those remote children as a
419  // neighbor
420  if (neigh &&
421  (neigh->ancestor() ||
422  // If neigh has subactive children which should have
423  // matched as neighbors of the current element but
424  // did not, then those likewise must be remote
425  // children.
426  (current_elem->subactive() && neigh->has_children() &&
427  (neigh->level()+1) == current_elem->level())))
428  {
429 #ifdef DEBUG
430  // Let's make sure that "had children made remote"
431  // situation is actually the case
432  libmesh_assert(neigh->has_children());
433  bool neigh_has_remote_children = false;
434  for (auto & child : neigh->child_ref_range())
435  if (&child == remote_elem)
436  neigh_has_remote_children = true;
437  libmesh_assert(neigh_has_remote_children);
438 
439  // And let's double-check that we don't have
440  // a remote_elem neighboring an active local element
441  if (current_elem->active())
442  libmesh_assert_not_equal_to (current_elem->processor_id(),
443  this->processor_id());
444 #endif // DEBUG
445  neigh = const_cast<RemoteElem *>(remote_elem);
446  }
447  // If neigh and current_elem are more than one level
448  // apart, figuring out whether we have a remote
449  // neighbor here becomes much harder.
450  else if (neigh && (current_elem->subactive() &&
451  neigh->has_children()))
452  {
453  // Find the deepest descendant of neigh which
454  // we could consider for a neighbor. If we run
455  // out of neigh children, then that's our
456  // neighbor. If we find a potential neighbor
457  // with remote_children and we don't find any
458  // potential neighbors among its non-remote
459  // children, then our neighbor must be remote.
460  while (neigh != remote_elem &&
461  neigh->has_children())
462  {
463  bool found_neigh = false;
464  for (unsigned int c = 0, nc = neigh->n_children();
465  !found_neigh && c != nc; ++c)
466  {
467  Elem * child = neigh->child_ptr(c);
468  if (child == remote_elem)
469  continue;
470  for (auto ncn : child->neighbor_ptr_range())
471  {
472  if (ncn != remote_elem &&
473  ncn->is_ancestor_of(current_elem))
474  {
475  neigh = ncn;
476  found_neigh = true;
477  break;
478  }
479  }
480  }
481  if (!found_neigh)
482  neigh = const_cast<RemoteElem *>(remote_elem);
483  }
484  }
485  current_elem->set_neighbor(s, neigh);
486 #ifdef DEBUG
487  if (neigh != libmesh_nullptr && neigh != remote_elem)
488  // We ignore subactive elements here because
489  // we don't care about neighbors of subactive element.
490  if ((!neigh->active()) && (!current_elem->subactive()))
491  {
492  libMesh::err << "On processor " << this->processor_id()
493  << std::endl;
494  libMesh::err << "Bad element ID = " << current_elem->id()
495  << ", Side " << s << ", Bad neighbor ID = " << neigh->id() << std::endl;
496  libMesh::err << "Bad element proc_ID = " << current_elem->processor_id()
497  << ", Bad neighbor proc_ID = " << neigh->processor_id() << std::endl;
498  libMesh::err << "Bad element size = " << current_elem->hmin()
499  << ", Bad neighbor size = " << neigh->hmin() << std::endl;
500  libMesh::err << "Bad element center = " << current_elem->centroid()
501  << ", Bad neighbor center = " << neigh->centroid() << std::endl;
502  libMesh::err << "ERROR: "
503  << (current_elem->active()?"Active":"Ancestor")
504  << " Element at level "
505  << current_elem->level() << std::endl;
506  libMesh::err << "with "
507  << (parent->active()?"active":
508  (parent->subactive()?"subactive":"ancestor"))
509  << " parent share "
510  << (neigh->subactive()?"subactive":"ancestor")
511  << " neighbor at level " << neigh->level()
512  << std::endl;
513  NameBasedIO(*this).write ("bad_mesh.gmv");
514  libmesh_error_msg("Problematic mesh written to bad_mesh.gmv.");
515  }
516 #endif // DEBUG
517  }
518  }
519 
520  // We can skip to the next element if we're full-dimension
521  // and therefore don't have any interior parents
522  if (current_elem->dim() >= LIBMESH_DIM)
523  continue;
524 
525  // We have no interior parents unless we can find one later
526  current_elem->set_interior_parent(libmesh_nullptr);
527 
528  Elem * pip = parent->interior_parent();
529 
530  if (!pip)
531  continue;
532 
533  // If there's no interior_parent children, whether due to a
534  // remote element or a non-conformity, then there's no
535  // children to search.
536  if (pip == remote_elem || pip->active())
537  {
538  current_elem->set_interior_parent(pip);
539  continue;
540  }
541 
542  // For node comparisons we'll need a sensible tolerance
543  Real node_tolerance = current_elem->hmin() * TOLERANCE;
544 
545  // Otherwise our interior_parent should be a child of our
546  // parent's interior_parent.
547  for (auto & child : pip->child_ref_range())
548  {
549  // If we have a remote_elem, that might be our
550  // interior_parent. We'll set it provisionally now and
551  // keep trying to find something better.
552  if (&child == remote_elem)
553  {
554  current_elem->set_interior_parent
555  (const_cast<RemoteElem *>(remote_elem));
556  continue;
557  }
558 
559  bool child_contains_our_nodes = true;
560  for (auto & n : current_elem->node_ref_range())
561  {
562  bool child_contains_this_node = false;
563  for (auto & cn : child.node_ref_range())
564  if (cn.absolute_fuzzy_equals
565  (n, node_tolerance))
566  {
567  child_contains_this_node = true;
568  break;
569  }
570  if (!child_contains_this_node)
571  {
572  child_contains_our_nodes = false;
573  break;
574  }
575  }
576  if (child_contains_our_nodes)
577  {
578  current_elem->set_interior_parent(&child);
579  break;
580  }
581  }
582 
583  // We should have found *some* interior_parent at this
584  // point, whether semilocal or remote.
585  libmesh_assert(current_elem->interior_parent());
586  }
587  }
588 
589 #endif // AMR
590 
591 
592 #ifdef DEBUG
594  !reset_remote_elements);
596 #endif
597 }
598 
599 
600 
601 void UnstructuredMesh::read (const std::string & name,
602  void *,
603  bool skip_renumber_nodes_and_elements,
604  bool skip_find_neighbors)
605 {
606  // Set the skip_renumber_nodes_and_elements flag on all processors
607  // if necessary.
608  // This ensures that renumber_nodes_and_elements is *not* called
609  // during prepare_for_use() for certain types of mesh files.
610  // This is required in cases where there is an associated solution
611  // file which expects a certain ordering of the nodes.
612  if (name.rfind(".gmv") + 4 == name.size())
613  this->allow_renumbering(false);
614 
615  NameBasedIO(*this).read(name);
616 
617  if (skip_renumber_nodes_and_elements)
618  {
619  // Use MeshBase::allow_renumbering() yourself instead.
620  libmesh_deprecated();
621  this->allow_renumbering(false);
622  }
623 
624  // Done reading the mesh. Now prepare it for use.
625  this->prepare_for_use(/*skip_renumber (deprecated)*/ false,
626  skip_find_neighbors);
627 }
628 
629 
630 
631 void UnstructuredMesh::write (const std::string & name)
632 {
633  LOG_SCOPE("write()", "Mesh");
634 
635  NameBasedIO(*this).write(name);
636 }
637 
638 
639 
640 void UnstructuredMesh::write (const std::string & name,
641  const std::vector<Number> & v,
642  const std::vector<std::string> & vn)
643 {
644  LOG_SCOPE("write()", "Mesh");
645 
646  NameBasedIO(*this).write_nodal_data(name, v, vn);
647 }
648 
649 
650 
651 
652 
654  const processor_id_type pid) const
655 {
656 
657  // Issue a warning if the number the number of processors
658  // currently available is less that that requested for
659  // partitioning. This is not necessarily an error since
660  // you may run on one processor and still partition the
661  // mesh into several partitions.
662 #ifdef DEBUG
663  if (this->n_processors() < pid)
664  {
665  libMesh::out << "WARNING: You are creating a "
666  << "mesh for a processor id (="
667  << pid
668  << ") greater than "
669  << "the number of processors available for "
670  << "the calculation. (="
671  << this->n_processors()
672  << ")."
673  << std::endl;
674  }
675 #endif
676 
677  // Create iterators to loop over the list of elements
678  // const_active_pid_elem_iterator it(this->elements_begin(), pid);
679  // const const_active_pid_elem_iterator it_end(this->elements_end(), pid);
680 
682  const const_element_iterator it_end = this->active_pid_elements_end(pid);
683 
684  this->create_submesh (pid_mesh, it, it_end);
685 }
686 
687 
688 
689 
690 
691 
692 
695  const const_element_iterator & it_end) const
696 {
697  // Just in case the subdomain_mesh already has some information
698  // in it, get rid of it.
699  new_mesh.clear();
700 
701  // If we're not serial, our submesh isn't either.
702  // There are no remote elements to delete on an empty mesh, but
703  // calling the method to do so marks the mesh as parallel.
704  if (!this->is_serial())
705  new_mesh.delete_remote_elements();
706 
707  // Fail if (*this == new_mesh), we cannot create a submesh inside ourself!
708  // This may happen if the user accidentally passes the original mesh into
709  // this function! We will check this by making sure we did not just
710  // clear ourself.
711  libmesh_assert_not_equal_to (this->n_nodes(), 0);
712  libmesh_assert_not_equal_to (this->n_elem(), 0);
713 
714  // Container to catch boundary IDs handed back by BoundaryInfo
715  std::vector<boundary_id_type> bc_ids;
716 
717  for (; it != it_end; ++it)
718  {
719  const Elem * old_elem = *it;
720 
721  // Add an equivalent element type to the new_mesh.
722  // Copy ids for this element.
723  Elem * new_elem = Elem::build(old_elem->type()).release();
724  new_elem->set_id() = old_elem->id();
725 #ifdef LIBMESH_ENABLE_UNIQUE_ID
726  new_elem->set_unique_id() = old_elem->unique_id();
727 #endif
728  new_elem->subdomain_id() = old_elem->subdomain_id();
729  new_elem->processor_id() = old_elem->processor_id();
730 
731  new_mesh.add_elem (new_elem);
732 
733  libmesh_assert(new_elem);
734 
735  // Loop over the nodes on this element.
736  for (auto n : old_elem->node_index_range())
737  {
738  const dof_id_type this_node_id = old_elem->node_id(n);
739 
740  // Add this node to the new mesh if it's not there already
741  if (!new_mesh.query_node_ptr(this_node_id))
742  {
743 #ifdef LIBMESH_ENABLE_UNIQUE_ID
744  Node *newn =
745 #endif
746  new_mesh.add_point (old_elem->point(n),
747  this_node_id,
748  old_elem->node_ptr(n)->processor_id());
749 
750 #ifdef LIBMESH_ENABLE_UNIQUE_ID
751  newn->set_unique_id() = old_elem->node_ptr(n)->unique_id();
752 #endif
753  }
754 
755  // Define this element's connectivity on the new mesh
756  new_elem->set_node(n) = new_mesh.node_ptr(this_node_id);
757  }
758 
759  // Maybe add boundary conditions for this element
760  for (auto s : old_elem->side_index_range())
761  {
762  this->get_boundary_info().boundary_ids(old_elem, s, bc_ids);
763  new_mesh.get_boundary_info().add_side (new_elem, s, bc_ids);
764  }
765  } // end loop over elements
766 
767  // Prepare the new_mesh for use
768  new_mesh.prepare_for_use(/*skip_renumber =*/false);
769 }
770 
771 
772 
773 #ifdef LIBMESH_ENABLE_AMR
775 {
776  LOG_SCOPE ("contract()", "Mesh");
777 
778  // Flag indicating if this call actually changes the mesh
779  bool mesh_changed = false;
780 
783 
784 #ifdef DEBUG
785  for ( ; in != end; ++in)
786  if (*in != libmesh_nullptr)
787  {
788  Elem * el = *in;
789  libmesh_assert(el->active() || el->subactive() || el->ancestor());
790  }
791  in = elements_begin();
792 #endif
793 
794  // Loop over the elements.
795  for ( ; in != end; ++in)
796  if (*in != libmesh_nullptr)
797  {
798  Elem * el = *in;
799 
800  // Delete all the subactive ones
801  if (el->subactive())
802  {
803  // No level-0 element should be subactive.
804  // Note that we CAN'T test elem->level(), as that
805  // touches elem->parent()->dim(), and elem->parent()
806  // might have already been deleted!
807  libmesh_assert(el->parent());
808 
809  // Delete the element
810  // This just sets a pointer to NULL, and doesn't
811  // invalidate any iterators
812  this->delete_elem(el);
813 
814  // the mesh has certainly changed
815  mesh_changed = true;
816  }
817  else
818  {
819  // Compress all the active ones
820  if (el->active())
821  el->contract();
822  else
823  libmesh_assert (el->ancestor());
824  }
825  }
826 
827  // Strip any newly-created NULL voids out of the element array
829 
830  // FIXME: Need to understand why deleting subactive children
831  // invalidates the point locator. For now we will clear it explicitly
832  this->clear_point_locator();
833 
834  // Allow our GhostingFunctor objects to reinit if necessary.
835  std::set<GhostingFunctor *>::iterator gf_it = this->ghosting_functors_begin();
836  const std::set<GhostingFunctor *>::iterator gf_end = this->ghosting_functors_end();
837  for (; gf_it != gf_end; ++gf_it)
838  {
839  GhostingFunctor *gf = *gf_it;
840  libmesh_assert(gf);
841  gf->mesh_reinit();
842  }
843 
844  return mesh_changed;
845 }
846 #endif // #ifdef LIBMESH_ENABLE_AMR
847 
848 } // namespace libMesh
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:39
The definition of the element_iterator struct.
Definition: mesh_base.h:1476
virtual void mesh_reinit()
GhostingFunctor subclasses which cache data will need to initialize that cache.
bool ancestor() const
Definition: elem.C:1574
OStreamProxy err
virtual void read(const std::string &mesh_file) libmesh_override
This method implements reading a mesh from a specified file.
Definition: namebased_io.C:62
bool has_children() const
Definition: elem.h:2295
bool closed()
Checks that the library has been closed.
Definition: libmesh.C:281
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:117
This class supports simple reads and writes in any libMesh-supported format, by dispatching to one of...
Definition: namebased_io.h:44
unique_id_type & set_unique_id()
Definition: dof_object.h:662
virtual void reserve_nodes(const dof_id_type nn)=0
Reserves space for a known number of nodes.
virtual void read(const std::string &name, void *mesh_data=libmesh_nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false) libmesh_override
Reads the file specified by name.
In parallel meshes where a ghost element has neighbors which do not exist on the local processor...
Definition: remote_elem.h:44
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:1941
A Node is like a Point, but with more information.
Definition: node.h:52
Encapsulates the MPI_Comm object.
Definition: parallel.h:657
void create_pid_mesh(UnstructuredMesh &pid_mesh, const processor_id_type pid) const
Generates a new mesh containing all the elements which are assigned to processor pid.
This abstract base class defines the interface by which library code and user code can report associa...
bool subactive() const
Definition: elem.h:2275
virtual bool is_serial() const
Definition: mesh_base.h:140
void libmesh_assert_valid_amr_interior_parents(const MeshBase &mesh)
A function for verifying that any interior_parent pointers on elements are consistent with AMR (paren...
Definition: mesh_tools.C:1133
bool active() const
Definition: elem.h:2257
static UniquePtr< Elem > build(const ElemType type, Elem *p=libmesh_nullptr)
Definition: elem.C:238
virtual ElemType type() const =0
virtual element_iterator level_elements_begin(unsigned int level)=0
Iterate over elements of a given level.
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) ...
void allow_renumbering(bool allow)
If false is passed in then this mesh will no longer be renumbered when being prepared for use...
Definition: mesh_base.h:749
bool skip_partitioning() const
Definition: mesh_base.h:775
void contract()
Contract an active element, i.e.
void skip_partitioning(bool skip)
If true is passed in then this mesh will no longer be (re)partitioned.
Definition: mesh_base.h:774
The definition of the const_element_iterator struct.
Definition: mesh_base.h:1494
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2083
IntRange< unsigned short > node_index_range() const
Definition: elem.h:2065
const Elem * parent() const
Definition: elem.h:2346
virtual void write_nodal_data(const std::string &, const std::vector< Number > &, const std::vector< std::string > &) libmesh_override
This method implements writing a mesh with nodal data to a specified file where the nodal data and va...
Definition: namebased_io.C:425
processor_id_type n_processors() const
const Elem * interior_parent() const
Definition: elem.C:951
This is the base class from which all geometric element types are derived.
Definition: elem.h:89
virtual Real hmin() const
Definition: elem.C:458
uint8_t processor_id_type
Definition: id_types.h:99
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
Definition: elem.C:1608
const class libmesh_nullptr_t libmesh_nullptr
virtual const Node * node_ptr(const dof_id_type i) const =0
static const Real TOLERANCE
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 find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true) libmesh_override
Other functions from MeshBase requiring re-definition.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
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)=0
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
void set_interior_parent(Elem *p)
Sets the pointer to the element&#39;s interior_parent.
Definition: elem.C:1003
This is the MeshBase class.
Definition: mesh_base.h:68
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
Definition: elem.h:1699
dof_id_type & set_id()
Definition: dof_object.h:641
libmesh_assert(j)
std::set< GhostingFunctor * >::const_iterator ghosting_functors_end() const
End of range of ghosting functors.
Definition: mesh_base.h:804
std::unique_ptr< T > UniquePtr
Definition: auto_ptr.h:46
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:1967
std::vector< boundary_id_type > boundary_ids(const Node *node) const
void create_submesh(UnstructuredMesh &new_mesh, const_element_iterator &it, const const_element_iterator &it_end) const
Constructs a mesh called "new_mesh" from the current mesh by iterating over the elements between it a...
virtual element_iterator elements_begin()=0
Iterate over all the elements in the Mesh.
virtual element_iterator level_elements_end(unsigned int level)=0
unsigned int _n_parts
The number of partitions the mesh has.
Definition: mesh_base.h:1342
void allow_remote_element_removal(bool allow)
If false is passed in then this mesh will no longer have remote elements deleted when being prepared ...
Definition: mesh_base.h:758
virtual void write(const std::string &mesh_file) libmesh_override
This method implements writing a mesh to a specified file.
Definition: namebased_io.C:279
virtual void delete_elem(Elem *e)=0
Removes element e from the mesh.
virtual SimpleRange< element_iterator > element_ptr_range()=0
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:1874
bool is_ancestor_of(const Elem *descendant) const
Definition: elem.h:2325
virtual element_iterator active_pid_elements_begin(processor_id_type proc_id)=0
The UnstructuredMesh class is derived from the MeshBase class.
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
virtual element_iterator elements_end()=0
unsigned int n_levels(const MeshBase &mesh)
Definition: mesh_tools.C:603
virtual SimpleRange< node_iterator > node_ptr_range()=0
virtual bool contract() libmesh_override
Delete subactive (i.e.
virtual const Node * query_node_ptr(const dof_id_type i) const =0
virtual void write(const std::string &name) libmesh_override
Write the file specified by name.
void clear_point_locator()
Releases the current PointLocator object.
Definition: mesh_base.C:555
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:2445
void libmesh_assert_valid_amr_elem_ids(const MeshBase &mesh)
A function for verifying that ids of elements are correctly sorted for AMR (parents have lower ids th...
Definition: mesh_tools.C:1113
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:174
subdomain_id_type subdomain_id() const
Definition: elem.h:1951
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition: elem.h:2000
virtual void clear()
Deletes all the data that are currently stored.
Definition: mesh_base.C:285
virtual unsigned int n_children() const =0
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2047
UnstructuredMesh(const Parallel::Communicator &comm_in, unsigned char dim=1)
Constructor.
unsigned int which_child_am_i(const Elem *e) const
Definition: elem.h:2487
std::set< GhostingFunctor * >::const_iterator ghosting_functors_begin() const
Beginning of range of ghosting functors.
Definition: mesh_base.h:798
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual element_iterator active_pid_elements_end(processor_id_type proc_id)=0
virtual ~UnstructuredMesh()
Destructor.
const Point & point(const unsigned int i) const
Definition: elem.h:1809
OStreamProxy out
virtual dof_id_type key(const unsigned int s) const =0
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
bool allow_renumbering() const
Definition: mesh_base.h:750
bool _is_prepared
Flag indicating if the mesh has been prepared for use.
Definition: mesh_base.h:1347
virtual unsigned int dim() const =0
unsigned int level() const
Definition: elem.h:2388
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:274
virtual Point centroid() const
Definition: elem.C:446
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
Definition: elem.h:2855
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1831
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
virtual void delete_remote_elements()
When supported, deletes all nonlocal elements of the mesh except for "ghosts" which touch a local ele...
Definition: mesh_base.h:182
dof_id_type id() const
Definition: dof_object.h:632
virtual dof_id_type n_nodes() const =0
virtual const Elem * elem_ptr(const dof_id_type i) const =0
virtual dof_id_type n_elem() const =0
unique_id_type unique_id() const
Definition: dof_object.h:649
bool allow_remote_element_removal() const
Definition: mesh_base.h:759
virtual void reserve_elem(const dof_id_type ne)=0
Reserves space for a known number of elements.
virtual UniquePtr< Elem > side_ptr(unsigned int i)=0
virtual void renumber_nodes_and_elements()=0
After partitioning a mesh it is useful to renumber the nodes and elements so that they lie in contigu...
uint8_t dof_id_type
Definition: id_types.h:64
processor_id_type processor_id() const
processor_id_type processor_id() const
Definition: dof_object.h:694
const RemoteElem * remote_elem
Definition: remote_elem.C:57