$extrastylesheet
unstructured_mesh.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 // C++ includes
00021 #include <fstream>
00022 #include <sstream>
00023 #include <iomanip>
00024 
00025 // C includes
00026 #include <sys/types.h> // for pid_t
00027 #include <unistd.h>    // for getpid(), unlink()
00028 
00029 // Local includes
00030 #include "libmesh/boundary_info.h"
00031 #include "libmesh/unstructured_mesh.h"
00032 #include "libmesh/libmesh_logging.h"
00033 #include "libmesh/elem.h"
00034 #include "libmesh/mesh_tools.h" // For n_levels
00035 #include "libmesh/parallel.h"
00036 #include "libmesh/remote_elem.h"
00037 
00038 // For most I/O
00039 #include "libmesh/namebased_io.h"
00040 
00041 // for MeshData backward compatibility
00042 #include "libmesh/unv_io.h"
00043 #include "libmesh/tetgen_io.h"
00044 
00045 #include LIBMESH_INCLUDE_UNORDERED_MAP
00046 
00047 
00048 namespace libMesh
00049 {
00050 
00051 
00052 // ------------------------------------------------------------
00053 // UnstructuredMesh class member functions
00054 UnstructuredMesh::UnstructuredMesh (const Parallel::Communicator &comm_in,
00055                                     unsigned char d) :
00056   MeshBase (comm_in,d)
00057 {
00058   libmesh_assert (libMesh::initialized());
00059 }
00060 
00061 
00062 
00063 #ifndef LIBMESH_DISABLE_COMMWORLD
00064 UnstructuredMesh::UnstructuredMesh (unsigned char d) :
00065   MeshBase (d)
00066 {
00067   libmesh_assert (libMesh::initialized());
00068 }
00069 #endif
00070 
00071 
00072 
00073 void UnstructuredMesh::copy_nodes_and_elements
00074 (const UnstructuredMesh& other_mesh, const bool skip_find_neighbors)
00075 {
00076   // We're assuming our subclass data needs no copy
00077   libmesh_assert_equal_to (_n_parts, other_mesh._n_parts);
00078   libmesh_assert (std::equal(_elem_dims.begin(), _elem_dims.end(), other_mesh._elem_dims.begin()));
00079   libmesh_assert_equal_to (_is_prepared, other_mesh._is_prepared);
00080 
00081   // We're assuming the other mesh has proper element number ordering,
00082   // so that we add parents before their children.
00083 #ifdef DEBUG
00084   MeshTools::libmesh_assert_valid_amr_elem_ids(other_mesh);
00085 #endif
00086 
00087   //Copy in Nodes
00088   {
00089     //Preallocate Memory if necessary
00090     this->reserve_nodes(other_mesh.n_nodes());
00091 
00092     const_node_iterator it = other_mesh.nodes_begin();
00093     const_node_iterator end = other_mesh.nodes_end();
00094 
00095     for (; it != end; ++it)
00096       {
00097         const Node *oldn = *it;
00098 
00099         // Add new nodes in old node Point locations
00100         /*Node *newn =*/ this->add_point(*oldn, oldn->id(), oldn->processor_id());
00101 
00102         // And start them off in the same subdomain
00103         //        newn->processor_id() = oldn->processor_id();
00104       }
00105   }
00106 
00107   //Copy in Elements
00108   {
00109     //Preallocate Memory if necessary
00110     this->reserve_elem(other_mesh.n_elem());
00111 
00112     // Declare a map linking old and new elements, needed to copy the neighbor lists
00113     std::map<const Elem*, Elem*> old_elems_to_new_elems;
00114 
00115     // Loop over the elements
00116     MeshBase::const_element_iterator it = other_mesh.elements_begin();
00117     const MeshBase::const_element_iterator end = other_mesh.elements_end();
00118 
00119     // FIXME: Where do we set element IDs??
00120     for (; it != end; ++it)
00121       {
00122         //Look at the old element
00123         const Elem *old = *it;
00124         //Build a new element
00125         Elem *newparent = old->parent() ?
00126           this->elem(old->parent()->id()) : NULL;
00127         UniquePtr<Elem> ap = Elem::build(old->type(), newparent);
00128         Elem * el = ap.release();
00129 
00130         el->subdomain_id() = old->subdomain_id();
00131 
00132         for (unsigned int s=0; s != old->n_sides(); ++s)
00133           if (old->neighbor(s) == remote_elem)
00134             el->set_neighbor(s, const_cast<RemoteElem*>(remote_elem));
00135 
00136 #ifdef LIBMESH_ENABLE_AMR
00137         if (old->has_children())
00138           for (unsigned int c=0; c != old->n_children(); ++c)
00139             if (old->child(c) == remote_elem)
00140               el->add_child(const_cast<RemoteElem*>(remote_elem), c);
00141 
00142         //Create the parent's child pointers if necessary
00143         if (newparent)
00144           {
00145             unsigned int oldc = old->parent()->which_child_am_i(old);
00146             newparent->add_child(el, oldc);
00147           }
00148 
00149         // Copy the refinement flags
00150         el->set_refinement_flag(old->refinement_flag());
00151         el->set_p_refinement_flag(old->p_refinement_flag());
00152 #endif // #ifdef LIBMESH_ENABLE_AMR
00153 
00154         //Assign all the nodes
00155         for(unsigned int i=0;i<el->n_nodes();i++)
00156           el->set_node(i) = &this->node(old->node(i));
00157 
00158         // And start it off in the same subdomain
00159         el->processor_id() = old->processor_id();
00160 
00161         // Give it the same id
00162         el->set_id(old->id());
00163 
00164         //Hold onto it
00165         if(!skip_find_neighbors)
00166           {
00167             this->add_elem(el);
00168           }
00169         else
00170           {
00171             Elem* new_el = this->add_elem(el);
00172             old_elems_to_new_elems[old] = new_el;
00173           }
00174 
00175         // Add the link between the original element and this copy to the map
00176         if(skip_find_neighbors)
00177           old_elems_to_new_elems[old] = el;
00178       }
00179 
00180     // Loop (again) over the elements to fill in the neighbors
00181     if(skip_find_neighbors)
00182       {
00183         it = other_mesh.elements_begin();
00184         for (; it != end; ++it)
00185           {
00186             Elem* old_elem = *it;
00187             Elem* new_elem = old_elems_to_new_elems[old_elem];
00188             for (unsigned int s=0; s != old_elem->n_neighbors(); ++s)
00189               {
00190                 const Elem* old_neighbor = old_elem->neighbor(s);
00191                 Elem* new_neighbor = old_elems_to_new_elems[old_neighbor];
00192                 new_elem->set_neighbor(s, new_neighbor);
00193               }
00194           }
00195       }
00196   }
00197 
00198   //Finally prepare the new Mesh for use.  Keep the same numbering and
00199   //partitioning but also the same renumbering and partitioning
00200   //policies as our source mesh.
00201   this->allow_renumbering(false);
00202   this->skip_partitioning(true);
00203   this->prepare_for_use(false, skip_find_neighbors);
00204   this->allow_renumbering(other_mesh.allow_renumbering());
00205   this->skip_partitioning(other_mesh.skip_partitioning());
00206 }
00207 
00208 
00209 
00210 UnstructuredMesh::~UnstructuredMesh ()
00211 {
00212   //  this->clear ();  // Nothing to clear at this level
00213 
00214   libmesh_exceptionless_assert (!libMesh::closed());
00215 }
00216 
00217 
00218 
00219 
00220 
00221 void UnstructuredMesh::find_neighbors (const bool reset_remote_elements,
00222                                        const bool reset_current_list)
00223 {
00224   // We might actually want to run this on an empty mesh
00225   // (e.g. the boundary mesh for a nonexistant bcid!)
00226   // libmesh_assert_not_equal_to (this->n_nodes(), 0);
00227   // libmesh_assert_not_equal_to (this->n_elem(), 0);
00228 
00229   // This function must be run on all processors at once
00230   parallel_object_only();
00231 
00232   START_LOG("find_neighbors()", "Mesh");
00233 
00234   const element_iterator el_end = this->elements_end();
00235 
00236   //TODO:[BSK] This should be removed later?!
00237   if (reset_current_list)
00238     for (element_iterator el = this->elements_begin(); el != el_end; ++el)
00239       {
00240         Elem* e = *el;
00241         for (unsigned int s=0; s<e->n_neighbors(); s++)
00242           if (e->neighbor(s) != remote_elem ||
00243               reset_remote_elements)
00244             e->set_neighbor(s,NULL);
00245       }
00246 
00247   // Find neighboring elements by first finding elements
00248   // with identical side keys and then check to see if they
00249   // are neighbors
00250   {
00251     // data structures -- Use the hash_multimap if available
00252     typedef unsigned int                    key_type;
00253     typedef std::pair<Elem*, unsigned char> val_type;
00254     typedef std::pair<key_type, val_type>   key_val_pair;
00255 
00256     typedef LIBMESH_BEST_UNORDERED_MULTIMAP<key_type, val_type> map_type;
00257 
00258     // A map from side keys to corresponding elements & side numbers
00259     map_type side_to_elem_map;
00260 
00261 
00262 
00263     for (element_iterator el = this->elements_begin(); el != el_end; ++el)
00264       {
00265         Elem* element = *el;
00266 
00267         for (unsigned char ms=0; ms<element->n_neighbors(); ms++)
00268           {
00269           next_side:
00270             // If we haven't yet found a neighbor on this side, try.
00271             // Even if we think our neighbor is remote, that
00272             // information may be out of date.
00273             if (element->neighbor(ms) == NULL ||
00274                 element->neighbor(ms) == remote_elem)
00275               {
00276                 // Get the key for the side of this element
00277                 const unsigned int key = element->key(ms);
00278 
00279                 // Look for elements that have an identical side key
00280                 std::pair <map_type::iterator, map_type::iterator>
00281                   bounds = side_to_elem_map.equal_range(key);
00282 
00283                 // May be multiple keys, check all the possible
00284                 // elements which _might_ be neighbors.
00285                 if (bounds.first != bounds.second)
00286                   {
00287                     // Get the side for this element
00288                     const UniquePtr<Elem> my_side(element->side(ms));
00289 
00290                     // Look at all the entries with an equivalent key
00291                     while (bounds.first != bounds.second)
00292                       {
00293                         // Get the potential element
00294                         Elem* neighbor = bounds.first->second.first;
00295 
00296                         // Get the side for the neighboring element
00297                         const unsigned int ns = bounds.first->second.second;
00298                         const UniquePtr<Elem> their_side(neighbor->side(ns));
00299                         //libmesh_assert(my_side.get());
00300                         //libmesh_assert(their_side.get());
00301 
00302                         // If found a match with my side
00303                         //
00304                         // We need special tests here for 1D:
00305                         // since parents and children have an equal
00306                         // side (i.e. a node), we need to check
00307                         // ns != ms, and we also check level() to
00308                         // avoid setting our neighbor pointer to
00309                         // any of our neighbor's descendants
00310                         if( (*my_side == *their_side) &&
00311                             (element->level() == neighbor->level()) &&
00312                             ((element->dim() != 1) || (ns != ms)) )
00313                           {
00314                             // So share a side.  Is this a mixed pair
00315                             // of subactive and active/ancestor
00316                             // elements?
00317                             // If not, then we're neighbors.
00318                             // If so, then the subactive's neighbor is
00319 
00320                             if (element->subactive() ==
00321                                 neighbor->subactive())
00322                               {
00323                                 // an element is only subactive if it has
00324                                 // been coarsened but not deleted
00325                                 element->set_neighbor (ms,neighbor);
00326                                 neighbor->set_neighbor(ns,element);
00327                               }
00328                             else if (element->subactive())
00329                               {
00330                                 element->set_neighbor(ms,neighbor);
00331                               }
00332                             else if (neighbor->subactive())
00333                               {
00334                                 neighbor->set_neighbor(ns,element);
00335                               }
00336                             side_to_elem_map.erase (bounds.first);
00337 
00338                             // get out of this nested crap
00339                             goto next_side;
00340                           }
00341 
00342                         ++bounds.first;
00343                       }
00344                   }
00345 
00346                 // didn't find a match...
00347                 // Build the map entry for this element
00348                 key_val_pair kvp;
00349 
00350                 kvp.first         = key;
00351                 kvp.second.first  = element;
00352                 kvp.second.second = ms;
00353 
00354                 // use the lower bound as a hint for
00355                 // where to put it.
00356 #if defined(LIBMESH_HAVE_UNORDERED_MAP) || defined(LIBMESH_HAVE_TR1_UNORDERED_MAP) || defined(LIBMESH_HAVE_HASH_MAP) || defined(LIBMESH_HAVE_EXT_HASH_MAP)
00357                 side_to_elem_map.insert (kvp);
00358 #else
00359                 side_to_elem_map.insert (bounds.first,kvp);
00360 #endif
00361               }
00362           }
00363       }
00364   }
00365 
00366 #ifdef LIBMESH_ENABLE_AMR
00367 
00388   const unsigned int n_levels = MeshTools::n_levels(*this);
00389   for (unsigned int level = 1; level < n_levels; ++level)
00390     {
00391       element_iterator end = this->level_elements_end(level);
00392       for (element_iterator el = this->level_elements_begin(level);
00393            el != end; ++el)
00394         {
00395           Elem* current_elem = *el;
00396           libmesh_assert(current_elem);
00397           Elem* parent = current_elem->parent();
00398           libmesh_assert(parent);
00399           const unsigned int my_child_num = parent->which_child_am_i(current_elem);
00400 
00401           for (unsigned int s=0; s < current_elem->n_neighbors(); s++)
00402             {
00403               if (current_elem->neighbor(s) == NULL ||
00404                   (current_elem->neighbor(s) == remote_elem &&
00405                    parent->is_child_on_side(my_child_num, s)))
00406                 {
00407                   Elem *neigh = parent->neighbor(s);
00408 
00409                   // If neigh was refined and had non-subactive children
00410                   // made remote earlier, then a non-subactive elem should
00411                   // actually have one of those remote children as a
00412                   // neighbor
00413                   if (neigh && (neigh->ancestor()) && (!current_elem->subactive()))
00414                     {
00415 #ifdef DEBUG
00416                       // Let's make sure that "had children made remote"
00417                       // situation is actually the case
00418                       libmesh_assert(neigh->has_children());
00419                       bool neigh_has_remote_children = false;
00420                       for (unsigned int c = 0; c != neigh->n_children(); ++c)
00421                         {
00422                           if (neigh->child(c) == remote_elem)
00423                             neigh_has_remote_children = true;
00424                         }
00425                       libmesh_assert(neigh_has_remote_children);
00426 
00427                       // And let's double-check that we don't have
00428                       // a remote_elem neighboring a local element
00429                       libmesh_assert_not_equal_to (current_elem->processor_id(),
00430                                                    this->processor_id());
00431 #endif // DEBUG
00432                       neigh = const_cast<RemoteElem*>(remote_elem);
00433                     }
00434 
00435                   current_elem->set_neighbor(s, neigh);
00436 #ifdef DEBUG
00437                   if (neigh != NULL && neigh != remote_elem)
00438                     // We ignore subactive elements here because
00439                     // we don't care about neighbors of subactive element.
00440                     if ((!neigh->active()) && (!current_elem->subactive()))
00441                       {
00442                         libMesh::err << "On processor " << this->processor_id()
00443                                      << std::endl;
00444                         libMesh::err << "Bad element ID = " << current_elem->id()
00445                                      << ", Side " << s << ", Bad neighbor ID = " << neigh->id() << std::endl;
00446                         libMesh::err << "Bad element proc_ID = " << current_elem->processor_id()
00447                                      << ", Bad neighbor proc_ID = " << neigh->processor_id() << std::endl;
00448                         libMesh::err << "Bad element size = " << current_elem->hmin()
00449                                      << ", Bad neighbor size = " << neigh->hmin() << std::endl;
00450                         libMesh::err << "Bad element center = " << current_elem->centroid()
00451                                      << ", Bad neighbor center = " << neigh->centroid() << std::endl;
00452                         libMesh::err << "ERROR: "
00453                                      << (current_elem->active()?"Active":"Ancestor")
00454                                      << " Element at level "
00455                                      << current_elem->level() << std::endl;
00456                         libMesh::err << "with "
00457                                      << (parent->active()?"active":
00458                                          (parent->subactive()?"subactive":"ancestor"))
00459                                      << " parent share "
00460                                      << (neigh->subactive()?"subactive":"ancestor")
00461                                      << " neighbor at level " << neigh->level()
00462                                      << std::endl;
00463                         NameBasedIO(*this).write ("bad_mesh.gmv");
00464                         libmesh_error_msg("Problematic mesh written to bad_mesh.gmv.");
00465                       }
00466 #endif // DEBUG
00467                 }
00468             }
00469         }
00470     }
00471 
00472 #endif // AMR
00473 
00474 
00475 #ifdef DEBUG
00476   MeshTools::libmesh_assert_valid_neighbors(*this);
00477 #endif
00478 
00479   STOP_LOG("find_neighbors()", "Mesh");
00480 }
00481 
00482 
00483 
00484 void UnstructuredMesh::read (const std::string& name,
00485                              MeshData* mesh_data,
00486                              bool skip_renumber_nodes_and_elements)
00487 {
00488   // Set the skip_renumber_nodes_and_elements flag on all processors
00489   // if necessary.
00490   // This ensures that renumber_nodes_and_elements is *not* called
00491   // during prepare_for_use() for certain types of mesh files.
00492   // This is required in cases where there is an associated solution
00493   // file which expects a certain ordering of the nodes.
00494   if(name.rfind(".gmv")+4==name.size())
00495     {
00496       skip_renumber_nodes_and_elements =  true;
00497     }
00498 
00499   if (mesh_data)
00500     {
00501       libmesh_deprecated();
00502       if (name.rfind(".unv") < name.size())
00503         UNVIO(*this, mesh_data).read (name);
00504       else if ((name.rfind(".node")  < name.size()) ||
00505                (name.rfind(".ele")   < name.size()))
00506         TetGenIO(*this,mesh_data).read (name);
00507     }
00508   else
00509     NameBasedIO(*this).read(name);
00510 
00511   if (skip_renumber_nodes_and_elements)
00512     {
00513       // Use MeshBase::allow_renumbering() yourself instead.
00514       libmesh_deprecated();
00515       this->allow_renumbering(false);
00516     }
00517 
00518   // Done reading the mesh.  Now prepare it for use.
00519   this->prepare_for_use();
00520 }
00521 
00522 
00523 
00524 void UnstructuredMesh::write (const std::string& name,
00525                               MeshData* mesh_data)
00526 {
00527   START_LOG("write()", "Mesh");
00528 
00529   if (mesh_data)
00530     {
00531       libmesh_deprecated();
00532       if (name.rfind(".unv") < name.size())
00533         UNVIO(*this, mesh_data).write (name);
00534       else
00535         libmesh_error_msg("Only UNV output supports MeshData");
00536     }
00537 
00538   NameBasedIO(*this).write(name);
00539 
00540   STOP_LOG("write()", "Mesh");
00541 }
00542 
00543 
00544 
00545 void UnstructuredMesh::write (const std::string& name,
00546                               const std::vector<Number>& v,
00547                               const std::vector<std::string>& vn)
00548 {
00549   START_LOG("write()", "Mesh");
00550 
00551   NameBasedIO(*this).write_nodal_data(name, v, vn);
00552 
00553   STOP_LOG("write()", "Mesh");
00554 }
00555 
00556 
00557 
00558 
00559 
00560 void UnstructuredMesh::create_pid_mesh(UnstructuredMesh& pid_mesh,
00561                                        const processor_id_type pid) const
00562 {
00563 
00564   // Issue a warning if the number the number of processors
00565   // currently available is less that that requested for
00566   // partitioning.  This is not necessarily an error since
00567   // you may run on one processor and still partition the
00568   // mesh into several partitions.
00569 #ifdef DEBUG
00570   if (this->n_processors() < pid)
00571     {
00572       libMesh::out << "WARNING:  You are creating a "
00573                    << "mesh for a processor id (="
00574                    << pid
00575                    << ") greater than "
00576                    << "the number of processors available for "
00577                    << "the calculation. (="
00578                    << this->n_processors()
00579                    << ")."
00580                    << std::endl;
00581     }
00582 #endif
00583 
00584   // Create iterators to loop over the list of elements
00585   //   const_active_pid_elem_iterator       it(this->elements_begin(),   pid);
00586   //   const const_active_pid_elem_iterator it_end(this->elements_end(), pid);
00587 
00588   const_element_iterator       it     = this->active_pid_elements_begin(pid);
00589   const const_element_iterator it_end = this->active_pid_elements_end(pid);
00590 
00591   this->create_submesh (pid_mesh, it, it_end);
00592 }
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 void UnstructuredMesh::create_submesh (UnstructuredMesh& new_mesh,
00601                                        const_element_iterator& it,
00602                                        const const_element_iterator& it_end) const
00603 {
00604   // Just in case the subdomain_mesh already has some information
00605   // in it, get rid of it.
00606   new_mesh.clear();
00607 
00608   // Fail if (*this == new_mesh), we cannot create a submesh inside ourself!
00609   // This may happen if the user accidently passes the original mesh into
00610   // this function!  We will check this by making sure we did not just
00611   // clear ourself.
00612   libmesh_assert_not_equal_to (this->n_nodes(), 0);
00613   libmesh_assert_not_equal_to (this->n_elem(), 0);
00614 
00615   // How the nodes on this mesh will be renumbered to nodes
00616   // on the new_mesh.
00617   std::vector<dof_id_type> new_node_numbers (this->n_nodes());
00618 
00619   std::fill (new_node_numbers.begin(),
00620              new_node_numbers.end(),
00621              DofObject::invalid_id);
00622 
00623 
00624 
00625   // the number of nodes on the new mesh, will be incremented
00626   dof_id_type n_new_nodes = 0;
00627   dof_id_type n_new_elem  = 0;
00628 
00629   for (; it != it_end; ++it)
00630     {
00631       // increment the new element counter
00632       n_new_elem++;
00633 
00634       const Elem* old_elem = *it;
00635 
00636       // Add an equivalent element type to the new_mesh
00637       Elem* new_elem =
00638         new_mesh.add_elem (Elem::build(old_elem->type()).release());
00639 
00640       libmesh_assert(new_elem);
00641 
00642       // Loop over the nodes on this element.
00643       for (unsigned int n=0; n<old_elem->n_nodes(); n++)
00644         {
00645           libmesh_assert_less (old_elem->node(n), new_node_numbers.size());
00646 
00647           if (new_node_numbers[old_elem->node(n)] == DofObject::invalid_id)
00648             {
00649               new_node_numbers[old_elem->node(n)] = n_new_nodes;
00650 
00651               // Add this node to the new mesh
00652               new_mesh.add_point (old_elem->point(n));
00653 
00654               // Increment the new node counter
00655               n_new_nodes++;
00656             }
00657 
00658           // Define this element's connectivity on the new mesh
00659           libmesh_assert_less (new_node_numbers[old_elem->node(n)], new_mesh.n_nodes());
00660 
00661           new_elem->set_node(n) = new_mesh.node_ptr (new_node_numbers[old_elem->node(n)]);
00662         }
00663 
00664       // Copy ids for this element
00665       new_elem->subdomain_id() = old_elem->subdomain_id();
00666       new_elem->processor_id() = old_elem->processor_id();
00667 
00668       // Maybe add boundary conditions for this element
00669       for (unsigned short s=0; s<old_elem->n_sides(); s++)
00670         // We're supporting boundary ids on internal sides now
00671         //if (old_elem->neighbor(s) == NULL)
00672         {
00673           const std::vector<boundary_id_type>& bc_ids =
00674             this->get_boundary_info().boundary_ids(old_elem, s);
00675           for (std::vector<boundary_id_type>::const_iterator id_it=bc_ids.begin(); id_it!=bc_ids.end(); ++id_it)
00676             {
00677               const boundary_id_type bc_id = *id_it;
00678               if (bc_id != this->get_boundary_info().invalid_id)
00679                 new_mesh.get_boundary_info().add_side (new_elem, s,
00680                                                        bc_id);
00681             }
00682         }
00683     } // end loop over elements
00684 
00685 
00686   // Prepare the new_mesh for use
00687   new_mesh.prepare_for_use(/*skip_renumber =*/false);
00688 
00689 }
00690 
00691 
00692 
00693 #ifdef LIBMESH_ENABLE_AMR
00694 bool UnstructuredMesh::contract ()
00695 {
00696   START_LOG ("contract()", "Mesh");
00697 
00698   // Flag indicating if this call actually changes the mesh
00699   bool mesh_changed = false;
00700 
00701   element_iterator in        = elements_begin();
00702   const element_iterator end = elements_end();
00703 
00704 #ifdef DEBUG
00705   for ( ; in != end; ++in)
00706     if (*in != NULL)
00707       {
00708         Elem* el = *in;
00709         libmesh_assert(el->active() || el->subactive() || el->ancestor());
00710       }
00711   in = elements_begin();
00712 #endif
00713 
00714   // Loop over the elements.
00715   for ( ; in != end; ++in)
00716     if (*in != NULL)
00717       {
00718         Elem* el = *in;
00719 
00720         // Delete all the subactive ones
00721         if (el->subactive())
00722           {
00723             // No level-0 element should be subactive.
00724             // Note that we CAN'T test elem->level(), as that
00725             // touches elem->parent()->dim(), and elem->parent()
00726             // might have already been deleted!
00727             libmesh_assert(el->parent());
00728 
00729             // Delete the element
00730             // This just sets a pointer to NULL, and doesn't
00731             // invalidate any iterators
00732             this->delete_elem(el);
00733 
00734             // the mesh has certainly changed
00735             mesh_changed = true;
00736           }
00737         else
00738           {
00739             // Compress all the active ones
00740             if (el->active())
00741               el->contract();
00742             else
00743               libmesh_assert (el->ancestor());
00744           }
00745       }
00746 
00747   // Strip any newly-created NULL voids out of the element array
00748   this->renumber_nodes_and_elements();
00749 
00750   // FIXME: Need to understand why deleting subactive children
00751   // invalidates the point locator.  For now we will clear it explicitly
00752   this->clear_point_locator();
00753 
00754   STOP_LOG ("contract()", "Mesh");
00755 
00756   return mesh_changed;
00757 }
00758 #endif // #ifdef LIBMESH_ENABLE_AMR
00759 
00760 } // namespace libMesh