$extrastylesheet
mesh_communication.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 <numeric>
00022 
00023 // Local Includes -----------------------------------
00024 #include "libmesh/boundary_info.h"
00025 #include "libmesh/elem.h"
00026 #include "libmesh/libmesh_config.h"
00027 #include "libmesh/libmesh_common.h"
00028 #include "libmesh/libmesh_logging.h"
00029 #include "libmesh/mesh_base.h"
00030 #include "libmesh/mesh_communication.h"
00031 #include "libmesh/mesh_inserter_iterator.h"
00032 #include "libmesh/mesh_tools.h"
00033 #include "libmesh/parallel.h"
00034 #include "libmesh/parallel_elem.h"
00035 #include "libmesh/parallel_mesh.h"
00036 #include "libmesh/parallel_node.h"
00037 #include "libmesh/parallel_ghost_sync.h"
00038 #include "libmesh/utility.h"
00039 #include "libmesh/remote_elem.h"
00040 
00041 
00042 
00043 //-----------------------------------------------
00044 // anonymous namespace for implementation details
00045 namespace {
00046 
00047 using namespace libMesh;
00048 
00055 struct CompareElemIdsByLevel
00056 {
00057   bool operator()(const Elem *a,
00058                   const Elem *b) const
00059   {
00060     libmesh_assert (a);
00061     libmesh_assert (b);
00062     const unsigned int
00063       al = a->level(), bl = b->level();
00064     const dof_id_type
00065       aid = a->id(),   bid = b->id();
00066 
00067     return (al == bl) ? aid < bid : al < bl;
00068   }
00069 };
00070 }
00071 
00072 
00073 namespace libMesh
00074 {
00075 
00076 
00077 // ------------------------------------------------------------
00078 // MeshCommunication class members
00079 void MeshCommunication::clear ()
00080 {
00081   //  _neighboring_processors.clear();
00082 }
00083 
00084 
00085 
00086 #ifndef LIBMESH_HAVE_MPI // avoid spurious gcc warnings
00087 // ------------------------------------------------------------
00088 void MeshCommunication::redistribute (ParallelMesh &) const
00089 {
00090   // no MPI == one processor, no redistribution
00091   return;
00092 }
00093 #else
00094 // ------------------------------------------------------------
00095 void MeshCommunication::redistribute (ParallelMesh &mesh) const
00096 {
00097   // This method will be called after a new partitioning has been
00098   // assigned to the elements.  This partitioning was defined in
00099   // terms of the active elements, and "trickled down" to the
00100   // parents and nodes as to be consistent.
00101   //
00102   // The point is that the entire concept of local elements is
00103   // kinda shaky in this method.  Elements which were previously
00104   // local may now be assigned to other processors, so we need to
00105   // send those off.  Similarly, we need to accept elements from
00106   // other processors.
00107   //
00108   // The approach is as follows:
00109   // (1) send all elements we have stored to their proper homes
00110   // (2) receive elements from all processors, watching for duplicates
00111   // (3) deleting all nonlocal elements elements
00112   // (4) obtaining required ghost elements from neighboring processors
00113   libmesh_parallel_only(mesh.comm());
00114   libmesh_assert (!mesh.is_serial());
00115   libmesh_assert (MeshTools::n_elem(mesh.unpartitioned_elements_begin(),
00116                                     mesh.unpartitioned_elements_end()) == 0);
00117 
00118   START_LOG("redistribute()","MeshCommunication");
00119 
00120   // Get a few unique message tags to use in communications; we'll
00121   // default to some numbers around pi*1000
00122   Parallel::MessageTag
00123     nodestag   = mesh.comm().get_unique_tag(3141),
00124     elemstag   = mesh.comm().get_unique_tag(3142);
00125 
00126   // Figure out how many nodes and elements we have which are assigned to each
00127   // processor.  send_n_nodes_and_elem_per_proc contains the number of nodes/elements
00128   // we will be sending to each processor, recv_n_nodes_and_elem_per_proc contains
00129   // the number of nodes/elements we will be receiving from each processor.
00130   // Format:
00131   //  send_n_nodes_and_elem_per_proc[2*pid+0] = number of nodes to send to pid
00132   //  send_n_nodes_and_elem_per_proc[2*pid+1] = number of elements to send to pid
00133   std::vector<dof_id_type> send_n_nodes_and_elem_per_proc(2*mesh.n_processors(), 0);
00134 
00135   std::vector<Parallel::Request>
00136     node_send_requests, element_send_requests;
00137 
00138   for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
00139     if (pid != mesh.processor_id()) // don't send to ourselves!!
00140       {
00141         // Build up a list of nodes and elements to send to processor pid.
00142         // We will certainly send all the elements assigned to this processor,
00143         // but we will also ship off any other elements which touch
00144         // their nodes.
00145         std::set<const Node*> connected_nodes;
00146         {
00147           MeshBase::const_element_iterator       elem_it  = mesh.pid_elements_begin(pid);
00148           const MeshBase::const_element_iterator elem_end = mesh.pid_elements_end(pid);
00149 
00150           for (; elem_it!=elem_end; ++elem_it)
00151             {
00152               const Elem* elem = *elem_it;
00153 
00154               for (unsigned int n=0; n<elem->n_nodes(); n++)
00155                 connected_nodes.insert (elem->get_node(n));
00156             }
00157         }
00158 
00159         std::set<const Elem*, CompareElemIdsByLevel> elements_to_send;
00160         {
00161           MeshBase::const_element_iterator       elem_it  = mesh.elements_begin();
00162           const MeshBase::const_element_iterator elem_end = mesh.elements_end();
00163 
00164           for (; elem_it!=elem_end; ++elem_it)
00165             {
00166               const Elem* elem = *elem_it;
00167 
00168               for (unsigned int n=0; n<elem->n_nodes(); n++)
00169                 if (connected_nodes.count(elem->get_node(n)))
00170                   elements_to_send.insert (elem);
00171             }
00172         }
00173 
00174         connected_nodes.clear();
00175         {
00176           std::set<const Elem*, CompareElemIdsByLevel>::iterator
00177             elem_it  = elements_to_send.begin(),
00178             elem_end = elements_to_send.end();
00179 
00180           for (; elem_it!=elem_end; ++elem_it)
00181             {
00182               const Elem* elem = *elem_it;
00183 
00184               for (unsigned int n=0; n<elem->n_nodes(); n++)
00185                 connected_nodes.insert(elem->get_node(n));
00186             }
00187         }
00188 
00189         // the number of nodes we will ship to pid
00190         send_n_nodes_and_elem_per_proc[2*pid+0] =
00191           cast_int<dof_id_type>(connected_nodes.size());
00192 
00193         // send any nodes off to the destination processor
00194         if (!connected_nodes.empty())
00195           {
00196             node_send_requests.push_back(Parallel::request());
00197 
00198             mesh.comm().send_packed_range (pid,
00199                                            &mesh,
00200                                            connected_nodes.begin(),
00201                                            connected_nodes.end(),
00202                                            node_send_requests.back(),
00203                                            nodestag);
00204           }
00205 
00206         // the number of elements we will send to this processor
00207         send_n_nodes_and_elem_per_proc[2*pid+1] =
00208           cast_int<dof_id_type>(elements_to_send.size());
00209 
00210         if (!elements_to_send.empty())
00211           {
00212             // send the elements off to the destination processor
00213             element_send_requests.push_back(Parallel::request());
00214 
00215             mesh.comm().send_packed_range (pid,
00216                                            &mesh,
00217                                            elements_to_send.begin(),
00218                                            elements_to_send.end(),
00219                                            element_send_requests.back(),
00220                                            elemstag);
00221           }
00222       }
00223 
00224   std::vector<dof_id_type> recv_n_nodes_and_elem_per_proc(send_n_nodes_and_elem_per_proc);
00225 
00226   mesh.comm().alltoall (recv_n_nodes_and_elem_per_proc);
00227 
00228   // In general we will only need to communicate with a subset of the other processors.
00229   // I can't immediately think of a case where we will send elements but not nodes, but
00230   // these are only bools and we have the information anyway...
00231   std::vector<bool>
00232     send_node_pair(mesh.n_processors(),false), send_elem_pair(mesh.n_processors(),false),
00233     recv_node_pair(mesh.n_processors(),false), recv_elem_pair(mesh.n_processors(),false);
00234 
00235   unsigned int
00236     n_send_node_pairs=0,      n_send_elem_pairs=0,
00237     n_recv_node_pairs=0,      n_recv_elem_pairs=0;
00238 
00239   for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
00240     {
00241       if (send_n_nodes_and_elem_per_proc[2*pid+0]) // we have nodes to send
00242         {
00243           send_node_pair[pid] = true;
00244           n_send_node_pairs++;
00245         }
00246 
00247       if (send_n_nodes_and_elem_per_proc[2*pid+1]) // we have elements to send
00248         {
00249           send_elem_pair[pid] = true;
00250           n_send_elem_pairs++;
00251         }
00252 
00253       if (recv_n_nodes_and_elem_per_proc[2*pid+0]) // we have nodes to receive
00254         {
00255           recv_node_pair[pid] = true;
00256           n_recv_node_pairs++;
00257         }
00258 
00259       if (recv_n_nodes_and_elem_per_proc[2*pid+1]) // we have elements to receive
00260         {
00261           recv_elem_pair[pid] = true;
00262           n_recv_elem_pairs++;
00263         }
00264     }
00265   libmesh_assert_equal_to (n_send_node_pairs, node_send_requests.size());
00266   libmesh_assert_equal_to (n_send_elem_pairs, element_send_requests.size());
00267 
00268   // Receive nodes.
00269   // We now know how many processors will be sending us nodes.
00270   for (unsigned int node_comm_step=0; node_comm_step<n_recv_node_pairs; node_comm_step++)
00271     // but we don't necessarily want to impose an ordering, so
00272     // just process whatever message is available next.
00273     mesh.comm().receive_packed_range (Parallel::any_source,
00274                                       &mesh,
00275                                       mesh_inserter_iterator<Node>(mesh),
00276                                       nodestag);
00277 
00278   // Receive elements.
00279   // Similarly we know how many processors are sending us elements,
00280   // but we don't really care in what order we receive them.
00281   for (unsigned int elem_comm_step=0; elem_comm_step<n_recv_elem_pairs; elem_comm_step++)
00282     mesh.comm().receive_packed_range (Parallel::any_source,
00283                                       &mesh,
00284                                       mesh_inserter_iterator<Elem>(mesh),
00285                                       elemstag);
00286 
00287   // Wait for all sends to complete
00288   Parallel::wait (node_send_requests);
00289   Parallel::wait (element_send_requests);
00290 
00291   // Check on the redistribution consistency
00292 #ifdef DEBUG
00293   MeshTools::libmesh_assert_equal_n_systems(mesh);
00294 
00295   MeshTools::libmesh_assert_valid_refinement_tree(mesh);
00296 #endif
00297 
00298   STOP_LOG("redistribute()","MeshCommunication");
00299 }
00300 #endif // LIBMESH_HAVE_MPI
00301 
00302 
00303 
00304 #ifndef LIBMESH_HAVE_MPI // avoid spurious gcc warnings
00305 // ------------------------------------------------------------
00306 void MeshCommunication::gather_neighboring_elements (ParallelMesh &) const
00307 {
00308   // no MPI == one processor, no need for this method...
00309   return;
00310 }
00311 #else
00312 // ------------------------------------------------------------
00313 void MeshCommunication::gather_neighboring_elements (ParallelMesh &mesh) const
00314 {
00315   // Don't need to do anything if there is
00316   // only one processor.
00317   if (mesh.n_processors() == 1)
00318     return;
00319 
00320   // This function must be run on all processors at once
00321   libmesh_parallel_only(mesh.comm());
00322 
00323   START_LOG("gather_neighboring_elements()","MeshCommunication");
00324 
00325   //------------------------------------------------------------------
00326   // The purpose of this function is to provide neighbor data structure
00327   // consistency for a parallel, distributed mesh.  In libMesh we require
00328   // that each local element have access to a full set of valid face
00329   // neighbors.  In some cases this requires us to store "ghost elements" -
00330   // elements that belong to other processors but we store to provide
00331   // data structure consistency.  Also, it is assumed that any element
00332   // with a NULL neighbor resides on a physical domain boundary.  So,
00333   // even our "ghost elements" must have non-NULL neighbors.  To handle
00334   // this the concept of "RemoteElem" is used - a special construct which
00335   // is used to denote that an element has a face neighbor, but we do
00336   // not actually store detailed information about that neighbor.  This
00337   // is required to prevent data structure explosion.
00338   //
00339   // So when this method is called we should have only local elements.
00340   // These local elements will then find neighbors among the local
00341   // element set.  After this is completed, any element with a NULL
00342   // neighbor has either (i) a face on the physical boundary of the mesh,
00343   // or (ii) a neighboring element which lives on a remote processor.
00344   // To handle case (ii), we communicate the global node indices connected
00345   // to all such faces to our neighboring processors.  They then send us
00346   // all their elements with a NULL neighbor that are connected to any
00347   // of the nodes in our list.
00348   //------------------------------------------------------------------
00349 
00350   // Let's begin with finding consistent neighbor data information
00351   // for all the elements we currently have.  We'll use a clean
00352   // slate here - clear any existing information, including RemoteElem's.
00353   //  mesh.find_neighbors (/* reset_remote_elements = */ true,
00354   //       /* reset_current_list    = */ true);
00355 
00356   // Get a unique message tag to use in communications; we'll default
00357   // to some numbers around pi*10000
00358   Parallel::MessageTag
00359     element_neighbors_tag = mesh.comm().get_unique_tag(31416);
00360 
00361   // Now any element with a NULL neighbor either
00362   // (i) lives on the physical domain boundary, or
00363   // (ii) lives on an inter-processor boundary.
00364   // We will now gather all the elements from adjacent processors
00365   // which are of the same state, which should address all the type (ii)
00366   // elements.
00367 
00368   // A list of all the processors which *may* contain neighboring elements.
00369   // (for development simplicity, just make this the identity map)
00370   std::vector<processor_id_type> adjacent_processors;
00371   for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
00372     if (pid != mesh.processor_id())
00373       adjacent_processors.push_back (pid);
00374 
00375 
00376   const processor_id_type n_adjacent_processors =
00377     cast_int<processor_id_type>(adjacent_processors.size());
00378 
00379   //-------------------------------------------------------------------------
00380   // Let's build a list of all nodes which live on NULL-neighbor sides.
00381   // For simplicity, we will use a set to build the list, then transfer
00382   // it to a vector for communication.
00383   std::vector<dof_id_type> my_interface_node_list;
00384   std::vector<const Elem*>  my_interface_elements;
00385   {
00386     std::set<dof_id_type> my_interface_node_set;
00387 
00388     // since parent nodes are a subset of children nodes, this should be sufficient
00389     MeshBase::const_element_iterator       it     = mesh.active_local_elements_begin();
00390     const MeshBase::const_element_iterator it_end = mesh.active_local_elements_end();
00391 
00392     for (; it != it_end; ++it)
00393       {
00394         const Elem * const elem = *it;
00395         libmesh_assert(elem);
00396 
00397         if (elem->on_boundary()) // denotes *any* side has a NULL neighbor
00398           {
00399             my_interface_elements.push_back(elem); // add the element, but only once, even
00400             // if there are multiple NULL neighbors
00401             for (unsigned int s=0; s<elem->n_sides(); s++)
00402               if (elem->neighbor(s) == NULL)
00403                 {
00404                   UniquePtr<Elem> side(elem->build_side(s));
00405 
00406                   for (unsigned int n=0; n<side->n_vertices(); n++)
00407                     my_interface_node_set.insert (side->node(n));
00408                 }
00409           }
00410       }
00411 
00412     my_interface_node_list.reserve (my_interface_node_set.size());
00413     my_interface_node_list.insert  (my_interface_node_list.end(),
00414                                     my_interface_node_set.begin(),
00415                                     my_interface_node_set.end());
00416   }
00417 
00418   // we will now send my_interface_node_list to all of the adjacent processors.
00419   // note that for the time being we will copy the list to a unique buffer for
00420   // each processor so that we can use a nonblocking send and not access the
00421   // buffer again until the send completes.  it is my understanding that the
00422   // MPI 2.1 standard seeks to remove this restriction as unnecessary, so in
00423   // the future we should change this to send the same buffer to each of the
00424   // adjacent processors. - BSK 11/17/2008
00425   std::vector<std::vector<dof_id_type> >
00426     my_interface_node_xfer_buffers (n_adjacent_processors, my_interface_node_list);
00427   std::map<processor_id_type, unsigned char> n_comm_steps;
00428 
00429   std::vector<Parallel::Request> send_requests (3*n_adjacent_processors);
00430   unsigned int current_request = 0;
00431 
00432   for (unsigned int comm_step=0; comm_step<n_adjacent_processors; comm_step++)
00433     {
00434       n_comm_steps[adjacent_processors[comm_step]]=1;
00435       mesh.comm().send (adjacent_processors[comm_step],
00436                         my_interface_node_xfer_buffers[comm_step],
00437                         send_requests[current_request++],
00438                         element_neighbors_tag);
00439     }
00440 
00441   //-------------------------------------------------------------------------
00442   // processor pairings are symmetric - I expect to receive an interface node
00443   // list from each processor in adjacent_processors as well!
00444   // now we will catch an incoming node list for each of our adjacent processors.
00445   //
00446   // we are done with the adjacent_processors list - note that it is in general
00447   // a superset of the processors we truly share elements with.  so let's
00448   // clear the superset list, and we will fill it with the true list.
00449   adjacent_processors.clear();
00450 
00451   std::vector<dof_id_type> common_interface_node_list;
00452 
00453   // we expect two classess of messages -
00454   // (1) incoming interface node lists, to which we will reply with our elements
00455   //     touching nodes in the list, and
00456   // (2) replies from the requests we sent off previously.
00457   //  (2.a) - nodes
00458   //  (2.b) - elements
00459   // so we expect 3 communications from each adjacent processor.
00460   // by structuring the communication in this way we hopefully impose no
00461   // order on the handling of the arriving messages.  in particular, we
00462   // should be able to handle the case where we receive a request and
00463   // all replies from processor A before even receiving a request from
00464   // processor B.
00465 
00466   for (unsigned int comm_step=0; comm_step<3*n_adjacent_processors; comm_step++)
00467     {
00468       //------------------------------------------------------------------
00469       // catch incoming node list
00470       Parallel::Status
00471         status(mesh.comm().probe (Parallel::any_source,
00472                                   element_neighbors_tag));
00473       const processor_id_type
00474         source_pid_idx = cast_int<processor_id_type>(status.source()),
00475         dest_pid_idx   = source_pid_idx;
00476 
00477       //------------------------------------------------------------------
00478       // first time - incoming request
00479       if (n_comm_steps[source_pid_idx] == 1)
00480         {
00481           n_comm_steps[source_pid_idx]++;
00482 
00483           mesh.comm().receive (source_pid_idx,
00484                                common_interface_node_list,
00485                                element_neighbors_tag);
00486           const std::size_t
00487             their_interface_node_list_size = common_interface_node_list.size();
00488 
00489           // we now have the interface node list from processor source_pid_idx.
00490           // now we can find all of our elements which touch any of these nodes
00491           // and send copies back to this processor.  however, we can make our
00492           // search more efficient by first excluding all the nodes in
00493           // their list which are not also contained in
00494           // my_interface_node_list.  we can do this in place as a set
00495           // intersection.
00496           common_interface_node_list.erase
00497             (std::set_intersection (my_interface_node_list.begin(),
00498                                     my_interface_node_list.end(),
00499                                     common_interface_node_list.begin(),
00500                                     common_interface_node_list.end(),
00501                                     common_interface_node_list.begin()),
00502              common_interface_node_list.end());
00503 
00504           if (false)
00505             libMesh::out << "[" << mesh.processor_id() << "] "
00506                          << "my_interface_node_list.size()="       << my_interface_node_list.size()
00507                          << ", [" << source_pid_idx << "] "
00508                          << "their_interface_node_list.size()="    << their_interface_node_list_size
00509                          << ", common_interface_node_list.size()=" << common_interface_node_list.size()
00510                          << std::endl;
00511 
00512           // Now we need to see which of our elements touch the nodes in the list.
00513           // We will certainly send all the active elements which intersect source_pid_idx,
00514           // but we will also ship off the other elements in the same family tree
00515           // as the active ones for data structure consistency.
00516           //
00517           // FIXME - shipping full family trees is unnecessary and inefficient.
00518           //
00519           // We also ship any nodes connected to these elements.  Note
00520           // some of these nodes and elements may be replicated from
00521           // other processors, but that is OK.
00522           std::set<const Elem*, CompareElemIdsByLevel> elements_to_send;
00523           std::set<const Node*> connected_nodes;
00524 
00525           // Check for quick return?
00526           if (common_interface_node_list.empty())
00527             {
00528               // let's try to be smart here - if we have no nodes in common,
00529               // we cannot share elements.  so post the messages expected
00530               // from us here and go on about our business.
00531               // note that even though these are nonblocking sends
00532               // they should complete essentially instantly, because
00533               // in all cases the send buffers are empty
00534               mesh.comm().send_packed_range (dest_pid_idx,
00535                                              &mesh,
00536                                              connected_nodes.begin(),
00537                                              connected_nodes.end(),
00538                                              send_requests[current_request++],
00539                                              element_neighbors_tag);
00540 
00541               mesh.comm().send_packed_range (dest_pid_idx,
00542                                              &mesh,
00543                                              elements_to_send.begin(),
00544                                              elements_to_send.end(),
00545                                              send_requests[current_request++],
00546                                              element_neighbors_tag);
00547 
00548               continue;
00549             }
00550           // otherwise, this really *is* an adjacent processor.
00551           adjacent_processors.push_back(source_pid_idx);
00552 
00553           std::vector<const Elem*> family_tree;
00554 
00555           for (dof_id_type e=0, n_shared_nodes=0; e<my_interface_elements.size(); e++, n_shared_nodes=0)
00556             {
00557               const Elem * elem = my_interface_elements[e];
00558 
00559               for (unsigned int n=0; n<elem->n_vertices(); n++)
00560                 if (std::binary_search (common_interface_node_list.begin(),
00561                                         common_interface_node_list.end(),
00562                                         elem->node(n)))
00563                   {
00564                     n_shared_nodes++;
00565 
00566                     // TBD - how many nodes do we need to share
00567                     // before we care?  certainly 2, but 1?  not
00568                     // sure, so let's play it safe...
00569                     if (n_shared_nodes > 0) break;
00570                   }
00571 
00572               if (n_shared_nodes) // share at least one node?
00573                 {
00574                   elem = elem->top_parent();
00575 
00576                   // avoid a lot of duplicated effort -- if we already have elem
00577                   // in the set its entire family tree is already in the set.
00578                   if (!elements_to_send.count(elem))
00579                     {
00580 #ifdef LIBMESH_ENABLE_AMR
00581                       elem->family_tree(family_tree);
00582 #else
00583                       family_tree.clear();
00584                       family_tree.push_back(elem);
00585 #endif
00586                       for (unsigned int leaf=0; leaf<family_tree.size(); leaf++)
00587                         {
00588                           elem = family_tree[leaf];
00589                           elements_to_send.insert (elem);
00590 
00591                           for (unsigned int n=0; n<elem->n_nodes(); n++)
00592                             connected_nodes.insert (elem->get_node(n));
00593                         }
00594                     }
00595                 }
00596             }
00597 
00598           // The elements_to_send and connected_nodes sets now contain all
00599           // the elements and nodes we need to send to this processor.
00600           // All that remains is to pack up the objects (along with
00601           // any boundary conditions) and send the messages off.
00602           {
00603             libmesh_assert (connected_nodes.empty() || !elements_to_send.empty());
00604             libmesh_assert (!connected_nodes.empty() || elements_to_send.empty());
00605 
00606             // send the nodes off to the destination processor
00607             mesh.comm().send_packed_range (dest_pid_idx,
00608                                            &mesh,
00609                                            connected_nodes.begin(),
00610                                            connected_nodes.end(),
00611                                            send_requests[current_request++],
00612                                            element_neighbors_tag);
00613 
00614             // send the elements off to the destination processor
00615             mesh.comm().send_packed_range (dest_pid_idx,
00616                                            &mesh,
00617                                            elements_to_send.begin(),
00618                                            elements_to_send.end(),
00619                                            send_requests[current_request++],
00620                                            element_neighbors_tag);
00621           }
00622         }
00623       //------------------------------------------------------------------
00624       // second time - reply of nodes
00625       else if (n_comm_steps[source_pid_idx] == 2)
00626         {
00627           n_comm_steps[source_pid_idx]++;
00628 
00629           mesh.comm().receive_packed_range (source_pid_idx,
00630                                             &mesh,
00631                                             mesh_inserter_iterator<Node>(mesh),
00632                                             element_neighbors_tag);
00633         }
00634       //------------------------------------------------------------------
00635       // third time - reply of elements
00636       else if (n_comm_steps[source_pid_idx] == 3)
00637         {
00638           n_comm_steps[source_pid_idx]++;
00639 
00640           mesh.comm().receive_packed_range (source_pid_idx,
00641                                             &mesh,
00642                                             mesh_inserter_iterator<Elem>(mesh),
00643                                             element_neighbors_tag);
00644         }
00645       //------------------------------------------------------------------
00646       // fourth time - shouldn't happen
00647       else
00648         {
00649           libMesh::err << "ERROR:  unexpected number of replies: "
00650                        << n_comm_steps[source_pid_idx]
00651                        << std::endl;
00652         }
00653     } // done catching & processing replies associated with tag ~ 100,000pi
00654 
00655   // allow any pending requests to complete
00656   Parallel::wait (send_requests);
00657 
00658   STOP_LOG("gather_neighboring_elements()","MeshCommunication");
00659 }
00660 #endif // LIBMESH_HAVE_MPI
00661 
00662 
00663 #ifndef LIBMESH_HAVE_MPI // avoid spurious gcc warnings
00664 // ------------------------------------------------------------
00665 void MeshCommunication::broadcast (MeshBase&) const
00666 {
00667   // no MPI == one processor, no need for this method...
00668   return;
00669 }
00670 #else
00671 // ------------------------------------------------------------
00672 void MeshCommunication::broadcast (MeshBase& mesh) const
00673 {
00674   // Don't need to do anything if there is
00675   // only one processor.
00676   if (mesh.n_processors() == 1)
00677     return;
00678 
00679   // This function must be run on all processors at once
00680   libmesh_parallel_only(mesh.comm());
00681 
00682   START_LOG("broadcast()","MeshCommunication");
00683 
00684   // Explicitly clear the mesh on all but processor 0.
00685   if (mesh.processor_id() != 0)
00686     mesh.clear();
00687 
00688   // Broadcast nodes
00689   mesh.comm().broadcast_packed_range(&mesh,
00690                                      mesh.nodes_begin(),
00691                                      mesh.nodes_end(),
00692                                      &mesh,
00693                                      mesh_inserter_iterator<Node>(mesh));
00694 
00695   // Broadcast elements from coarsest to finest, so that child
00696   // elements will see their parents already in place.
00697   unsigned int n_levels = MeshTools::n_levels(mesh);
00698   mesh.comm().broadcast(n_levels);
00699 
00700   for (unsigned int l=0; l != n_levels; ++l)
00701     mesh.comm().broadcast_packed_range(&mesh,
00702                                        mesh.level_elements_begin(l),
00703                                        mesh.level_elements_end(l),
00704                                        &mesh,
00705                                        mesh_inserter_iterator<Elem>(mesh));
00706 
00707   // Make sure mesh_dimension and elem_dimensions are consistent.
00708   mesh.cache_elem_dims();
00709 
00710   // Broadcast all of the named entity information
00711   mesh.comm().broadcast(mesh.set_subdomain_name_map());
00712   mesh.comm().broadcast(mesh.get_boundary_info().set_sideset_name_map());
00713   mesh.comm().broadcast(mesh.get_boundary_info().set_nodeset_name_map());
00714 
00715   libmesh_assert (mesh.comm().verify(mesh.n_elem()));
00716   libmesh_assert (mesh.comm().verify(mesh.n_nodes()));
00717 
00718 #ifdef DEBUG
00719   MeshTools::libmesh_assert_valid_procids<Elem>(mesh);
00720   MeshTools::libmesh_assert_valid_procids<Node>(mesh);
00721 #endif
00722 
00723   STOP_LOG("broadcast()","MeshCommunication");
00724 }
00725 #endif // LIBMESH_HAVE_MPI
00726 
00727 
00728 
00729 #ifndef LIBMESH_HAVE_MPI // avoid spurious gcc warnings
00730 // ------------------------------------------------------------
00731 void MeshCommunication::gather (const processor_id_type, ParallelMesh&) const
00732 {
00733   // no MPI == one processor, no need for this method...
00734   return;
00735 }
00736 #else
00737 // ------------------------------------------------------------
00738 void MeshCommunication::gather (const processor_id_type root_id, ParallelMesh& mesh) const
00739 {
00740   // The mesh should know it's about to be serialized
00741   libmesh_assert (mesh.is_serial());
00742 
00743   // Check for quick return
00744   if (mesh.n_processors() == 1)
00745     return;
00746 
00747   // This function must be run on all processors at once
00748   libmesh_parallel_only(mesh.comm());
00749 
00750   START_LOG("(all)gather()","MeshCommunication");
00751 
00752   (root_id == DofObject::invalid_processor_id) ?
00753 
00754     mesh.comm().allgather_packed_range (&mesh,
00755                                         mesh.nodes_begin(),
00756                                         mesh.nodes_end(),
00757                                         mesh_inserter_iterator<Node>(mesh)) :
00758 
00759     mesh.comm().gather_packed_range (root_id,
00760                                      &mesh,
00761                                      mesh.nodes_begin(),
00762                                      mesh.nodes_end(),
00763                                      mesh_inserter_iterator<Node>(mesh));
00764 
00765   // Gather elements from coarsest to finest, so that child
00766   // elements will see their parents already in place.
00767   // rank 0 should know n_levels regardless, so this is
00768   // safe independent of root_id
00769   unsigned int n_levels = MeshTools::n_levels(mesh);
00770   mesh.comm().broadcast(n_levels);
00771 
00772   for (unsigned int l=0; l != n_levels; ++l)
00773     (root_id == DofObject::invalid_processor_id) ?
00774 
00775       mesh.comm().allgather_packed_range (&mesh,
00776                                           mesh.level_elements_begin(l),
00777                                           mesh.level_elements_end(l),
00778                                           mesh_inserter_iterator<Elem>(mesh)) :
00779 
00780       mesh.comm().gather_packed_range (root_id,
00781                                        &mesh,
00782                                        mesh.level_elements_begin(l),
00783                                        mesh.level_elements_end(l),
00784                                        mesh_inserter_iterator<Elem>(mesh));
00785 
00786 
00787   // If we are doing an allgather(), perform sanity check on the result.
00788   if (root_id == DofObject::invalid_processor_id)
00789     {
00790       libmesh_assert (mesh.comm().verify(mesh.n_elem()));
00791       libmesh_assert (mesh.comm().verify(mesh.n_nodes()));
00792     }
00793 
00794   // Inform new elements of their neighbors,
00795   // while resetting all remote_elem links on
00796   // the appropriate ranks.
00797   if ((root_id == DofObject::invalid_processor_id) ||
00798       (mesh.comm().rank() == root_id))
00799     mesh.find_neighbors(true);
00800 
00801   // All done!
00802   STOP_LOG("(all)gather()","MeshCommunication");
00803 }
00804 #endif // LIBMESH_HAVE_MPI
00805 
00806 
00807 
00808 // Functor for make_elems_parallel_consistent and
00809 // make_node_ids_parallel_consistent
00810 namespace {
00811 
00812 struct SyncIds
00813 {
00814   typedef dof_id_type datum;
00815   typedef void (MeshBase::*renumber_obj)(dof_id_type, dof_id_type);
00816 
00817   SyncIds(MeshBase &_mesh, renumber_obj _renumberer) :
00818     mesh(_mesh),
00819     renumber(_renumberer) {}
00820 
00821   MeshBase &mesh;
00822   renumber_obj renumber;
00823   // renumber_obj &renumber;
00824 
00825   // Find the id of each requested DofObject -
00826   // Parallel::sync_* already did the work for us
00827   void gather_data (const std::vector<dof_id_type>& ids,
00828                     std::vector<datum>& ids_out)
00829   {
00830     ids_out = ids;
00831   }
00832 
00833   void act_on_data (const std::vector<dof_id_type>& old_ids,
00834                     std::vector<datum>& new_ids)
00835   {
00836     for (unsigned int i=0; i != old_ids.size(); ++i)
00837       if (old_ids[i] != new_ids[i])
00838         (mesh.*renumber)(old_ids[i], new_ids[i]);
00839   }
00840 };
00841 }
00842 
00843 
00844 
00845 // ------------------------------------------------------------
00846 void MeshCommunication::make_node_ids_parallel_consistent
00847 (MeshBase &mesh)
00848 {
00849   // This function must be run on all processors at once
00850   libmesh_parallel_only(mesh.comm());
00851 
00852   START_LOG ("make_node_ids_parallel_consistent()", "MeshCommunication");
00853 
00854   SyncIds syncids(mesh, &MeshBase::renumber_node);
00855   Parallel::sync_node_data_by_element_id
00856     (mesh, mesh.elements_begin(), mesh.elements_end(), syncids);
00857 
00858   STOP_LOG ("make_node_ids_parallel_consistent()", "MeshCommunication");
00859 }
00860 
00861 
00862 
00863 // ------------------------------------------------------------
00864 void MeshCommunication::make_elems_parallel_consistent(MeshBase &mesh)
00865 {
00866   // This function must be run on all processors at once
00867   libmesh_parallel_only(mesh.comm());
00868 
00869   START_LOG ("make_elems_parallel_consistent()", "MeshCommunication");
00870 
00871   SyncIds syncids(mesh, &MeshBase::renumber_elem);
00872   Parallel::sync_element_data_by_parent_id
00873     (mesh, mesh.active_elements_begin(),
00874      mesh.active_elements_end(), syncids);
00875 
00876   STOP_LOG ("make_elems_parallel_consistent()", "MeshCommunication");
00877 }
00878 
00879 
00880 
00881 // Functors for make_node_proc_ids_parallel_consistent
00882 namespace {
00883 
00884 struct SyncProcIds
00885 {
00886   typedef processor_id_type datum;
00887 
00888   SyncProcIds(MeshBase &_mesh) : mesh(_mesh) {}
00889 
00890   MeshBase &mesh;
00891 
00892   // ------------------------------------------------------------
00893   void gather_data (const std::vector<dof_id_type>& ids,
00894                     std::vector<datum>& data)
00895   {
00896     // Find the processor id of each requested node
00897     data.resize(ids.size());
00898 
00899     for (std::size_t i=0; i != ids.size(); ++i)
00900       {
00901         // Look for this point in the mesh
00902         // We'd better find every node we're asked for
00903         Node *node = mesh.node_ptr(ids[i]);
00904 
00905         // Return the node's correct processor id,
00906         data[i] = node->processor_id();
00907       }
00908   }
00909 
00910   // ------------------------------------------------------------
00911   void act_on_data (const std::vector<dof_id_type>& ids,
00912                     std::vector<datum> proc_ids)
00913   {
00914     // Set the ghost node processor ids we've now been informed of
00915     for (std::size_t i=0; i != ids.size(); ++i)
00916       {
00917         Node *node = mesh.node_ptr(ids[i]);
00918         node->processor_id() = proc_ids[i];
00919       }
00920   }
00921 };
00922 }
00923 
00924 
00925 
00926 // ------------------------------------------------------------
00927 void MeshCommunication::make_node_proc_ids_parallel_consistent
00928 (MeshBase& mesh)
00929 {
00930   START_LOG ("make_node_proc_ids_parallel_consistent()", "MeshCommunication");
00931 
00932   // This function must be run on all processors at once
00933   libmesh_parallel_only(mesh.comm());
00934 
00935   // When this function is called, each section of a parallelized mesh
00936   // should be in the following state:
00937   //
00938   // All nodes should have the exact same physical location on every
00939   // processor where they exist.
00940   //
00941   // Local nodes should have unique authoritative ids,
00942   // and processor ids consistent with all processors which own
00943   // an element touching them.
00944   //
00945   // Ghost nodes touching local elements should have processor ids
00946   // consistent with all processors which own an element touching
00947   // them.
00948 
00949   SyncProcIds sync(mesh);
00950   Parallel::sync_node_data_by_element_id
00951     (mesh, mesh.elements_begin(), mesh.elements_end(), sync);
00952 
00953   STOP_LOG ("make_node_proc_ids_parallel_consistent()", "MeshCommunication");
00954 }
00955 
00956 
00957 
00958 // ------------------------------------------------------------
00959 void MeshCommunication::make_nodes_parallel_consistent
00960 (MeshBase &mesh)
00961 {
00962   // This function must be run on all processors at once
00963   libmesh_parallel_only(mesh.comm());
00964 
00965   // When this function is called, each section of a parallelized mesh
00966   // should be in the following state:
00967   //
00968   // All nodes should have the exact same physical location on every
00969   // processor where they exist.
00970   //
00971   // Local nodes should have unique authoritative ids,
00972   // and processor ids consistent with all processors which own
00973   // an element touching them.
00974   //
00975   // Ghost nodes touching local elements should have processor ids
00976   // consistent with all processors which own an element touching
00977   // them.
00978   //
00979   // Ghost nodes should have ids which are either already correct
00980   // or which are in the "unpartitioned" id space.
00981 
00982   // First, let's sync up processor ids.  Some of these processor ids
00983   // may be "wrong" from coarsening, but they're right in the sense
00984   // that they'll tell us who has the authoritative dofobject ids for
00985   // each node.
00986   this->make_node_proc_ids_parallel_consistent(mesh);
00987 
00988   // Second, sync up dofobject ids.
00989   this->make_node_ids_parallel_consistent(mesh);
00990 
00991   // Finally, correct the processor ids to make DofMap happy
00992   MeshTools::correct_node_proc_ids(mesh);
00993 }
00994 
00995 
00996 
00997 // ------------------------------------------------------------
00998 void MeshCommunication::delete_remote_elements(ParallelMesh& mesh, const std::set<Elem *> & extra_ghost_elem_ids) const
00999 {
01000   // The mesh should know it's about to be parallelized
01001   libmesh_assert (!mesh.is_serial());
01002 
01003   START_LOG("delete_remote_elements()", "MeshCommunication");
01004 
01005 #ifdef DEBUG
01006   // We expect maximum ids to be in sync so we can use them to size
01007   // vectors
01008   mesh.comm().verify(mesh.max_node_id());
01009   mesh.comm().verify(mesh.max_elem_id());
01010   const dof_id_type par_max_node_id = mesh.parallel_max_node_id();
01011   const dof_id_type par_max_elem_id = mesh.parallel_max_elem_id();
01012   libmesh_assert_equal_to (par_max_node_id, mesh.max_node_id());
01013   libmesh_assert_equal_to (par_max_elem_id, mesh.max_elem_id());
01014 #endif
01015 
01016   // FIXME - should these be "unsorted_set"s?  O(N) is O(N)...
01017   std::vector<bool> local_nodes(mesh.max_node_id(), false);
01018   std::vector<bool> semilocal_nodes(mesh.max_node_id(), false);
01019   std::vector<bool> semilocal_elems(mesh.max_elem_id(), false);
01020 
01021   // We don't want to delete any element that shares a node
01022   // with or is an ancestor of a local element.
01023   MeshBase::const_element_iterator l_elem_it = mesh.local_elements_begin(),
01024     l_end     = mesh.local_elements_end();
01025   for (; l_elem_it != l_end; ++l_elem_it)
01026     {
01027       const Elem *elem = *l_elem_it;
01028       for (unsigned int n=0; n != elem->n_nodes(); ++n)
01029         {
01030           dof_id_type nodeid = elem->node(n);
01031           libmesh_assert_less (nodeid, local_nodes.size());
01032           local_nodes[nodeid] = true;
01033         }
01034       while (elem)
01035         {
01036           dof_id_type elemid = elem->id();
01037           libmesh_assert_less (elemid, semilocal_elems.size());
01038           semilocal_elems[elemid] = true;
01039 
01040           for (unsigned int n=0; n != elem->n_nodes(); ++n)
01041             semilocal_nodes[elem->node(n)] = true;
01042 
01043           const Elem *parent = elem->parent();
01044           // Don't proceed from a boundary mesh to an interior mesh
01045           if (parent && parent->dim() != elem->dim())
01046             break;
01047 
01048           elem = parent;
01049         }
01050     }
01051 
01052   // We don't want to delete any element that shares a node
01053   // with or is an ancestor of an unpartitioned element either.
01054   MeshBase::const_element_iterator
01055     u_elem_it = mesh.unpartitioned_elements_begin(),
01056     u_end     = mesh.unpartitioned_elements_end();
01057 
01058   for (; u_elem_it != u_end; ++u_elem_it)
01059     {
01060       const Elem *elem = *u_elem_it;
01061       for (unsigned int n=0; n != elem->n_nodes(); ++n)
01062         local_nodes[elem->node(n)] = true;
01063       while (elem)
01064         {
01065           semilocal_elems[elem->id()] = true;
01066 
01067           for (unsigned int n=0; n != elem->n_nodes(); ++n)
01068             semilocal_nodes[elem->node(n)] = true;
01069 
01070           const Elem *parent = elem->parent();
01071           // Don't proceed from a boundary mesh to an interior mesh
01072           if (parent && parent->dim() != elem->dim())
01073             break;
01074 
01075           elem = parent;
01076         }
01077     }
01078 
01079   // Flag all the elements that share nodes with
01080   // local and unpartitioned elements, along with their ancestors
01081   MeshBase::element_iterator nl_elem_it = mesh.not_local_elements_begin(),
01082     nl_end     = mesh.not_local_elements_end();
01083   for (; nl_elem_it != nl_end; ++nl_elem_it)
01084     {
01085       const Elem *elem = *nl_elem_it;
01086       for (unsigned int n=0; n != elem->n_nodes(); ++n)
01087         if (local_nodes[elem->node(n)])
01088           {
01089             while (elem)
01090               {
01091                 semilocal_elems[elem->id()] = true;
01092 
01093                 for (unsigned int nn=0; nn != elem->n_nodes(); ++nn)
01094                   semilocal_nodes[elem->node(nn)] = true;
01095 
01096                 const Elem *parent = elem->parent();
01097                 // Don't proceed from a boundary mesh to an interior mesh
01098                 if (parent && parent->dim() != elem->dim())
01099                   break;
01100 
01101                 elem = parent;
01102               }
01103             break;
01104           }
01105     }
01106 
01107   // Don't delete elements that we were explicitly told not to
01108   for(std::set<Elem *>::iterator it = extra_ghost_elem_ids.begin();
01109       it != extra_ghost_elem_ids.end();
01110       ++it)
01111     {
01112       const Elem *elem = *it;
01113       semilocal_elems[elem->id()] = true;
01114       for (unsigned int n=0; n != elem->n_nodes(); ++n)
01115         semilocal_nodes[elem->node(n)] = true;
01116     }
01117 
01118   // Delete all the elements we have no reason to save,
01119   // starting with the most refined so that the mesh
01120   // is valid at all intermediate steps
01121   unsigned int n_levels = MeshTools::n_levels(mesh);
01122 
01123   for (int l = n_levels - 1; l >= 0; --l)
01124     {
01125       MeshBase::element_iterator lev_elem_it = mesh.level_elements_begin(l),
01126         lev_end     = mesh.level_elements_end(l);
01127       for (; lev_elem_it != lev_end; ++lev_elem_it)
01128         {
01129           Elem *elem = *lev_elem_it;
01130           libmesh_assert (elem);
01131           // Make sure we don't leave any invalid pointers
01132           if (!semilocal_elems[elem->id()])
01133             elem->make_links_to_me_remote();
01134 
01135           // Subactive neighbor pointers aren't preservable here
01136           if (elem->subactive())
01137             for (unsigned int s=0; s != elem->n_sides(); ++s)
01138               elem->set_neighbor(s, NULL);
01139 
01140           // delete_elem doesn't currently invalidate element
01141           // iterators... that had better not change
01142           if (!semilocal_elems[elem->id()])
01143             mesh.delete_elem(elem);
01144         }
01145     }
01146 
01147   // Delete all the nodes we have no reason to save
01148   MeshBase::node_iterator node_it  = mesh.nodes_begin(),
01149     node_end = mesh.nodes_end();
01150   for (node_it = mesh.nodes_begin(); node_it != node_end; ++node_it)
01151     {
01152       Node *node = *node_it;
01153       libmesh_assert(node);
01154       if (!semilocal_nodes[node->id()])
01155         mesh.delete_node(node);
01156     }
01157 
01158 #ifdef DEBUG
01159   MeshTools::libmesh_assert_valid_refinement_tree(mesh);
01160 #endif
01161 
01162   STOP_LOG("delete_remote_elements()", "MeshCommunication");
01163 }
01164 
01165 } // namespace libMesh