[MOAB-dev] r1790 - in MOAB/trunk: . parallel tools/mbzoltan

tautges at mcs.anl.gov tautges at mcs.anl.gov
Fri May 2 08:25:23 CDT 2008


Author: tautges
Date: 2008-05-02 08:25:23 -0500 (Fri, 02 May 2008)
New Revision: 1790

Modified:
   MOAB/trunk/FileOptions.hpp
   MOAB/trunk/MBParallelConventions.h
   MOAB/trunk/MBReadUtil.cpp
   MOAB/trunk/mbparallelcomm_test.cpp
   MOAB/trunk/parallel/MBParallelComm.cpp
   MOAB/trunk/parallel/MBParallelComm.hpp
   MOAB/trunk/parallel/ReadParallel.cpp
   MOAB/trunk/parallel/ReadParallel.hpp
   MOAB/trunk/parallel/WriteHDF5Parallel.cpp
   MOAB/trunk/parallel/pcomm_unit.cpp
   MOAB/trunk/tools/mbzoltan/MBZoltan.cpp
   MOAB/trunk/tools/mbzoltan/MBZoltan.hpp
   MOAB/trunk/tools/mbzoltan/main.cpp
Log:
 - modified mbzoltan to allow storing partition as sets/tags/both, and
to allow specifying dimension of partitioned entities (to allow
partitioning vertices)

- adding PARALLEL_IFACE_SETS_TAG_NAME to denote convention for naming
parallel interface sets

- adding ghosting option to mbparallelcomm

- fixing spelling error in FileOptions (sometimes I just can't help
myself)

- added gathering of parent/child sets in
MBReadUtil::gather_related_ents

- getting rid of a few unused variables in WriteHDF5Parallel

- MBParallelComm: changing implementation of ghost communication, to 
use asynchronous functions

- ReadParallel: adding resolve shared entities and exchange ghosts as
event types, and cleaning up partition set assignment a bit to better handle
pre-existing partition sets

Passes make check.


Modified: MOAB/trunk/FileOptions.hpp
===================================================================
--- MOAB/trunk/FileOptions.hpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/FileOptions.hpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -81,7 +81,7 @@
   
   /**\brief Check for option with any value.
    *
-   * Check for aan option with any value.
+   * Check for an option with any value.
    *\param name The option name
    *\param value Output. The value.
    *\return - MB_SUCCESS if option is found

Modified: MOAB/trunk/MBParallelConventions.h
===================================================================
--- MOAB/trunk/MBParallelConventions.h	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/MBParallelConventions.h	2008-05-02 13:25:23 UTC (rev 1790)
@@ -64,4 +64,14 @@
 #define PSTATUS_SHARED 0x1
 #define PSTATUS_NOT_OWNED 0x2
  
+/** \brief Tag storing interface sets
+ *
+ * This tag stores interface sets allocated for a particular 
+ * interface instance.  This is tag of length MAX_SHARING_PROCS
+ * (defined in parallel/MBParallelComm.hpp) which stores interface 
+ * set handles (entries set to 0 by default).
+ *
+ */
+#define PARALLEL_IFACE_SETS_TAG_NAME "PARALLEL_IFACE_SETS"
+
 #endif

Modified: MOAB/trunk/MBReadUtil.cpp
===================================================================
--- MOAB/trunk/MBReadUtil.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/MBReadUtil.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -206,9 +206,6 @@
                                             MBRange &related_ents,
                                             MBRange *all_sets) 
 {
-    // first, related ents includes the partition itself
-  related_ents.merge(partition);
-  
     // loop over any sets, getting contained ents
   std::pair<MBRange::const_iterator, MBRange::const_iterator> pair_it =
     partition.equal_range(MBENTITYSET);
@@ -223,18 +220,11 @@
   }
   RR;
 
-    // gather adjacent ents of lower dimension
+    // gather adjacent ents of other dimensions
   MBRange tmp_ents;
-  for (int dim = 2; dim >= 0; dim--) {
-    MBEntityType lower_type = MBCN::TypeDimensionMap[dim+1].first,
-      upper_type = MBCN::TypeDimensionMap[3].second;
-    
-    MBRange::const_iterator bit = related_ents.lower_bound(lower_type),
-      eit = related_ents.upper_bound(upper_type);
-    MBRange from_ents;
-    from_ents.merge(bit, eit);
+  for (int dim = 3; dim >= 0; dim--) {
     tmp_ents.clear();
-    MBErrorCode tmp_result = mMB->get_adjacencies(from_ents, dim, false, 
+    MBErrorCode tmp_result = mMB->get_adjacencies(related_ents, dim, false, 
                                                   tmp_ents, 
                                                   MBInterface::UNION);
     if (MB_SUCCESS != tmp_result) result = tmp_result;
@@ -242,19 +232,47 @@
   }
   RR;
   
-    // get related sets
-  MBRange tmp_ents3;
+    // related ents includes the partition itself
+  related_ents.merge(partition);
+  
+    // get contains-related sets
+  MBRange tmp_ents3, last_related;
   if (!all_sets) all_sets = &tmp_ents3;
-  result = mMB->get_entities_by_type(0, MBENTITYSET, *all_sets);
-  for (MBRange::iterator rit = all_sets->begin(); 
-       rit != all_sets->end(); rit++) {
-    tmp_ents.clear();
-    result = mMB->get_entities_by_handle(*rit, tmp_ents, true); RR;
-    MBRange tmp_ents2 = tmp_ents.intersect(related_ents);
+  result = mMB->get_entities_by_type(0, MBENTITYSET, *all_sets); RR;
+  while (related_ents.size() != last_related.size()) {
+    last_related = related_ents;
+    for (MBRange::iterator rit = all_sets->begin(); 
+         rit != all_sets->end(); rit++) {
+      if (related_ents.find(*rit) != related_ents.end()) continue;
+      
+      tmp_ents.clear();
+      result = mMB->get_entities_by_handle(*rit, tmp_ents, true); RR;
+      MBRange tmp_ents2 = tmp_ents.intersect(related_ents);
     
-      // if the intersection is not empty, set is related
-    if (!tmp_ents2.empty()) related_ents.insert(*rit);
+        // if the intersection is not empty, set is related
+      if (!tmp_ents2.empty()) related_ents.insert(*rit);
+    }
   }
+  
+    // get parent/child-related sets
+  last_related.clear();
+  while (related_ents.size() != last_related.size()) {
+    last_related = related_ents;
+    std::pair<MBRange::const_iterator, MBRange::const_iterator> it_pair = 
+      last_related.equal_range(MBENTITYSET);
 
+    for (MBRange::const_iterator rit = it_pair.first;
+         rit != it_pair.second; rit++) {
+        // get all parents/children and add to related ents
+      tmp_ents.clear();
+      result = mMB->get_parent_meshsets(*rit, tmp_ents, 0); RR;
+      related_ents.merge(tmp_ents);
+      
+      tmp_ents.clear();
+      result = mMB->get_child_meshsets(*rit, tmp_ents, 0); RR;
+      related_ents.merge(tmp_ents);
+    }
+  }
+  
   return MB_SUCCESS;
 }

Modified: MOAB/trunk/mbparallelcomm_test.cpp
===================================================================
--- MOAB/trunk/mbparallelcomm_test.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/mbparallelcomm_test.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -45,7 +45,7 @@
 
 MBErrorCode read_file(MBInterface *mbImpl, const char *filename,
                       const char *tag_name, int tag_val, int distrib,
-                      int parallel_option);
+                      int parallel_option, int with_ghosts);
 
 MBErrorCode test_packing(MBInterface *mbImpl, const char *filename);
 
@@ -61,7 +61,7 @@
   err = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
 
     // start time
-  double stime, rtime, shtime, setime, dtime, ltime;
+  double stime, rtime, setime, dtime, ltime;
   if (0 == rank) stime = MPI_Wtime();
 
     // create MOAB instance based on that
@@ -88,13 +88,14 @@
         << " 1     <linear_ints> <shared_verts> " << std::endl
         << " 2     <n_ints> " << std::endl
         << " 3*    <file_name> [<tag_name>=\"MATERIAL_SET\" [tag_val] [distribute=1] ]" << std::endl
+        << " 4    <file_name> " << std::endl
         << "*Note: if opt 3 is used, it must be the last one." << std::endl;
     
     err = MPI_Finalize();
     return 1;
   }
 
-  int npos = 1, tag_val, distrib;
+  int npos = 1, tag_val, distrib, with_ghosts = 1;
   const char *tag_name, *filename;
   int parallel_option = 0;
 
@@ -140,9 +141,10 @@
         if (npos < argc) tag_name = argv[npos++];
         if (npos < argc) tag_val = strtol(argv[npos++], NULL, 0);
         if (npos < argc) distrib = strtol(argv[npos++], NULL, 0);
+        if (npos < argc) with_ghosts = strtol(argv[npos++], NULL, 0);
         else distrib = 1;
         tmp_result = read_file(mbImpl, filename, tag_name, tag_val,
-                               distrib, parallel_option);
+                               distrib, parallel_option, with_ghosts);
         if (MB_SUCCESS != tmp_result) {
           result = tmp_result;
           std::cerr << "Couldn't read mesh; error message:" << std::endl;
@@ -160,7 +162,7 @@
           PRINT_LAST_ERROR
         }
         break;
-        
+
       default:
         std::cerr << "Unrecognized option \"" << this_opt
                   << "\"; skipping." << std::endl;
@@ -172,15 +174,6 @@
     if (MB_SUCCESS == tmp_result && 4 != this_opt) {
         // now figure out which vertices are shared
       MBParallelComm *pcomm = new MBParallelComm(mbImpl);
-      tmp_result = pcomm->resolve_shared_ents();
-      if (MB_SUCCESS != tmp_result) {
-        std::cerr << "Couldn't resolve shared entities; error message:" << std::endl;
-        PRINT_LAST_ERROR
-        result = tmp_result;
-        continue;
-      }
-      
-      if (0 == rank) shtime = MPI_Wtime();
 
       MBRange shared_ents;
       tmp_result = pcomm->get_shared_entities(0, shared_ents);
@@ -251,11 +244,10 @@
   if (0 == rank) std::cout << "Times: " 
                            << dtime-stime << " "
                            << rtime-stime << " "
-                           << shtime-rtime << " "
-                           << setime-shtime << " "
+                           << setime-rtime << " "
                            << ltime-setime << " "
                            << dtime - ltime
-                           << " (total/read/resolve/shared/report/delete)"
+                           << " (total/read/shared/report/delete)"
                            << std::endl;
    
   return (MB_SUCCESS == result ? 0 : 1);
@@ -328,7 +320,7 @@
 
 MBErrorCode read_file(MBInterface *mbImpl, const char *filename,
                       const char *tag_name, int tag_val,
-                      int distrib, int parallel_option) 
+                      int distrib, int parallel_option, int with_ghosts) 
 {
   std::ostringstream options;
   switch (parallel_option) {
@@ -354,6 +346,9 @@
   if (1 == distrib)
     options << ";PARTITION_DISTRIBUTE";
 
+  if (1 == with_ghosts)
+    options << ";PARALLEL_GHOSTS=3.0.1";
+
   options << ";CPUTIME";
     
   MBEntityHandle file_set;
@@ -717,22 +712,19 @@
   
     // get 3d entities and pack a buffer with them
   MBRange ents, new_ents, whole_range;
-  result = mbImpl->get_entities_by_dimension(0, 3, ents);
+  result = mbImpl->get_entities_by_handle(file_set, ents);
   RRA("Getting 3d ents failed.");
   
+  ents.insert(file_set);
+  
   MBParallelComm *pcomm = new MBParallelComm(mbImpl);
+  std::vector<unsigned char> buff(1024);
   int buff_size;
-  result = pcomm->pack_buffer(ents, false, true, true, false, -1,
-                              whole_range, buff_size);
+  result = pcomm->pack_buffer(ents, false, true, false, -1,
+                              whole_range, buff, buff_size);
   RRA("Packing buffer count (non-stored handles) failed.");
 
-  pcomm->buffer_size(buff_size);
-  
-  result = pcomm->pack_buffer(ents, false, true, false, false, -1,
-                              whole_range, buff_size);
-  RRA("Packing buffer (non-stored handles) failed.");
-
-  result = pcomm->unpack_buffer(new_ents, false, -1);
+  result = pcomm->unpack_buffer(&buff[0], false, -1, new_ents);
   RRA("Unacking buffer (non-stored handles) failed.");
 
   return MB_SUCCESS;

Modified: MOAB/trunk/parallel/MBParallelComm.cpp
===================================================================
--- MOAB/trunk/parallel/MBParallelComm.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/parallel/MBParallelComm.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -42,10 +42,7 @@
 
 #define INITIAL_BUFF_SIZE 1024
 
-unsigned char MBParallelComm::PROC_SHARED = 0x1;
-unsigned char MBParallelComm::PROC_OWNER = 0x2;
-
-// #define DEBUG_PACKING 1
+//#define DEBUG_PACKING 1
 #ifdef DEBUG_PACKING
 unsigned int __PACK_num = 0, __UNPACK_num = 0, __PACK_count = 0, __UNPACK_count = 0;
 std::string __PACK_string, __UNPACK_string;
@@ -111,9 +108,15 @@
       dynamic_cast<MBCore*>(mbImpl)->get_error_handler()->set_last_error(tmp_str.c_str()); \
       return result;}
 
+enum MBMessageTag {MB_MESG_ANY=MPI_ANY_TAG, 
+                   MB_MESG_SIZE,
+                   MB_MESG_ENTS,
+                   MB_MESG_REMOTE_HANDLES
+};
+
 MBParallelComm::MBParallelComm(MBInterface *impl, MPI_Comm comm) 
     : mbImpl(impl), procConfig(comm), sharedpTag(0), sharedpsTag(0),
-      sharedhTag(0), sharedhsTag(0), pstatusTag(0)
+      sharedhTag(0), sharedhsTag(0), pstatusTag(0), ifaceSetsTag(0)
 {
   myBuffer.resize(INITIAL_BUFF_SIZE);
 
@@ -125,7 +128,7 @@
                                std::vector<unsigned char> &tmp_buff, 
                                MPI_Comm comm) 
     : mbImpl(impl), procConfig(comm), sharedpTag(0), sharedpsTag(0),
-      sharedhTag(0), sharedhsTag(0), pstatusTag(0)
+      sharedhTag(0), sharedhsTag(0), pstatusTag(0), ifaceSetsTag(0)
 {
   myBuffer.swap(tmp_buff);
 }
@@ -199,121 +202,223 @@
   
   return MB_SUCCESS;
 }
-  
-MBErrorCode MBParallelComm::communicate_entities(const int from_proc, 
-                                                 const int to_proc,
-                                                 MBRange &entities,
-                                                 const bool adjacencies,
-                                                 const bool tags,
-                                                 const bool store_remote_handles) 
+
+MBErrorCode MBParallelComm::send_entities(const int to_proc,
+                                          MBRange &orig_ents,
+                                          const bool adjs,
+                                          const bool tags,
+                                          const bool store_remote_handles,
+                                          MBRange &final_ents,
+                                          bool wait_all) 
 {
-#ifndef USE_MPI
-  return MB_FAILURE;
-#else
 
-//  xxx - a. flag to include originating handle;
-//   b. flag to indicate whether to delete locally afterwards
-  MBErrorCode result = MB_SUCCESS;
+    // find a spot in the proc buffers vector
+  int index = get_buffers(to_proc);
   
-    // if I'm the from, do the packing and sending
-  if ((int)procConfig.proc_rank() == from_proc) {
-    allRanges.clear();
-    vertsPerEntity.clear();
-    setRange.clear();
-    setRanges.clear();
-    allTags.clear();
-    setSizes.clear();
-    optionsVec.clear();
-    setPcs.clear();
+    // pack/send the entities to the destination
+  MPI_Request req_vec[2] = {MPI_REQUEST_NULL,  // send req (ownerSBuff)
+                             MPI_REQUEST_NULL}; // recv req (remote handles)
+  MBErrorCode result = pack_send_entities(to_proc, orig_ents, 
+                                          adjs, tags, store_remote_handles,
+                                          ownerSBuffs[index], ownerRBuffs[index],
+                                          req_vec[0], req_vec[1], final_ents);
+  RRA("Failed to pack-send entities.");
 
-    MBRange whole_range;
+  MPI_Status statuses[2];
 
-    int buff_size;
-    
-    MBErrorCode result = pack_buffer(entities, adjacencies, tags, true, 
-                                     store_remote_handles, to_proc,
-                                     whole_range, buff_size); 
-    RRA("Failed to compute buffer size in communicate_entities.");
+    // if we're storing remote handles, process the return message
+  if (store_remote_handles) {
+    assert(MPI_REQUEST_NULL != req_vec[1]);
+    MPI_Wait(&req_vec[1], &statuses[1]);
+    MBRange remote_range;
+    unsigned char *buff_ptr = &ownerRBuffs[index][0];
+    UNPACK_RANGE(buff_ptr, remote_range);
+    result = set_remote_data(final_ents, remote_range, to_proc);
+    RRA("Trouble setting remote data range on sent entities.");
+  }
 
-      // if the message is large, send a first message to tell how large
-    if (INITIAL_BUFF_SIZE < buff_size) {
-      int tmp_buff_size = -buff_size;
-      MPI_Request send_req;
-      int success = MPI_Isend(&tmp_buff_size, sizeof(int), MPI_UNSIGNED_CHAR, to_proc, 
-                              0, procConfig.proc_comm(), &send_req);
-      if (success != MPI_SUCCESS) return MB_FAILURE;
+  if (wait_all) {
+      // wait for all to finish
+    int success = MPI_Waitall(2, req_vec, statuses);
+    if (success != MPI_SUCCESS) {
+      result = MB_FAILURE;
+      RRA("Failed in waitall in send_entities.");
     }
-    
-      // allocate space in the buffer
-    myBuffer.resize(buff_size);
+  }
+  
+  return MB_SUCCESS;
+}
 
-      // pack the actual buffer
-    int actual_buff_size;
-    result = pack_buffer(whole_range, adjacencies, tags, false, 
-                         store_remote_handles, to_proc,
-                         whole_range, actual_buff_size); 
-    RRA("Failed to pack buffer in communicate_entities.");
-    
-      // send it
-    MPI_Request send_req;
-    int success = MPI_Isend(&myBuffer[0], actual_buff_size, MPI_UNSIGNED_CHAR, to_proc, 
-                            0, procConfig.proc_comm(), &send_req);
-    if (!success) return MB_FAILURE;
+MBErrorCode MBParallelComm::recv_entities(const int from_proc,
+                                          const bool store_remote_handles,
+                                          MBRange &final_ents,
+                                          bool wait_all) 
+{
+  MBErrorCode result;
+  
+    // find a spot in the proc buffers vector
+  int index = get_buffers(from_proc);
+  
+    // recv/unpack entities from the sender
+  MPI_Request req = MPI_REQUEST_NULL;
+  MPI_Status status;
+  int success = MPI_Recv(&ghostRBuffs[index][0], ghostRBuffs[index].size(), 
+                         MPI_UNSIGNED_CHAR, from_proc, 
+                         MB_MESG_ANY, procConfig.proc_comm(), 
+                         &status);
+  if (MPI_SUCCESS != success) {
+    result = MB_FAILURE;
+    RRA("Recv failed in recv_ents.");
+  }
 
-      // now receive back remote range, if requested
-    if (store_remote_handles) {
-      MPI_Status status;
-      success = MPI_Recv(&myBuffer[0], myBuffer.size(), MPI_UNSIGNED_CHAR, to_proc, 
-                           MPI_ANY_TAG, procConfig.proc_comm(), &status);
-      if (!success) return MB_FAILURE;
-      
-      MBRange remote_range;
-      unsigned char *buff_ptr = (unsigned char *)&myBuffer[0];
-      UNPACK_RANGE(buff_ptr, remote_range);
-      
-      result = set_remote_data(whole_range, remote_range, to_proc);
-      RRA("Trouble setting remote data range on sent entities.");
+    // check type, and if it's just the size, resize buffer and re-call recv
+  if (MB_MESG_SIZE == status.MPI_TAG) {
+    result = recv_size_buff(from_proc,
+                            ghostRBuffs[index],
+                            req);
+    RRA("Failed to resize recv buffer.");
+    MPI_Wait(&req, &status);
+  }
+  
+    // ok, got the actual entities, now unpack
+  result = recv_unpack_entities(from_proc, store_remote_handles,
+                                ghostRBuffs[index], ghostSBuffs[index], 
+                                req, final_ents);
+  RRA("Failed to recv-unpack message.");
+
+  if (wait_all) {
+      // wait for last message to finish
+    int success = MPI_Wait(&req, &status);
+    if (success != MPI_SUCCESS) {
+      result = MB_FAILURE;
+      RRA("Failed in wait in recv_entities.");
     }
   }
-  else if ((int)procConfig.proc_rank() == to_proc) {
-    int buff_size;
+
+  return result;
+}
+
+int MBParallelComm::get_buffers(int to_proc) 
+{
+  int ind = -1;
+  std::vector<int>::iterator vit = 
+    std::find(buffProcs.begin(), buffProcs.end(), to_proc);
+  if (vit == buffProcs.end()) {
+    ind = buffProcs.size();
+    buffProcs.push_back(to_proc);
+    ownerSBuffs[ind].resize(INITIAL_BUFF_SIZE);
+    ghostRBuffs[ind].resize(INITIAL_BUFF_SIZE);
+      // allocate these other buffs in case we're storing remote handles
+    ownerRBuffs[ind].resize(INITIAL_BUFF_SIZE);
+    ghostSBuffs[ind].resize(INITIAL_BUFF_SIZE);
+      
+  }
+  else ind = vit - buffProcs.begin();
+  assert(ind < MAX_SHARING_PROCS);
+  return ind;
+}
+
+MBErrorCode MBParallelComm::pack_send_entities(const int to_proc,
+                                               MBRange &orig_ents,
+                                               const bool adjacencies,
+                                               const bool tags,
+                                               const bool store_remote_handles,
+                                               std::vector<unsigned char> &send_buff,
+                                               std::vector<unsigned char> &recv_buff,
+                                               MPI_Request &send_req,
+                                               MPI_Request &recv_req,
+                                               MBRange &final_ents) 
+{
+#ifndef USE_MPI
+  return MB_FAILURE;
+#else
+
+  MBErrorCode result = MB_SUCCESS;
+  MBRange whole_range;
+  int buff_size;
     
-      // get how much to allocate
-    MPI_Status status;
-    int success = MPI_Recv(&myBuffer[0], myBuffer.size(), MPI_UNSIGNED_CHAR, from_proc, 
-                           MPI_ANY_TAG, procConfig.proc_comm(), &status);
-    int num_recd;
-    success = MPI_Get_count(&status, MPI_UNSIGNED_CHAR, &num_recd);
+  result = pack_buffer(orig_ents, adjacencies, tags, 
+                       store_remote_handles, to_proc,
+                       final_ents, send_buff, buff_size); 
+  RRA("Failed to pack buffer in pack_send.");
+
+    // now that we know how many entities, post a receive for the 
+    // remote range, if requested
+  int success;
+  if (store_remote_handles) {
+    recv_buff.resize(2*num_subranges(final_ents)*sizeof(MBEntityHandle) + sizeof(int));
     
-    if (sizeof(int) == num_recd && 0 > *((int*)&myBuffer[0])) {
-        // this was just the size of the next message; prepare buffer then receive that message
-      buff_size = myBuffer[0];
-      myBuffer.resize(buff_size);
+    success = MPI_Irecv(&recv_buff[0], recv_buff.size(), MPI_UNSIGNED_CHAR, to_proc, 
+                        MB_MESG_REMOTE_HANDLES, procConfig.proc_comm(), 
+                        &recv_req);
+    if (success != MPI_SUCCESS) return MB_FAILURE;
+  }
+
+    // if the message is large, send a first message to tell how large
+  if (INITIAL_BUFF_SIZE < buff_size) {
+    int tmp_buff_size = -buff_size;
+    int success = MPI_Send(&tmp_buff_size, sizeof(int), MPI_UNSIGNED_CHAR, 
+                           to_proc, MB_MESG_SIZE, procConfig.proc_comm());
+    if (success != MPI_SUCCESS) return MB_FAILURE;
+  }
     
-      // receive the real message
-      success = MPI_Recv(&myBuffer[0], buff_size, MPI_UNSIGNED_CHAR, from_proc, 
-                         MPI_ANY_TAG, procConfig.proc_comm(), &status);
-    }
-    if (!success) return MB_FAILURE;
-    
-      // unpack the buffer
-    result = unpack_buffer(entities, store_remote_handles, from_proc); 
-    RRA("Failed to unpack buffer in communicate_entities.");
+    // send the buffer
+  success = MPI_Isend(&send_buff[0], buff_size, MPI_UNSIGNED_CHAR, to_proc, 
+                      MB_MESG_ENTS, procConfig.proc_comm(), &send_req);
+  if (success != MPI_SUCCESS) return MB_FAILURE;
 
-    if (store_remote_handles) {
-      MPI_Request send_req;
-      unsigned char *buff_ptr = (unsigned char *)&myBuffer[0];
-      PACK_RANGE(buff_ptr, entities);
-      int range_size = 2*num_subranges(entities)*sizeof(MBEntityHandle) +
-        sizeof(int);
-      success = MPI_Isend(&myBuffer[0], range_size, MPI_UNSIGNED_CHAR, to_proc, 
-                            0, procConfig.proc_comm(), &send_req);
-      if (!success) return MB_FAILURE;
+  return result;
+#endif
+}
+
+MBErrorCode MBParallelComm::recv_size_buff(const int from_proc,
+                                           std::vector<unsigned char> &recv_buff,
+                                           MPI_Request &recv_req) 
+{
+    // use the received size to resize buffer, then post another irecv
+  recv_buff.resize(*((int*)&recv_buff[0]));
+  int success = MPI_Irecv(&recv_buff[0], recv_buff.size(), MPI_UNSIGNED_CHAR, from_proc, 
+                          MB_MESG_ENTS, procConfig.proc_comm(), &recv_req);
+  if (MPI_SUCCESS != success) {
+    MBErrorCode result = MB_FAILURE;
+    RRA("Failed call to Irecv in recv_size_buff.");
+  }
+  
+  return MB_SUCCESS;
+}
+  
+MBErrorCode MBParallelComm::recv_unpack_entities(const int from_proc,
+                                                 const bool store_remote_handles,
+                                                 std::vector<unsigned char> &recv_buff,
+                                                 std::vector<unsigned char> &send_buff,
+                                                 MPI_Request &send_req,
+                                                 MBRange &recd_ents)
+{
+#ifndef USE_MPI
+  return MB_FAILURE;
+#else
+
+  MBErrorCode result = MB_SUCCESS;
+  
+    // unpack the buffer
+  result = unpack_buffer(&recv_buff[0], store_remote_handles, from_proc, recd_ents); 
+  RRA("Failed to unpack buffer in recv_unpack.");
+
+  if (store_remote_handles) {
+    int range_size = 2*num_subranges(recd_ents)*sizeof(MBEntityHandle) +
+      sizeof(int);
+    send_buff.resize(range_size);
+    unsigned char *buff_ptr = &send_buff[0];
+    PACK_RANGE(buff_ptr, recd_ents);
+    int success = MPI_Isend(&send_buff[0], range_size, MPI_UNSIGNED_CHAR, from_proc, 
+                            MB_MESG_REMOTE_HANDLES, procConfig.proc_comm(), &send_req);
+    if (success != MPI_SUCCESS) {
+      result = MB_FAILURE;
+      RRA("Failed to send handles in recv_unpack.");
     }
   }
   
   return result;
-
 #endif
 }
 
@@ -331,19 +436,11 @@
   MBRange whole_range;
   int buff_size;
   
-  allRanges.clear();
-  vertsPerEntity.clear();
-  setRange.clear();
-  setRanges.clear();
-  allTags.clear();
-  setSizes.clear();
-  optionsVec.clear();
-  setPcs.clear();
-
+  std::vector<unsigned char> buff;
   if ((int)procConfig.proc_rank() == from_proc) {
-    result = pack_buffer( entities, adjacencies, tags, true, 
+    result = pack_buffer( entities, adjacencies, tags, 
                           false, -1,
-                          whole_range, buff_size ); 
+                          whole_range, buff, buff_size); 
     RRA("Failed to compute buffer size in broadcast_entities.");
   }
 
@@ -353,23 +450,16 @@
   
   if (!buff_size) // no data
     return MB_SUCCESS;
-  
-  myBuffer.resize( buff_size );
-  
-  if ((int)procConfig.proc_rank() == from_proc) {
-    int actual_buffer_size;
-    result = pack_buffer( whole_range, adjacencies, tags, false, 
-                          false, -1,
-                          whole_range, actual_buffer_size );
-    RRA("Failed to pack buffer in broadcast_entities.");
-  }
 
-  success = MPI_Bcast( &myBuffer[0], buff_size, MPI_UNSIGNED_CHAR, from_proc, procConfig.proc_comm() );
+  if ((int)procConfig.proc_rank() != from_proc) 
+    buff.resize(buff_size);
+
+  success = MPI_Bcast( &buff[0], buff_size, MPI_UNSIGNED_CHAR, from_proc, procConfig.proc_comm() );
   if (MPI_SUCCESS != success)
     return MB_FAILURE;
   
   if ((int)procConfig.proc_rank() != from_proc) {
-    result = unpack_buffer( entities, false, from_proc);
+    result = unpack_buffer(&buff[0], false, from_proc, entities);
     RRA("Failed to unpack buffer in broadcast_entities.");
   }
 
@@ -377,13 +467,13 @@
 #endif
 }
 
-MBErrorCode MBParallelComm::pack_buffer(MBRange &entities, 
+MBErrorCode MBParallelComm::pack_buffer(MBRange &orig_ents, 
                                         const bool adjacencies,
                                         const bool tags,
-                                        const bool just_count,
                                         const bool store_remote_handles,
                                         const int to_proc,
-                                        MBRange &whole_range,
+                                        MBRange &final_ents,
+                                        std::vector<unsigned char> &buff,
                                         int &buff_size) 
 {
     // pack the buffer with the entity ranges, adjacencies, and tags sections
@@ -434,61 +524,145 @@
 
   MBErrorCode result;
 
+  std::vector<MBEntityType> ent_types;
+  std::vector<MBRange> all_ranges;
+  std::vector<int> verts_per_entity;
+  MBRange set_range;
+  std::vector<MBRange> set_ranges;
+  std::vector<MBTag> all_tags;
+  std::vector<MBRange> tag_ranges;
+  std::vector<int> set_sizes;
+  std::vector<unsigned int> options_vec;
+
   buff_size = 0;
   MBRange::const_iterator rit;
+  
+    //=================
+    // count first...
+    //=================
+
   unsigned char *buff_ptr = NULL;
-  if (!just_count) buff_ptr = &myBuffer[0];
   
     // entities
-  result = pack_entities(entities, rit, whole_range, buff_ptr, 
-                         buff_size, just_count, store_remote_handles, to_proc); 
-  RRA("Packing entities failed.");
+  result = pack_entities(orig_ents, rit, final_ents, buff_ptr,
+                         buff_size, true, store_remote_handles, to_proc,
+                         ent_types, all_ranges, verts_per_entity); 
+  RRA("Packing entities (count) failed.");
   
     // sets
-  int tmp_size;
-  result = pack_sets(entities, rit, whole_range, buff_ptr, tmp_size, just_count,
-                     store_remote_handles, to_proc); 
-  RRA("Packing sets failed.");
-  buff_size += tmp_size;
+  result = pack_sets(orig_ents, rit, final_ents, buff_ptr, buff_size, true,
+                     store_remote_handles, to_proc, set_range, set_ranges,
+                     set_sizes, options_vec); 
+  RRA("Packing sets (count) failed.");
   
     // adjacencies
   if (adjacencies) {
-    result = pack_adjacencies(entities, rit, whole_range, buff_ptr, 
-                              tmp_size, just_count,
+    result = pack_adjacencies(orig_ents, rit, final_ents, buff_ptr, 
+                              buff_size, true,
                               store_remote_handles, to_proc);
-    RRA("Packing adjs failed.");
-    buff_size += tmp_size;
+    RRA("Packing adjs (count) failed.");
   }
     
     // tags
   if (tags) {
-    result = pack_tags(entities, rit, whole_range, buff_ptr, 
-                       tmp_size, just_count,
-                       store_remote_handles, to_proc);
-    RRA("Packing tags failed.");
-    buff_size += tmp_size;
+    result = pack_tags(orig_ents, rit, final_ents, buff_ptr, 
+                       buff_size, true, store_remote_handles, to_proc, 
+                       all_tags, tag_ranges);
+    RRA("Packing tags (count) failed.");
   }
 
+    //=================
+    // now do the real packing
+    //=================
+
+  assert(0 <= buff_size);
+  buff.resize(buff_size);
+  int orig_buff_size = buff_size;
+  buff_size = 0;
+  buff_ptr = &buff[0];
+  
+    // entities
+  result = pack_entities(orig_ents, rit, final_ents, buff_ptr,
+                         buff_size, false, store_remote_handles, to_proc,
+                         ent_types, all_ranges, verts_per_entity); 
+  RRA("Packing entities (real) failed.");
+#ifdef DEBUG_PACKING
+  std::cerr << "pack_entities buffer space: " << buff_ptr - &buff[0] << " bytes." << std::endl;
+  unsigned char *tmp_buff = buff_ptr;
+#endif  
+  
+    // sets
+  result = pack_sets(orig_ents, rit, final_ents, buff_ptr, buff_size, false,
+                     store_remote_handles, to_proc, set_range, set_ranges,
+                     set_sizes, options_vec); 
+  RRA("Packing sets (real) failed.");
+#ifdef DEBUG_PACKING
+  std::cerr << "pack_sets buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
+  tmp_buff = buff_ptr;
+#endif  
+  
+    // adjacencies
+  if (adjacencies) {
+    result = pack_adjacencies(orig_ents, rit, final_ents, buff_ptr, 
+                              buff_size, false,
+                              store_remote_handles, to_proc);
+    RRA("Packing adjs (real) failed.");
+  }
+    
+    // tags
+  if (tags) {
+    result = pack_tags(orig_ents, rit, final_ents, buff_ptr, 
+                       buff_size, false, store_remote_handles, to_proc, all_tags,
+                       tag_ranges);
+    RRA("Packing tags (real) failed.");
+#ifdef DEBUG_PACKING
+    std::cerr << "pack_tags buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
+    tmp_buff = buff_ptr;
+#endif  
+  }
+
+    // original buffer size might be larger, because some
+    // ranges of local handles pack into more compact ranges of
+    // remote handles (because they're expressed using MBMAXTYPE plus
+    // index in new entity range, and that list of entities is likely
+    // to be compact)
+  assert(orig_buff_size >= buff_size);
+
   return result;
 }
  
-MBErrorCode MBParallelComm::unpack_buffer(MBRange &entities, 
+MBErrorCode MBParallelComm::unpack_buffer(unsigned char *buff_ptr,
                                           const bool store_remote_handles,
-                                          int from_proc) 
+                                          int from_proc,
+                                          MBRange &final_ents)
 {
   if (myBuffer.capacity() == 0) return MB_FAILURE;
   
-  unsigned char *buff_ptr = &myBuffer[0];
-  MBErrorCode result = unpack_entities(buff_ptr, entities, 
+#ifdef DEBUG_PACKING
+    unsigned char *tmp_buff = buff_ptr;
+#endif  
+  MBErrorCode result = unpack_entities(buff_ptr, final_ents, 
                                        store_remote_handles,
                                        from_proc);
   RRA("Unpacking entities failed.");
-  result = unpack_sets(buff_ptr, entities, store_remote_handles, 
+#ifdef DEBUG_PACKING
+    std::cerr << "unpack_entities buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
+    tmp_buff = buff_ptr;
+#endif  
+  result = unpack_sets(buff_ptr, final_ents, store_remote_handles, 
                        from_proc);
   RRA("Unpacking sets failed.");
-  result = unpack_tags(buff_ptr, entities, store_remote_handles,
+#ifdef DEBUG_PACKING
+    std::cerr << "unpack_sets buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
+    tmp_buff = buff_ptr;
+#endif  
+  result = unpack_tags(buff_ptr, final_ents, store_remote_handles,
                        from_proc);
   RRA("Unpacking tags failed.");
+#ifdef DEBUG_PACKING
+    std::cerr << "unpack_tags buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
+    tmp_buff = buff_ptr;
+#endif  
 
 #ifdef DEBUG_PACKING
   std::cerr << std::endl;
@@ -515,7 +689,10 @@
                                           int &count,
                                           const bool just_count,
                                           const bool store_remote_handles,
-                                          const int to_proc) 
+                                          const int to_proc,
+                                          std::vector<MBEntityType> &ent_types, 
+                                          std::vector<MBRange> &all_ranges, 
+                                          std::vector<int> &verts_per_entity) 
 {
     // (. w/ handles ? (0-no, 1-yes, range, 2-yes, vector))
     // ENTITIES:
@@ -529,8 +706,6 @@
     //   - }
     //   - if (handles) range/vector of remote handles
 
-  if (just_count) allRanges.clear();
-  count = 0;
   unsigned char *orig_buff_ptr = buff_ptr;
   MBErrorCode result;
   MBWriteUtilIface *wu = NULL;
@@ -544,40 +719,39 @@
     // pack vertices
   if (just_count) {
       // don't count size of verts until after all entities are included
-    entTypes.push_back(MBVERTEX);
-    vertsPerEntity.push_back(1);
-    allRanges.push_back(entities.subset_by_type(MBVERTEX));
+    ent_types.push_back(MBVERTEX);
+    verts_per_entity.push_back(1);
+    all_ranges.push_back(entities.subset_by_type(MBVERTEX));
   }
   else {
-    if (!allRanges[0].empty()) {
+    if (!all_ranges[0].empty()) {
       PACK_INT(buff_ptr, ((int) MBVERTEX));
-      PACK_INT(buff_ptr, ((int) allRanges[0].size()));
-      int num_verts = allRanges[0].size();
+      PACK_INT(buff_ptr, ((int) all_ranges[0].size()));
+      int num_verts = all_ranges[0].size();
       std::vector<double*> coords(3);
       for (int i = 0; i < 3; i++)
         coords[i] = reinterpret_cast<double*>(buff_ptr + i * num_verts * sizeof(double));
 
       assert(NULL != wu);
     
-      result = wu->get_node_arrays(3, num_verts, allRanges[0], 0, 0, coords);
+      result = wu->get_node_arrays(3, num_verts, all_ranges[0], 0, 0, coords);
       RR("Couldn't allocate node space.");
       PC(3*num_verts, " doubles");
 
       buff_ptr += 3 * num_verts * sizeof(double);
 
       if (store_remote_handles)
-        PACK_RANGE(buff_ptr, allRanges[0]);
+        PACK_RANGE(buff_ptr, all_ranges[0]);
 
 #ifdef DEBUG_PACKING
-      std::cerr << "Packed " << allRanges[0].size() << " vertices." << std::endl;
+      std::cerr << "Packed " << all_ranges[0].size() << " vertices." << std::endl;
 #endif      
     }
   }
 
-
     // place an iterator at the first non-vertex entity
-  if (!allRanges[0].empty()) {
-    start_rit = entities.find(*allRanges[0].rbegin());
+  if (!all_ranges[0].empty()) {
+    start_rit = entities.find(*all_ranges[0].rbegin());
     start_rit++;
   }
   else {
@@ -589,7 +763,7 @@
   // doesn't get appended and the unpack code fails.  -- j.kraftcheck
   //if (allRanges[0].size() == entities.size()) return MB_SUCCESS;
 
-  std::vector<MBRange>::iterator allr_it = allRanges.begin();
+  std::vector<MBRange>::iterator allr_it = all_ranges.begin();
   
     // pack entities
   if (just_count) {    
@@ -607,11 +781,11 @@
       eseq = dynamic_cast<ElementSequence*>(seq);
 
         // if type and nodes per element change, start a new range
-      if (eseq->type() != *entTypes.rbegin() || 
-          (int) eseq->nodes_per_element() != *vertsPerEntity.rbegin()) {
-        entTypes.push_back(eseq->type());
-        vertsPerEntity.push_back(eseq->nodes_per_element());
-        allRanges.push_back(MBRange());
+      if (eseq->type() != *ent_types.rbegin() || 
+          (int) eseq->nodes_per_element() != *verts_per_entity.rbegin()) {
+        ent_types.push_back(eseq->type());
+        verts_per_entity.push_back(eseq->nodes_per_element());
+        all_ranges.push_back(MBRange());
         allr_it++;
       }
     
@@ -619,26 +793,42 @@
       end_rit = entities.lower_bound(start_rit, entities.end(), eseq->end_handle()+1);
 
         // put these entities in the last range
-      std::copy(start_rit, end_rit, mb_range_inserter(*allRanges.rbegin()));
-      whole_range.merge(*allRanges.rbegin());
+      std::copy(start_rit, end_rit, mb_range_inserter(*all_ranges.rbegin()));
+
+        // remove any which are already shared
+      if (store_remote_handles) {
+        result = remove_nonowned_shared(*all_ranges.rbegin(), to_proc, false);
+        RRA("Failed nonowned_shared test.");
+      }
+
+      whole_range.merge(*all_ranges.rbegin());
       
         // now start where we last left off
       start_rit = end_rit;
     }
 
-      // update vertex range and count those data, now that we know which 
-      // entities get communicated
-    result = mbImpl->get_adjacencies(whole_range, 0, false, allRanges[0], 
+      // update vertex range to cover vertices included in other entities
+      // and remove entities already there
+    result = mbImpl->get_adjacencies(whole_range, 0, false, all_ranges[0], 
                                      MBInterface::UNION);
     RR("Failed get_adjacencies.");
-    whole_range.merge(allRanges[0]);
-    count += 3 * sizeof(double) * allRanges[0].size();
+
+    if (store_remote_handles) {
+      whole_range = whole_range.subtract(all_ranges[0]);
+      result = remove_nonowned_shared(all_ranges[0], to_proc, false);
+      RRA("Failed nonowned_shared test.");
+    }
     
+      // count those data, now that we know which 
+      // entities get communicated
+    whole_range.merge(all_ranges[0]);
+    count += 3 * sizeof(double) * all_ranges[0].size();
+    
       // space for the ranges
-    std::vector<MBRange>::iterator vit = allRanges.begin();
-    std::vector<int>::iterator iit = vertsPerEntity.begin();
-    std::vector<MBEntityType>::iterator eit = entTypes.begin();
-    for (; vit != allRanges.end(); vit++, iit++, eit++) {
+    std::vector<MBRange>::iterator vit = all_ranges.begin();
+    std::vector<int>::iterator iit = verts_per_entity.begin();
+    std::vector<MBEntityType>::iterator eit = ent_types.begin();
+    for (; vit != all_ranges.end(); vit++, iit++, eit++) {
         // entity type of this range, but passed as int
       count += sizeof(int);
       
@@ -646,10 +836,10 @@
       count += sizeof(int);
 
         // nodes per entity
-      if (iit != vertsPerEntity.begin()) count += sizeof(int);
+      if (iit != verts_per_entity.begin()) count += sizeof(int);
 
         // connectivity of subrange
-      if (iit != vertsPerEntity.begin()) {
+      if (iit != verts_per_entity.begin()) {
         count += *iit * sizeof(MBEntityHandle)*(*vit).size();
       }
       
@@ -664,11 +854,11 @@
   else {
       // for each range beyond the first
     allr_it++;
-    std::vector<int>::iterator nv_it = vertsPerEntity.begin();
-    std::vector<MBEntityType>::iterator et_it = entTypes.begin();
+    std::vector<int>::iterator nv_it = verts_per_entity.begin();
+    std::vector<MBEntityType>::iterator et_it = ent_types.begin();
     nv_it++; et_it++;
     
-    for (; allr_it != allRanges.end(); allr_it++, nv_it++, et_it++) {
+    for (; allr_it != all_ranges.end(); allr_it++, nv_it++, et_it++) {
         // pack the entity type
       PACK_INT(buff_ptr, ((int)*et_it));
 
@@ -709,11 +899,9 @@
       // pack MBMAXTYPE to indicate end of ranges
     PACK_INT(buff_ptr, ((int)MBMAXTYPE));
 
-    count = buff_ptr - orig_buff_ptr;
+    count += buff_ptr - orig_buff_ptr;
   }
 
-  if (!just_count) allRanges.clear();
-  
   if (debug_packing) std::cerr << std::endl << "Done packing entities." << std::endl;
 
   return MB_SUCCESS;
@@ -742,9 +930,9 @@
     int err;
       // in this case, substitute position in new_ents list
     for (int i = 0; i < num_ents; i++) {
-      int index = new_ents.index(from_vec[i]);
-      to_vec[i] = CREATE_HANDLE(MBMAXTYPE, index, err);
-      assert(to_vec[i] != 0 && !err && -1 != index);
+      int ind = new_ents.index(from_vec[i]);
+      to_vec[i] = CREATE_HANDLE(MBMAXTYPE, ind, err);
+      assert(to_vec[i] != 0 && !err && -1 != ind);
     }
   }
   else {
@@ -771,16 +959,16 @@
     MBEntityHandle *tmp_eh;
     for (tmp_eh = to_vec, i = 0; i < num_ents; i++) {
       if (!to_vec[i]) {
-        result = mbImpl->tag_get_data(sharedhs_tag, from_vec+i, 1, tmp_handles);
-        RRA("Trouble getting sharedhs tag.");
         result = mbImpl->tag_get_data(sharedps_tag, from_vec+i, 1, tmp_procs);
-        RRA("Trouble getting sharedps tag.");
-        for (int j = 0; j < MAX_SHARING_PROCS; j++)
-          if (tmp_procs[j] == to_proc) {
-            to_vec[i] = tmp_handles[j];
-            break;
-          }
-      
+        if (MB_SUCCESS == result) {
+          for (int j = 0; j < MAX_SHARING_PROCS; j++)
+            if (tmp_procs[j] == to_proc) {
+              result = mbImpl->tag_get_data(sharedhs_tag, from_vec+i, 1, tmp_handles);
+              RRA("Trouble getting sharedhs tag.");
+              to_vec[i] = tmp_handles[j];
+              break;
+            }
+        }
         if (!to_vec[i]) {
           int j = new_ents.index(from_vec[i]);
           if (-1 == j) {
@@ -807,22 +995,6 @@
 
 MBErrorCode MBParallelComm::get_remote_handles(const bool store_remote_handles,
                                                const MBRange &from_range, 
-                                               MBRange &to_range,
-                                               int to_proc,
-                                               const MBRange &new_ents) 
-{
-  std::vector<MBEntityHandle> to_vector(from_range.size());
-
-  MBErrorCode result =
-    get_remote_handles(store_remote_handles, from_range, &to_vector[0],
-                       to_proc, new_ents);
-  RRA("Trouble getting remote handles.");
-  std::copy(to_vector.begin(), to_vector.end(), mb_range_inserter(to_range));
-  return result;
-}
-
-MBErrorCode MBParallelComm::get_remote_handles(const bool store_remote_handles,
-                                               const MBRange &from_range, 
                                                MBEntityHandle *to_vec,
                                                int to_proc,
                                                const MBRange &new_ents) 
@@ -838,9 +1010,9 @@
     MBRange::iterator rit;
     unsigned int i;
     for (rit = from_range.begin(), i = 0; rit != from_range.end(); rit++, i++) {
-      int index = new_ents.index(*rit);
-      to_vec[i] = CREATE_HANDLE(MBMAXTYPE, index, err);
-      assert(to_vec[i] != 0 && !err && -1 != index);
+      int ind = new_ents.index(*rit);
+      to_vec[i] = CREATE_HANDLE(MBMAXTYPE, ind, err);
+      assert(to_vec[i] != 0 && !err && -1 != ind);
     }
   }
   else {
@@ -867,14 +1039,15 @@
     for (rit = from_range.begin(), i = 0; rit != from_range.end(); rit++, i++) {
       if (!to_vec[i]) {
         result = mbImpl->tag_get_data(sharedhs_tag, &(*rit), 1, tmp_handles);
-        RRA("Trouble getting sharedhs tag.");
-        result = mbImpl->tag_get_data(sharedps_tag, &(*rit), 1, tmp_procs);
-        RRA("Trouble getting sharedps tag.");
-        for (int j = 0; j < MAX_SHARING_PROCS; j++)
-          if (tmp_procs[j] == to_proc) {
-            to_vec[i] = tmp_handles[j];
-            break;
-          }
+        if (MB_SUCCESS == result) {
+          result = mbImpl->tag_get_data(sharedps_tag, &(*rit), 1, tmp_procs);
+          RRA("Trouble getting sharedps tag.");
+          for (int j = 0; j < MAX_SHARING_PROCS; j++)
+            if (tmp_procs[j] == to_proc) {
+              to_vec[i] = tmp_handles[j];
+              break;
+            }
+        }
       
         if (!to_vec[i]) {
           int j = new_ents.index(*rit);
@@ -896,6 +1069,22 @@
   return MB_SUCCESS;
 }
 
+MBErrorCode MBParallelComm::get_remote_handles(const bool store_remote_handles,
+                                               const MBRange &from_range, 
+                                               MBRange &to_range,
+                                               int to_proc,
+                                               const MBRange &new_ents) 
+{
+  std::vector<MBEntityHandle> to_vector(from_range.size());
+
+  MBErrorCode result =
+    get_remote_handles(store_remote_handles, from_range, &to_vector[0],
+                       to_proc, new_ents);
+  RRA("Trouble getting remote handles.");
+  std::copy(to_vector.begin(), to_vector.end(), mb_range_inserter(to_range));
+  return result;
+}
+
 MBErrorCode MBParallelComm::unpack_entities(unsigned char *&buff_ptr,
                                             MBRange &entities,
                                             const bool store_remote_handles,
@@ -1058,8 +1247,7 @@
     else {
       result = mbImpl->tag_get_data(sharedps_tag, &(*rit), 1,
                                     &remote_procs[0]);
-      RRA("Couldn't get sharedps tag.");
-      if (-1 != remote_procs[0]) {
+      if (MB_SUCCESS == result) {
         result = mbImpl->tag_get_data(sharedhs_tag, &(*rit), 1,
                                       &remote_handles[0]);
         RRA("Couldn't get sharedhs tag.");
@@ -1100,7 +1288,7 @@
   result = mbImpl->tag_get_data(pstatus_tag, local_range, shared_flags);
   RRA("Couldn't get shared tag");
   for (unsigned int i = 0; i < local_range.size(); i++)
-    shared_flags[i] |= PROC_SHARED;
+    shared_flags[i] |= PSTATUS_SHARED;
   result = mbImpl->tag_set_data(pstatus_tag, local_range, shared_flags);
   RRA("Couldn't set shared tag");
   
@@ -1141,8 +1329,7 @@
     else {
       result = mbImpl->tag_get_data(sharedps_tag, &local_ents[rit], 1,
                                     &remote_procs[0]);
-      RRA("Couldn't get sharedps tag.");
-      if (-1 != remote_procs[0]) {
+      if (MB_SUCCESS == result) {
         result = mbImpl->tag_get_data(sharedhs_tag, &local_ents[rit], 1,
                                       &remote_handles[0]);
         RRA("Couldn't get sharedhs tag.");
@@ -1188,7 +1375,7 @@
                                 shared_flags);
   RRA("Couldn't get shared tag");
   for (int i = 0; i < num_ents; i++)
-    shared_flags[i] |= PROC_SHARED;
+    shared_flags[i] |= PSTATUS_SHARED;
   result = mbImpl->tag_set_data(pstatus_tag, local_ents, 
                                 num_ents, shared_flags);
   RRA("Couldn't set shared tag");
@@ -1217,7 +1404,11 @@
                                       int &count,
                                       const bool just_count,
                                       const bool store_remote_handles,
-                                      const int to_proc)
+                                      const int to_proc,
+                                      MBRange &set_range,
+                                      std::vector<MBRange> &set_ranges,
+                                      std::vector<int> &set_sizes,
+                                      std::vector<unsigned int> &options_vec)
 {
     // SETS:
     // . #sets
@@ -1233,43 +1424,39 @@
     //   - if (#children) handles[#children]
   
     // now the sets; assume any sets the application wants to pass are in the entities list
-  count = 0;
   unsigned char *orig_buff_ptr = buff_ptr;
   MBErrorCode result;
 
   if (just_count) {
-      // num of sets
-    count += sizeof(int);
+    int ranges_size = 0, vecs_size = 0, tot_parch = 0;
     
     for (; start_rit != entities.end(); start_rit++) {
-      setRange.insert(*start_rit);
+      set_range.insert(*start_rit);
     
       unsigned int options;
       result = mbImpl->get_meshset_options(*start_rit, options);
       RR("Failed to get meshset options.");
-      optionsVec.push_back(options);
+      options_vec.push_back(options);
 
-        // option
-      count += sizeof(unsigned int);
-    
       if (options & MESHSET_SET) {
           // range-based set; count the subranges
-        setRanges.push_back(MBRange());
-        result = mbImpl->get_entities_by_handle(*start_rit, *setRanges.rbegin());
+        set_ranges.push_back(MBRange());
+        result = mbImpl->get_entities_by_handle(*start_rit, *set_ranges.rbegin());
         RRA("Failed to get set entities.");
 
           // set range
-        count += 2 * sizeof(MBEntityHandle) * num_subranges(*setRanges.rbegin()) + sizeof(int);
+        ranges_size += 2 * sizeof(MBEntityHandle) * num_subranges(*set_ranges.rbegin()) + 
+          sizeof(int);
       }
       else if (options & MESHSET_ORDERED) {
           // just get the number of entities in the set
         int num_ents;
         result = mbImpl->get_number_entities_by_handle(*start_rit, num_ents);
         RR("Failed to get number entities in ordered set.");
-        setSizes.push_back(num_ents);
+        set_sizes.push_back(num_ents);
 
           // set vec
-        count += sizeof(MBEntityHandle) * num_ents + sizeof(int);
+        vecs_size += sizeof(MBEntityHandle) * num_ents + sizeof(int);
       }
 
         // get numbers of parents/children
@@ -1280,31 +1467,43 @@
       result = mbImpl->num_parent_meshsets(*start_rit, &num_par);
       RR("Failed to get num parents.");
 
-        // set children, parents
-      count += 2*sizeof(int) + (num_par + num_ch) * sizeof(MBEntityHandle);
+      tot_parch += num_ch + num_par;
+      
     }
 
+      // num of sets
+    count += sizeof(int);
+    
+      // options
+    count += set_range.size() * sizeof(unsigned int);
+
+      // range, vector sizes
+    count += ranges_size + vecs_size;
+    
+      // set children, parents
+    count += 2 * set_range.size() * sizeof(int) + tot_parch * sizeof(MBEntityHandle);
+
         // set handles
-    if (!setRange.empty())
-      count += sizeof(int) + 2*sizeof(MBEntityHandle)*num_subranges(setRange);
+    if (!set_range.empty() && store_remote_handles)
+      count += sizeof(int) + 2*sizeof(MBEntityHandle)*num_subranges(set_range);
 
-    whole_range.merge(setRange);
+    whole_range.merge(set_range);
   }
   else {
     
       // set handle range
-    PACK_INT(buff_ptr, setRange.size());
+    PACK_INT(buff_ptr, set_range.size());
 
       // option values
-    if (!setRange.empty())
-      PACK_VOID(buff_ptr, &optionsVec[0], setRange.size()*sizeof(unsigned int));
+    if (!set_range.empty())
+      PACK_VOID(buff_ptr, &options_vec[0], set_range.size()*sizeof(unsigned int));
 
-    std::vector<unsigned int>::const_iterator opt_it = optionsVec.begin();
-    std::vector<MBRange>::const_iterator rit = setRanges.begin();
-    std::vector<int>::const_iterator mem_it = setSizes.begin();
+    std::vector<unsigned int>::const_iterator opt_it = options_vec.begin();
+    std::vector<MBRange>::const_iterator rit = set_ranges.begin();
+    std::vector<int>::const_iterator mem_it = set_sizes.begin();
     static std::vector<MBEntityHandle> members;
 
-    for (MBRange::const_iterator set_it = setRange.begin(); set_it != setRange.end(); 
+    for (MBRange::const_iterator set_it = set_range.begin(); set_it != set_range.end(); 
          set_it++, opt_it++) {
       if ((*opt_it) & MESHSET_SET) {
           // pack entities as a range
@@ -1332,40 +1531,59 @@
       }
     }
     
-      // now pack parents/children
-    for (MBRange::const_iterator set_it = setRange.begin(); set_it != setRange.end(); 
+      // pack numbers of parents/children
+    unsigned int tot_pch = 0;
+    for (MBRange::const_iterator set_it = set_range.begin(); set_it != set_range.end(); 
          set_it++) {
         // pack parents
-      members.clear();
-      result = mbImpl->get_parent_meshsets(*set_it, members);
+      int num_pch;
+      result = mbImpl->num_parent_meshsets(*set_it, &num_pch);
+      RRA("Failed to get num parents.");
+      PACK_INT(buff_ptr, num_pch);
+      tot_pch += num_pch;
+      result = mbImpl->num_child_meshsets(*set_it, &num_pch);
+      RRA("Failed to get num children.");
+      PACK_INT(buff_ptr, num_pch);
+      tot_pch += num_pch;
+    }
+
+      // now pack actual parents/children
+    members.clear();
+    members.reserve(tot_pch);
+    std::vector<MBEntityHandle> tmp_pch;
+    for (MBRange::const_iterator set_it = set_range.begin(); set_it != set_range.end(); 
+         set_it++) {
+      result = mbImpl->get_parent_meshsets(*set_it, tmp_pch);
       RRA("Failed to get parents.");
-      int num_par = members.size();
-      result = mbImpl->get_child_meshsets(*set_it, members);
+      std::copy(tmp_pch.begin(), tmp_pch.end(), std::back_inserter(members));
+      tmp_pch.clear();
+      result = mbImpl->get_child_meshsets(*set_it, tmp_pch);
       RRA("Failed to get children.");
-      PACK_INT(buff_ptr, num_par);
-      PACK_INT(buff_ptr, members.size() - num_par);
-      if (!members.empty()) {
-        result = get_remote_handles(store_remote_handles,
-                                    &members[0], &members[0], 
-                                    members.size(), to_proc,
-                                    whole_range);
-        RRA("Trouble getting remote handles for set parent/child sets.");
-#ifdef DEBUG_PACKING
-          // check that all handles are either sets or maxtype
-        for (unsigned int __j = 0; __j < members.size(); __j++)
-          assert((TYPE_FROM_HANDLE(members[__j]) == MBMAXTYPE &&
-                  ID_FROM_HANDLE(members[__j]) < (int)whole_range.size()) ||
-                 TYPE_FROM_HANDLE(members[__j]) == MBENTITYSET);
+      std::copy(tmp_pch.begin(), tmp_pch.end(), std::back_inserter(members));
+      tmp_pch.clear();
+    }
+    assert(members.size() == tot_pch);
+    if (!members.empty()) {
+      result = get_remote_handles(store_remote_handles,
+                                  &members[0], &members[0], 
+                                  members.size(), to_proc,
+                                  whole_range);
+      RRA("Trouble getting remote handles for set parent/child sets.");
+#ifndef NDEBUG
+        // check that all handles are either sets or maxtype
+      for (unsigned int __j = 0; __j < members.size(); __j++)
+        assert((TYPE_FROM_HANDLE(members[__j]) == MBMAXTYPE &&
+                ID_FROM_HANDLE(members[__j]) < (int)whole_range.size()) ||
+               TYPE_FROM_HANDLE(members[__j]) == MBENTITYSET);
 #endif        
-        PACK_EH(buff_ptr, &members[0], members.size());
-      }
+      PACK_EH(buff_ptr, &members[0], members.size());
     }
     
-      // pack the handles
-    if (store_remote_handles && !setRange.empty())
-      PACK_RANGE(buff_ptr, setRange);
+    // pack the handles
+    if (store_remote_handles && !set_range.empty())
+      PACK_RANGE(buff_ptr, set_range);
 
-    count = buff_ptr - orig_buff_ptr;
+    count += buff_ptr - orig_buff_ptr;
   }
 
   if (debug_packing) std::cerr << std::endl << "Done packing sets." << std::endl;
@@ -1390,10 +1608,10 @@
          
   std::vector<MBEntityHandle> members;
   int num_ents;
-  optionsVec.resize(num_sets);
+  std::vector<unsigned int> options_vec(num_sets);
       // option value
   if (num_sets)
-    UNPACK_VOID(buff_ptr, &optionsVec[0], num_sets*sizeof(unsigned int));
+    UNPACK_VOID(buff_ptr, &options_vec[0], num_sets*sizeof(unsigned int));
 
     // create sets
   int i;
@@ -1402,7 +1620,7 @@
     
       // create the set
     MBEntityHandle set_handle;
-    result = mbImpl->create_meshset(optionsVec[i], set_handle);
+    result = mbImpl->create_meshset(options_vec[i], set_handle);
     RRA("Failed to create set in unpack.");
     new_sets.insert(set_handle);
   }
@@ -1413,7 +1631,7 @@
   entities.merge(new_sets);
   
   for (rit = new_sets.begin(), i = 0; rit != new_sets.end(); rit++, i++) {
-    if (optionsVec[i] & MESHSET_SET) {
+    if (options_vec[i] & MESHSET_SET) {
         // unpack entities as a range
       MBRange set_range, tmp_range;
       UNPACK_RANGE(buff_ptr, tmp_range);
@@ -1422,7 +1640,7 @@
       result = mbImpl->add_entities(*rit, set_range);
       RRA("Failed to add ents to unordered set in unpack.");
     }
-    else if (optionsVec[i] & MESHSET_ORDERED) {
+    else if (options_vec[i] & MESHSET_ORDERED) {
         // unpack entities as vector, with length
       UNPACK_INT(buff_ptr, num_ents);
       members.resize(num_ents);
@@ -1433,27 +1651,38 @@
       RRA("Failed to add ents to ordered set in unpack.");
     }
   }
+
+  std::vector<int> num_pch(2*new_sets.size());
+  std::vector<int>::iterator vit;
+  int tot_pch = 0;
+  for (vit = num_pch.begin(); vit != num_pch.end(); vit++) {
+    UNPACK_INT(buff_ptr, *vit);
+    tot_pch += *vit;
+  }
   
+  members.resize(tot_pch);
+  UNPACK_EH(buff_ptr, &members[0], tot_pch);
+  result = get_local_handles(&members[0], tot_pch, entities);
+  RRA("Couldn't get local handle for parent/child sets.");
+
+  int num = 0;
+  MBEntityHandle *mem_ptr = &members[0];
   for (rit = new_sets.begin(); rit != new_sets.end(); rit++) {
       // unpack parents/children
-    int num_par, num_child;
-    UNPACK_INT(buff_ptr, num_par);
-    UNPACK_INT(buff_ptr, num_child);
+    int num_par = num_pch[num++], num_child = num_pch[num++];
     if (num_par+num_child) {
-      members.resize(num_par+num_child);
-      UNPACK_EH(buff_ptr, &members[0], num_par+num_child);
-      result = get_local_handles(&members[0], num_par+num_child, entities);
-      RRA("Couldn't get local handle for parent/child sets.");
       for (i = 0; i < num_par; i++) {
-        assert(0 != members[i]);
-        result = mbImpl->add_parent_meshset(*rit, members[i]);
+        assert(0 != mem_ptr[i]);
+        result = mbImpl->add_parent_meshset(*rit, mem_ptr[i]);
         RRA("Failed to add parent to set in unpack.");
       }
-      for (i = num_par; i < num_par+num_child; i++) {
-        assert(0 != members[i]);
-        result = mbImpl->add_child_meshset(*rit, members[i]);
+      mem_ptr += num_par;
+      for (i = 0; i < num_child; i++) {
+        assert(0 != mem_ptr[i]);
+        result = mbImpl->add_child_meshset(*rit, mem_ptr[i]);
         RRA("Failed to add child to set in unpack.");
       }
+      mem_ptr += num_child;
     }
   }
 
@@ -1497,14 +1726,15 @@
                                       int &count,
                                       const bool just_count,
                                       const bool store_remote_handles,
-                                      const int to_proc)
+                                      const int to_proc,
+                                      std::vector<MBTag> &all_tags,
+                                      std::vector<MBRange> &tag_ranges)
 {
     // tags
     // get all the tags
     // for dense tags, compute size assuming all entities have that tag
     // for sparse tags, get number of entities w/ that tag to compute size
 
-  count = 0;
   unsigned char *orig_buff_ptr = buff_ptr;
   MBErrorCode result;
   std::vector<int> var_len_sizes;
@@ -1512,11 +1742,11 @@
 
   if (just_count) {
 
-    std::vector<MBTag> all_tags;
-    result = tagServer->get_tags(all_tags);
+    std::vector<MBTag> tmp_tags;
+    result = tagServer->get_tags(tmp_tags);
     RR("Failed to get tags in pack_tags.");
 
-    for (std::vector<MBTag>::iterator tag_it = all_tags.begin(); tag_it != all_tags.end(); tag_it++) {
+    for (std::vector<MBTag>::iterator tag_it = tmp_tags.begin(); tag_it != tmp_tags.end(); tag_it++) {
       const TagInfo *tinfo = tagServer->get_tag_info(*tag_it);
       MBRange tmp_range;
       result = tagServer->get_entities(*tag_it, tmp_range);
@@ -1527,7 +1757,7 @@
         continue;
 
         // ok, we'll be sending this tag
-      allTags.push_back(*tag_it);
+      all_tags.push_back(*tag_it);
 
         // default value
       count += sizeof(int);
@@ -1542,7 +1772,7 @@
       count += tinfo->get_name().size();
 
       if (!tmp_range.empty()) {
-        tagRanges.push_back(tmp_range);
+        tag_ranges.push_back(tmp_range);
 
         // range of tag
         count += sizeof(int) + tmp_range.size() * sizeof(MBEntityHandle);
@@ -1572,11 +1802,11 @@
 
   else {
     std::vector<unsigned char> tag_data;
-    std::vector<MBRange>::const_iterator tr_it = tagRanges.begin();
+    std::vector<MBRange>::const_iterator tr_it = tag_ranges.begin();
 
-    PACK_INT(buff_ptr, allTags.size());
+    PACK_INT(buff_ptr, all_tags.size());
     
-    for (std::vector<MBTag>::const_iterator tag_it = allTags.begin(); tag_it != allTags.end(); tag_it++) {
+    for (std::vector<MBTag>::const_iterator tag_it = all_tags.begin(); tag_it != all_tags.end(); tag_it++) {
 
       const TagInfo *tinfo = tagServer->get_tag_info(*tag_it);
 
@@ -1608,7 +1838,15 @@
       result = get_remote_handles(store_remote_handles,
                                   (*tr_it), (MBEntityHandle*)buff_ptr, to_proc,
                                   whole_range);
-      RR("Trouble getting remote handles for tagged entities.");
+#ifdef DEBUG_PACKING
+      if (MB_SUCCESS != result) {
+        std::cerr << "Trouble getting remote handles for tagged entities:" << std::endl;
+        (*tr_it).print("  ");
+      }
+#else
+      RRA("Trouble getting remote handles for tagged entities.");
+#endif
+
       buff_ptr += (*tr_it).size() * sizeof(MBEntityHandle);
 
       const size_t num_ent = tr_it->size();
@@ -1617,21 +1855,21 @@
         var_len_values.resize( num_ent, 0 );
         result = mbImpl->tag_get_data(*tag_it, *tr_it, &var_len_values[0], 
                                       &var_len_sizes[0] );
-        RR("Failed to get variable-length tag data in pack_tags.");
+        RRA("Failed to get variable-length tag data in pack_tags.");
         PACK_INTS(buff_ptr, &var_len_sizes[0], num_ent);
         for (unsigned int i = 0; i < num_ent; ++i)
           PACK_VOID(buff_ptr, var_len_values[i], var_len_sizes[i]);
       }
       else {
         result = mbImpl->tag_get_data(*tag_it, *tr_it, buff_ptr);
-        RR("Failed to get tag data in pack_tags.");
+        RRA("Failed to get tag data in pack_tags.");
         buff_ptr += num_ent * tinfo->get_size();
-        UPC(num_ent*tinfo->get_size(), " void");
+        PC(num_ent*tinfo->get_size(), " void");
       }
       tr_it++;
     }
 
-    count = buff_ptr - orig_buff_ptr;
+    count += buff_ptr - orig_buff_ptr;
   }
   
   if (debug_packing) std::cerr << std::endl << "Done packing tags." << std::endl;
@@ -1769,18 +2007,6 @@
   return MB_SUCCESS;
 }
 
-bool MBParallelComm::buffer_size(const unsigned int new_size) 
-{
-  unsigned int old_size = myBuffer.size();
-  myBuffer.resize(new_size);
-  return (new_size == old_size);
-}
-
-void MBParallelComm::take_buffer(std::vector<unsigned char> &new_buffer) 
-{
-  new_buffer.swap(myBuffer);
-}
-
 MBErrorCode MBParallelComm::resolve_shared_ents(int dim,
                                                 int shared_dim) 
 {
@@ -1808,7 +2034,12 @@
                                                 int shared_dim) 
 {
   if (debug) std::cerr << "Resolving shared entities." << std::endl;
+
+  if (proc_ents.empty()) return MB_SUCCESS;
   
+  if (-1 == shared_dim)
+    shared_dim = mbImpl->dimension_from_handle(*proc_ents.begin())-1;
+  
     // get the skin entities by dimension
   MBRange skin_ents[4];
   MBErrorCode result;
@@ -1908,11 +2139,12 @@
   
     // call gather-scatter to get shared ids & procs
   gs_data *gsd;
-  if (sizeof(int) != sizeof(long)) {
+  assert(sizeof(ulong_) == sizeof(MBEntityHandle));
+  if (sizeof(int) != sizeof(ulong_)) {
     std::vector<long> lgid_data(gid_data.size());
     std::copy(gid_data.begin(), gid_data.end(), lgid_data.begin());
-    gsd = gs_data_setup(skin_ents[0].size(), &lgid_data[0], (ulong_*)&handle_vec[0], 2, 
-                        1, 1, cd);
+    gsd = gs_data_setup(skin_ents[0].size(), &lgid_data[0], 
+                        (ulong_*)&handle_vec[0], 2, 1, 1, cd);
   }
   else {
     gsd = gs_data_setup(skin_ents[0].size(), (long*)&gid_data[0], 
@@ -1968,9 +2200,10 @@
                            proc_nranges);
   RRA("Trouble tagging shared entities.");
   
-    // create the sets for each interface
+    // create the sets for each interface; store them as tags on
+    // the interface instance
   MBRange iface_sets;
-  result = create_interface_sets(proc_nranges, iface_sets);
+  result = create_interface_sets(proc_nranges, &iface_sets);
   RRA("Trouble creating iface sets.");
 
     // resolve shared ent remote handles
@@ -2027,8 +2260,10 @@
 }
 
 MBErrorCode MBParallelComm::create_interface_sets(std::map<std::vector<int>, MBRange> &proc_nranges,
-                                                  MBRange &iface_sets) 
+                                                  MBRange *iface_sets_ptr) 
 {
+  if (proc_nranges.empty()) return MB_SUCCESS;
+  
   MBTag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
   MBErrorCode result = get_shared_proc_tags(sharedp_tag, sharedps_tag, 
                                             sharedh_tag, sharedhs_tag,
@@ -2043,17 +2278,21 @@
                               tmp_iface_tag, &tmp_iface_set);
   RRA("Failed to create temporary iface set tag.");
 
-    // get all partition sets and mark contents with iface set tag
+  MBRange psets;
+  if (!iface_sets_ptr) iface_sets_ptr = &psets;
+  
+    // get all partition sets and mark contents with iface set tag; 
+    // pre-use iface_sets
   MBTag pset_tag;
   MBRange tmp_ents, tmp_ents2;
 ;
   result = mbImpl->tag_get_handle(PARALLEL_PARTITION_TAG_NAME, pset_tag);
   RRA("Couldn't get PARALLEL_PARTITION tag, needed to create iface sets.");
   result = mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &pset_tag, NULL, 1,
-                                                iface_sets);
+                                                psets);
   RRA("Couldn't get PARALLEL_PARTITION sets.");
-  for (rit = iface_sets.begin(); rit != iface_sets.end(); rit++) {
-    result = mbImpl->get_entities_by_handle(*rit, tmp_ents);
+  for (rit = psets.begin(); rit != psets.end(); rit++) {
+    result = mbImpl->get_entities_by_handle(*rit, tmp_ents, true);
     RR("Failed to get entities in partition set.");
     std::vector<MBEntityHandle> tag_vals(tmp_ents.size());
     std::fill(tag_vals.begin(), tag_vals.end(), *rit);
@@ -2070,13 +2309,16 @@
     MBEntityHandle new_set;
     result = mbImpl->create_meshset(MESHSET_SET, new_set); 
     RR("Failed to create interface set.");
-    iface_sets.insert(new_set);
+    iface_sets_ptr->insert(new_set);
+
+    int nump = 0;
+    while (((*mit).first)[nump] != -1 && nump < MAX_SHARING_PROCS) nump++;
     
       // add entities
     result = mbImpl->add_entities(new_set, (*mit).second); 
     RR("Failed to add entities to interface set.");
       // tag set with the proc rank(s)
-    if (((*mit).first).size() == 1)
+    if (nump == 1)
       result = mbImpl->tag_set_data(sharedp_tag, &new_set, 1, 
                                     &((*mit).first)[0]); 
     else
@@ -2100,16 +2342,17 @@
 
     // now go back through interface sets and add parent/child links
   for (int d = 2; d >= 0; d--) {
-    for (MBRange::iterator rit = iface_sets.begin(); rit != iface_sets.end();
+    for (rit = iface_sets_ptr->begin(); rit != iface_sets_ptr->end();
          rit++) {
+      
       tmp_ents.clear();
-      result = mbImpl->get_entities_by_handle(*rit, tmp_ents);
+      result = mbImpl->get_entities_by_handle(*rit, tmp_ents, true);
       RR("Couldn't get entities by dimension.");
       if (tmp_ents.empty() || 
           mbImpl->dimension_from_handle(*tmp_ents.rbegin()) != d) continue;
 
         // get higher-dimensional entities and their interface sets
-      result = mbImpl->get_adjacencies(&(*tmp_ents.rbegin()), 1, d+1,
+      result = mbImpl->get_adjacencies(&(*tmp_ents.begin()), 1, d+1,
                                        false, tmp_ents2);
       RR("Couldn't get adjacencies for interface sets.");
       tag_vals.resize(tmp_ents2.size());
@@ -2117,10 +2360,12 @@
       RR("Couldn't get iface set tag for interface sets.");
       
         // go through and for any on interface make it a parent
+      MBEntityHandle last_set = 0;
       for (unsigned int i = 0; i < tag_vals.size(); i++) {
-        if (tag_vals[i]) {
+        if (tag_vals[i] && tag_vals[i] != last_set) {
           result = mbImpl->add_parent_child(tag_vals[i], *rit);
           RR("Couldn't add parent/child link for interface set.");
+          last_set = tag_vals[i];
         }
       }
     }
@@ -2129,6 +2374,18 @@
     // delete the temporary tag
   result = mbImpl->tag_delete(tmp_iface_tag);
   RR("Couldn't delete tmp iface tag.");
+
+    // get interface sets tag, reuse tmp_iface_tag
+  tmp_iface_tag = iface_sets_tag();
+  MBEntityHandle tmp_iface_sets[MAX_SHARING_PROCS];
+  std::fill(tmp_iface_sets, tmp_iface_sets+MAX_SHARING_PROCS, 0);
+  unsigned int i;
+  for (rit = iface_sets_ptr->begin(), i = 0; rit != iface_sets_ptr->end(); 
+       rit++, i++)
+    tmp_iface_sets[i] = *rit;
+  result = mbImpl->tag_set_data(iface_sets_tag(), NULL, 0,
+                                tmp_iface_sets);
+  RRA("Couldn't set iface sets tag on MOAB interface.");
   
   return MB_SUCCESS;
 }
@@ -2146,22 +2403,41 @@
   const MBEntityHandle *connect; int num_connect;
   std::vector<int> sharing_procs(MAX_SHARING_PROCS);
   std::fill(sharing_procs.begin(), sharing_procs.end(), -1);
+  std::vector<unsigned char> pstatus_flags(MB_MAX_SUB_ENTITIES);
 
   for (int d = shared_dim; d > 0; d--) {
     for (MBRange::iterator rit = skin_ents[d].begin();
          rit != skin_ents[d].end(); rit++) {
         // get connectivity
       result = mbImpl->get_connectivity(*rit, connect, num_connect);
-      RR("Failed to get connectivity on non-vertex skin entities.");
+      RRA("Failed to get connectivity on non-vertex skin entities.");
       MBRange sp_range, vp_range;
+
+        // if any vertices not shared, this entity isn't
+      assert(num_connect <= MB_MAX_SUB_ENTITIES);
+      bool is_shared = true;
+      result = mbImpl->tag_get_data(pstatus_tag, connect, num_connect,
+                                    &pstatus_flags[0]);
+      RRA("Couldn't get pstatus flag.");
       for (int nc = 0; nc < num_connect; nc++) {
+        if (!(pstatus_flags[nc] & PSTATUS_SHARED)) {
+          is_shared = false;
+          break;
+        }
+      }
+      if (!is_shared) continue;
+
+      bool and_zero = false;
+      for (int nc = 0; nc < num_connect; nc++) {
           // get sharing procs
-        result = mbImpl->tag_get_data(sharedp_tag, &(*rit), 1, &sharing_procs[0]);
+        result = mbImpl->tag_get_data(sharedp_tag, connect+nc, 1, &sharing_procs[0]);
         RR("Couldn't get sharedp_tag on skin vertices in entity.");
         if (sharing_procs[0] == -1) {
-          result = mbImpl->tag_get_data(sharedps_tag, &(*rit), 1, &sharing_procs[0]);
+          result = mbImpl->tag_get_data(sharedps_tag, connect+nc, 1, &sharing_procs[0]);
           RR("Couldn't get sharedps_tag on skin vertices in entity.");
         }
+        assert(-1 != sharing_procs[0]);
+        
           // build range of sharing procs for this vertex
         unsigned int p = 0; vp_range.clear();
         while (sharing_procs[p] != -1 && p < MAX_SHARING_PROCS)
@@ -2170,14 +2446,20 @@
           // intersect with range for this skin ent
         if (0 != nc) sp_range = sp_range.intersect(vp_range);
         else sp_range = vp_range;
+
+          // need to also save rank zero, since ranges don't handle that
+        if (sharing_procs[0] == 0) and_zero = true;
       }
+
         // intersection is the owning proc(s) for this skin ent; should
         // not be empty
-      assert(!sp_range.empty());
+      assert(!sp_range.empty() || and_zero);
       MBRange::iterator rit2;
         // set tag for this ent
-      int j;
-      for (j = 0, rit2 = sp_range.begin(); rit2 != sp_range.end(); 
+      int j = 0;
+      if (and_zero) sharing_procs[j++] = 0;
+      
+      for (rit2 = sp_range.begin(); rit2 != sp_range.end(); 
            rit2++, j++) sharing_procs[j] = *rit2;
       proc_nranges[sharing_procs].insert(*rit);
       if (2 > j) {
@@ -2190,6 +2472,12 @@
       }
       RR("Failed to set sharedp(s)_tag on non-vertex skin entity.");
       
+      unsigned char share_flag = PSTATUS_SHARED;
+      if ((int) procConfig.proc_rank() > sharing_procs[0]) 
+        share_flag |= PSTATUS_NOT_OWNED;
+      result = mbImpl->tag_set_data(pstatus_tag, &(*rit), 1, &share_flag);
+      RRA("Couldn't set shared tag on shared entity.");
+
         // reset sharing proc(s) tags
       std::fill(sharing_procs.begin(), sharing_procs.end(), -1);
     }
@@ -2251,6 +2539,12 @@
     }
     RR("Failed setting shared_procs tag on skin vertices.");
 
+    unsigned char share_flag = PSTATUS_SHARED;
+    if ((int) procConfig.proc_rank() > sharing_procs[0]) 
+      share_flag |= PSTATUS_NOT_OWNED;
+    result = mbImpl->tag_set_data(pstatus_tag, &this_ent, 1, &share_flag);
+    RRA("Couldn't set shared tag on shared vertex.");
+
       // reset sharing proc(s) tags
     std::fill(sharing_procs.begin(), sharing_procs.end(), -1);
     std::fill(sharing_handles, sharing_handles+nump, 0);
@@ -2259,73 +2553,6 @@
   return MB_SUCCESS;
 }
   
-MBErrorCode MBParallelComm::get_shared_proc_tags(MBTag &sharedp_tag,
-                                                 MBTag &sharedps_tag,
-                                                 MBTag &sharedh_tag,
-                                                 MBTag &sharedhs_tag,
-                                                 MBTag &pstatus_tag) 
-{
-  int def_val = -1;
-  MBErrorCode result;
-  
-  if (!sharedpTag) {
-    result = mbImpl->tag_create(PARALLEL_SHARED_PROC_TAG_NAME, sizeof(int), 
-                                MB_TAG_DENSE,
-                                MB_TYPE_INTEGER, sharedpTag, &def_val, true);
-    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) {
-      RR("Couldn't create shared_proc tag.");
-    }
-  }
-  sharedp_tag = sharedpTag;
-  
-  if (!sharedpsTag) {
-    result = mbImpl->tag_create(PARALLEL_SHARED_PROCS_TAG_NAME, 
-                                MAX_SHARING_PROCS*sizeof(int), 
-                                MB_TAG_SPARSE,
-                                MB_TYPE_INTEGER, sharedpsTag, NULL, true);
-    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) {
-      RR("Couldn't create shared_procs tag.");
-    }
-  }
-  sharedps_tag = sharedpsTag;
-  
-  def_val = 0;
-  if (!sharedhTag) {
-    result = mbImpl->tag_create(PARALLEL_SHARED_HANDLE_TAG_NAME, 
-                                sizeof(MBEntityHandle), 
-                                MB_TAG_DENSE,
-                                MB_TYPE_INTEGER, sharedhTag, &def_val, true);
-    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) {
-      RR("Couldn't create shared_handle tag.");
-    }
-  }
-  sharedh_tag = sharedhTag;
-  
-  if (!sharedhsTag) {
-    result = mbImpl->tag_create(PARALLEL_SHARED_HANDLES_TAG_NAME, 
-                                MAX_SHARING_PROCS*sizeof(MBEntityHandle), 
-                                MB_TAG_SPARSE,
-                                MB_TYPE_INTEGER, sharedhsTag, NULL, true);
-    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) {
-      RR("Couldn't create shared_handles tag.");
-    }
-  }
-  sharedhs_tag = sharedhsTag;
-  
-  if (!pstatusTag) {
-    result = mbImpl->tag_create(PARALLEL_STATUS_TAG_NAME, 
-                                1,
-                                MB_TAG_SPARSE,
-                                MB_TYPE_OPAQUE, pstatusTag, NULL, true);
-    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) {
-      RR("Couldn't create shared_handles tag.");
-    }
-  }
-  pstatus_tag = pstatusTag;
-  
-  return MB_SUCCESS;
-}
-
 MBErrorCode MBParallelComm::get_shared_entities(int dim,
                                                 MBRange &shared_ents) 
 {
@@ -2404,19 +2631,377 @@
   return MB_SUCCESS;
 }
 
-MBErrorCode MBParallelComm::exchange_ghost_cells(int to_dim, int bridge_dim,
+MBErrorCode MBParallelComm::get_ghost_layers(MBEntityHandle iface_set,
+                                             int to_dim, int bridge_dim,
+                                             int num_layers,
+                                             MBRange &to_ents) 
+{
+  MBRange bridge_ents;
+  MBErrorCode result = mbImpl->get_entities_by_dimension(iface_set, bridge_dim, 
+                                                         bridge_ents,
+                                                         MBInterface::UNION);
+  RRA("Couldn't get bridge ents in the set.");
+
+  if (bridge_ents.empty()) return MB_SUCCESS;
+
+    // for each layer, get bridge-adj entities and accumulate
+  for (int nl = 0; nl < num_layers; nl++) {
+    MBRange new_ghosts, new_bridges;
+    result = mbImpl->get_adjacencies(bridge_ents, to_dim, false, new_ghosts,
+                                     MBInterface::UNION);
+    RRA("Trouble getting ghost adjacencies in iteration.");
+    to_ents.merge(new_ghosts);
+    result = mbImpl->get_adjacencies(new_ghosts, bridge_dim, false, new_bridges,
+                                     MBInterface::UNION);
+    if (nl < num_layers-1)
+      bridge_ents = new_bridges.subtract(bridge_ents);
+  }
+
+  return MB_SUCCESS;
+}
+
+MBErrorCode MBParallelComm::get_iface_sets_procs(MBRange &iface_sets,
+                                                 std::vector<int> &sharing_procs) 
+{
+  MBTag iface_tag = iface_sets_tag();
+  if (0 == iface_tag) return MB_FAILURE;
+
+  int tag_sz;
+  MBErrorCode result = mbImpl->tag_get_size(iface_tag, tag_sz);
+  RRA("Failed to get iface tag size.");
+  tag_sz /= sizeof(MBEntityHandle);
+  
+  std::vector<MBEntityHandle> iface_sets_vec(tag_sz);
+  result = mbImpl->tag_get_data(iface_tag, NULL, 0, &iface_sets_vec[0]);
+  RRA("Failed to find iface tag.");
+  
+  unsigned int i, j;
+  for (i = 0; i < iface_sets_vec.size(); i++) 
+    if (0 != iface_sets_vec[i]) iface_sets.insert(iface_sets_vec[i]);
+  
+  std::vector<int> iface_proc(iface_sets.size());
+  result = mbImpl->tag_get_data(sharedp_tag(), iface_sets, &iface_proc[0]);
+  RRA("Failed to get iface_proc for iface sets.");
+  
+  int iface_procs[MAX_SHARING_PROCS];
+  std::fill(iface_procs, iface_procs+MAX_SHARING_PROCS, -1);
+  MBRange::iterator rit;
+  for (rit = iface_sets.begin(), i = 0; rit != iface_sets.end(); rit++, i++) {
+    if (-1 != iface_proc[i]) iface_procs[0] = iface_proc[i];
+    else {
+        // get the sharing_procs tag
+      result = mbImpl->tag_get_data(sharedps_tag(), &(*rit), 1,
+                                    &iface_procs[0]);
+      RRA("Failed to get iface_procs for iface set.");
+    }
+    
+    for (j = 0; j < MAX_SHARING_PROCS; j++) {
+      if (-1 == iface_procs[j]) break;
+      
+      if (std::find(sharing_procs.begin(), sharing_procs.end(), iface_procs[j])
+          == sharing_procs.end()) 
+        sharing_procs.push_back(iface_proc[j]);
+    }
+    std::fill(iface_procs, iface_procs+MAX_SHARING_PROCS, -1);
+  }
+
+  return MB_SUCCESS;
+}
+
+bool MBParallelComm::is_iface_proc(MBEntityHandle this_set,
+                                   int to_proc) 
+{
+  int sharing_procs[MAX_SHARING_PROCS];
+  std::fill(sharing_procs, sharing_procs+MAX_SHARING_PROCS, -1);
+  MBErrorCode result = mbImpl->tag_get_data(sharedp_tag(), &this_set, 1,
+                                            sharing_procs);
+  if (to_proc == sharing_procs[0]) return true;
+  
+  result = mbImpl->tag_get_data(sharedps_tag(), &this_set, 1,
+                                sharing_procs);
+  for (int i = 0; i < MAX_SHARING_PROCS; i++) {
+    if (to_proc == sharing_procs[i]) return true;
+    else if (-1 == sharing_procs[i]) return false;
+  }
+  
+  return false;
+}
+
+MBErrorCode MBParallelComm::remove_nonowned_shared(MBRange &ents,
+                                                   int to_proc,
+                                                   bool owned_test) 
+{
+    // remove from ents any entities which are not owned locally or
+    // who are already shared with to_proc
+  std::vector<unsigned char> shared_flags(ents.size());
+  MBErrorCode result = mbImpl->tag_get_data(pstatus_tag(), ents,
+                                            &shared_flags[0]);
+  RRA("Failed to get pstatus flag.");
+  MBRange tmp_ents;
+  MBRange::iterator rit;
+  int sharing_procs[MAX_SHARING_PROCS];
+  std::fill(sharing_procs, sharing_procs+MAX_SHARING_PROCS, -1);
+  int i;
+  for (rit = ents.begin(), i = 0; rit != ents.end(); rit++, i++) {
+      // don't save if I don't own this entity
+    if (owned_test && (PSTATUS_NOT_OWNED & shared_flags[i])) continue;
+  
+      // if entity isn't shared yet, add to list
+    else if (!(PSTATUS_SHARED & shared_flags[i])) tmp_ents.insert(*rit);
+    
+      // else we need to check sharing procs
+    else {
+      result = mbImpl->tag_get_data(sharedp_tag(), &(*rit), 1,
+                                    sharing_procs);
+      RRA(" ");
+      if (-1 == sharing_procs[0]) {
+        result = mbImpl->tag_get_data(sharedps_tag(), &(*rit), 1,
+                                      sharing_procs);
+        assert(-1 != sharing_procs[0]);
+        RRA(" ");
+      }
+      for (unsigned int j = 0; j < MAX_SHARING_PROCS; j++) {
+          // if to_proc shares this entity, skip it
+        if (sharing_procs[j] == to_proc) break;
+          // if we get here, no more sharing procs, and it's not shared
+          // with to_proc, so add to list
+        else if (sharing_procs[j] == -1) 
+          tmp_ents.insert(*rit);
+      }
+      std::fill(sharing_procs, sharing_procs+MAX_SHARING_PROCS, -1);
+    }
+  }
+    
+  ents.swap(tmp_ents);
+  
+  return MB_SUCCESS;
+}
+
+MBErrorCode MBParallelComm::exchange_ghost_cells(int ghost_dim, int bridge_dim,
                                                  int num_layers,
-                                                 int with_proc) 
+                                                 bool store_remote_handles,
+                                                 bool wait_all) 
 {
     // get the b-dimensional interface(s) with with_proc, where b = bridge_dim
+  MBErrorCode result;
+  int success;
 
-    // for each layer, get non-ghost bridge entities and accumulate
+  if (bridge_dim != 0) {
+    result = MB_NOT_IMPLEMENTED;
+    RRA("Exchanging ghost cells only works with bridge_dim = 0 for now.");
+  }
 
-    // send those entities, then receive entities from that proc
-  return MB_FAILURE;
+    // get all procs interfacing to this proc
+  MBRange iface_sets;
+  std::vector<int> iface_procs;
+  result = get_iface_sets_procs(iface_sets, iface_procs);
+  RRA("Failed to get iface sets, procs");
+
+    // post ghost irecv's for all interface procs
+    // index greqs the same as buffer/sharing procs indices
+  std::vector<MPI_Request> recv_reqs(2*MAX_SHARING_PROCS, MPI_REQUEST_NULL);
+  std::vector<MPI_Status> gstatus(MAX_SHARING_PROCS);
+  std::vector<int>::iterator vit;
+  for (vit = iface_procs.begin(); vit != iface_procs.end(); vit++) {
+    int ind = get_buffers(*vit);
+    success = MPI_Irecv(&ghostRBuffs[ind][0], ghostRBuffs[ind].size(), 
+                        MPI_UNSIGNED_CHAR, *vit,
+                        MB_MESG_ANY, procConfig.proc_comm(), 
+                        &recv_reqs[ind]);
+    if (success != MPI_SUCCESS) {
+      result = MB_FAILURE;
+      RRA("Failed to post irecv in ghost exchange.");
+    }
+  }
+  
+    // pack and send ghosts from this proc to others
+    // make sendReqs vector to simplify initialization
+  std::fill(sendReqs, sendReqs+2*MAX_SHARING_PROCS, MPI_REQUEST_NULL);
+  MBRange sent_ents[MAX_SHARING_PROCS], recd_ents[MAX_SHARING_PROCS];
+  for (vit = iface_procs.begin(); vit != iface_procs.end(); vit++) {
+    int ind = get_buffers(*vit);
+    
+    MBRange bridge_ents;
+
+      // get bridge ents on interface(s)
+    for (MBRange::iterator rit = iface_sets.begin(); rit != iface_sets.end();
+         rit++) {
+      if (!is_iface_proc(*rit, *vit)) continue;
+      
+      result = get_ghost_layers(*rit, ghost_dim, bridge_dim, num_layers,
+                                bridge_ents);
+      RRA("Failed to get ghost layers.");
+    }
+
+      // pack-send; this also posts receives if store_remote_handles is true
+    result = pack_send_entities(*vit, bridge_ents, false, true, store_remote_handles,
+                                ownerSBuffs[ind], ownerRBuffs[MAX_SHARING_PROCS+ind], 
+                                sendReqs[ind], recv_reqs[MAX_SHARING_PROCS+ind], 
+                                sent_ents[ind]);
+    RRA("Failed to pack-send in ghost exchange.");
+  }
+  
+    // receive/unpack entities
+    // number of incoming messages depends on whether we're getting back
+    // remote handles
+  int num_incoming = iface_sets.size() * (store_remote_handles ? 2 : 1);
+  
+  while (num_incoming) {
+    int ind;
+    MPI_Status status;
+    success = MPI_Waitany(2*MAX_SHARING_PROCS, &recv_reqs[0], &ind, &status);
+    if (MPI_SUCCESS != success) {
+      result = MB_FAILURE;
+      RRA("Failed in waitany in ghost exchange.");
+    }
+    
+      // ok, received something; decrement incoming counter
+    num_incoming--;
+    
+    MBRange remote_range;
+    int new_size;
+    unsigned char *buff_ptr;
+    
+      // branch on message type
+    switch (status.MPI_TAG) {
+      case MB_MESG_SIZE:
+          // incoming message just has size; resize buffer and re-call recv,
+          // then re-increment incoming count
+        assert(ind < MAX_SHARING_PROCS);
+        new_size = *((int*)&ghostRBuffs[ind][0]);
+        assert(0 > new_size);
+        result = recv_size_buff(*vit, ghostRBuffs[ind], recv_reqs[ind]);
+        RRA("Failed to resize recv buffer.");
+        num_incoming++;
+        break;
+      case MB_MESG_ENTS:
+          // incoming ghost entities; process
+        result = recv_unpack_entities(buffProcs[ind], store_remote_handles,
+                                      ghostRBuffs[ind], ghostSBuffs[ind], 
+                                      sendReqs[ind], recd_ents[ind]);
+        RRA("Failed to recv-unpack message.");
+        break;
+      case MB_MESG_REMOTE_HANDLES:
+          // incoming remote handles; use to set remote handles
+        buff_ptr = &ownerRBuffs[ind][0];
+        assert(ind >= MAX_SHARING_PROCS);
+        UNPACK_RANGE(buff_ptr, remote_range);
+        result = set_remote_data(sent_ents[ind-MAX_SHARING_PROCS], remote_range, *vit);
+        RRA("Trouble setting remote data range on sent entities in ghost exchange.");
+        break;
+    }
+  }
+  
+    // ok, now wait if requested
+  if (wait_all) {
+    MPI_Status status[2*MAX_SHARING_PROCS];
+    success = MPI_Waitall(2*MAX_SHARING_PROCS, &sendReqs[0], status);
+    if (MPI_SUCCESS != success) {
+      result = MB_FAILURE;
+      RRA("Failure in waitall in ghost exchange.");
+    }
+  }
+  
+  return MB_SUCCESS;
 }
 
+  //! return sharedp tag
+MBTag MBParallelComm::sharedp_tag()
+{
+  if (!sharedpTag) {
+    int def_val = -1;
+    MBErrorCode result = mbImpl->tag_create(PARALLEL_SHARED_PROC_TAG_NAME, 
+                                            sizeof(int), 
+                                            MB_TAG_DENSE,
+                                            MB_TYPE_INTEGER, sharedpTag, 
+                                            &def_val, true);
+    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) 
+      return 0;
+  }
+  
+  return sharedpTag;
+}
 
+  //! return sharedps tag
+MBTag MBParallelComm::sharedps_tag()
+{
+  if (!sharedpsTag) {
+    MBErrorCode result = mbImpl->tag_create(PARALLEL_SHARED_PROCS_TAG_NAME, 
+                                            MAX_SHARING_PROCS*sizeof(int), 
+                                            MB_TAG_SPARSE,
+                                            MB_TYPE_INTEGER, sharedpsTag, NULL, true);
+    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) 
+      return 0;
+  }
+  
+  return sharedpsTag;
+}
+  
+  //! return sharedh tag
+MBTag MBParallelComm::sharedh_tag()
+{
+  if (!sharedhTag) {
+    int def_val = 0;
+    MBErrorCode result = mbImpl->tag_create(PARALLEL_SHARED_HANDLE_TAG_NAME, 
+                                            sizeof(MBEntityHandle), 
+                                            MB_TAG_DENSE,
+                                            MB_TYPE_INTEGER, sharedhTag, 
+                                            &def_val, true);
+    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result)
+      return 0;
+  }
+  
+  return sharedhTag;
+}
+  
+  //! return sharedhs tag
+MBTag MBParallelComm::sharedhs_tag()
+{  
+  if (!sharedhsTag) {
+    MBErrorCode result = mbImpl->tag_create(PARALLEL_SHARED_HANDLES_TAG_NAME, 
+                                            MAX_SHARING_PROCS*sizeof(MBEntityHandle), 
+                                            MB_TAG_SPARSE,
+                                            MB_TYPE_INTEGER, sharedhsTag, NULL, true);
+    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) 
+      return 0;
+  }
+
+  return sharedhsTag;
+}
+  
+  //! return pstatus tag
+MBTag MBParallelComm::pstatus_tag()
+{  
+  if (!pstatusTag) {
+    unsigned char tmp_pstatus = 0;
+    MBErrorCode result = mbImpl->tag_create(PARALLEL_STATUS_TAG_NAME, 
+                                            sizeof(unsigned char),
+                                            MB_TAG_DENSE,
+                                            MB_TYPE_OPAQUE, pstatusTag, 
+                                            &tmp_pstatus, true);
+    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result)
+      return 0;
+  }
+  
+  return pstatusTag;
+}
+  
+  //! return iface set tag
+MBTag MBParallelComm::iface_sets_tag()
+{  
+  if (!ifaceSetsTag) {
+    MBErrorCode result = mbImpl->tag_create(PARALLEL_IFACE_SETS_TAG_NAME, 
+                                            MAX_SHARING_PROCS*sizeof(MBEntityHandle),
+                                            MB_TAG_SPARSE,
+                                            MB_TYPE_HANDLE, ifaceSetsTag, 
+                                            NULL, true);
+    if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result)
+      return 0;
+  }
+  
+  return ifaceSetsTag;
+}
+  
 #ifdef TEST_PARALLELCOMM
 
 #include <iostream>

Modified: MOAB/trunk/parallel/MBParallelComm.hpp
===================================================================
--- MOAB/trunk/parallel/MBParallelComm.hpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/parallel/MBParallelComm.hpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -74,26 +74,87 @@
                                const bool parallel = true);
   
 
-    //! communicate entities from/to this range
-  MBErrorCode communicate_entities(const int from_proc, const int to_proc,
-                                   MBRange &entities,
-                                   const bool adjacencies = false,
-                                   const bool tags = true,
-                                   const bool store_remote_handles = true);
+    /** \brief send entities to another processor, optionally waiting until it's done
+     *
+     * Send entities to another processor, with adjs, sets, and tags.  
+     * If store_remote_handles is true, this call receives back handles assigned to
+     * entities sent to destination processor and stores them in sharedh_tag or 
+     * sharedhs_tag.
+     * \param to_proc Destination processor
+     * \param orig_ents Entities requested to send
+     * \param adjs If true, send adjacencies for equiv entities (currently unsupported)
+     * \param tags If true, send tag values for all tags assigned to entities
+     * \param store_remote_handles If true, also recv message with handles on destination processor
+     * \param final_ents Range containing all entities sent
+     * \param wait_all If true, wait until all messages received/sent complete
+     */
+  MBErrorCode send_entities(const int to_proc,
+                            MBRange &orig_ents,
+                            const bool adjs,
+                            const bool tags,
+                            const bool store_remote_handles,
+                            MBRange &final_ents,
+                            bool wait_all = true);
   
-  MBErrorCode broadcast_entities( const int from_proc,
-                                  MBRange& entities,
-                                  const bool adjacencies = false,
-                                  const bool tags = true );
+    /** \brief Receive entities from another processor, optionally waiting until it's done
+     *
+     * Receive entities from another processor, with adjs, sets, and tags.  
+     * If store_remote_handles is true, this call sends back handles assigned to
+     * the entities received.
+     * \param from_proc Source processor
+     * \param store_remote_handles If true, send message with new entity handles to source processor
+     * \param final_ents Range containing all entities received
+     * \param wait_all If true, wait until all messages received/sent complete
+     */
+  MBErrorCode recv_entities(const int from_proc,
+                            const bool store_remote_handles,
+                            MBRange &final_ents,
+                            bool wait_all = true);
+  
+    /** \brief Exchange ghost cells with neighboring procs
+     * Neighboring processors are those sharing an interface 
+     * with this processor.  All entities of dimension ghost_dim
+     * within num_layers of interface, measured going through bridge_dim,
+     * are exchanged.  See MeshTopoUtil::get_bridge_adjacencies for description
+     * of bridge adjacencies.  If wait_all is false and store_remote_handles
+     * is true, MPI_Request objects are available in the sendReqs[2*MAX_SHARING_PROCS] 
+     * member array, with inactive requests marked as MPI_REQUEST_NULL.  If
+     * store_remote_handles or wait_all is false, this function returns after 
+     * all entities have been received and processed.
+     * \param ghost_dim Dimension of ghost entities to be exchanged
+     * \param bridge_dim Dimension of entities used to measure layers from interface
+     * \param num_layers Number of layers of ghosts requested
+     * \param store_remote_handles If true, send message with new entity handles to source processor
+     * \param wait_all If true, function does not return until all send buffers
+     *       are cleared.
+     */
+  MBErrorCode exchange_ghost_cells(int ghost_dim, int bridge_dim, 
+                                   int num_layers,
+                                   bool store_remote_handles,
+                                   bool wait_all = true);
 
-    /** Resolve shared entities between processors
+    /** \brief Broadcast all entities resident on from_proc to other processors
+     * This function assumes remote handles are *not* being stored, since (usually)
+     * every processor will know about the whole mesh.
+     * \param from_proc Processor having the mesh to be broadcast
+     * \param entities On return, the entities sent or received in this call
+     * \param adjacencies If true, adjacencies are sent for equiv entities (currently unsupported)
+     * \param tags If true, all non-default-valued tags are sent for sent entities
+     */
+  MBErrorCode broadcast_entities(const int from_proc,
+                                 MBRange& entities,
+                                 const bool adjacencies = false,
+                                 const bool tags = true );
+
+    /** \brief Resolve shared entities between processors
+     *
      * Resolve shared entities between processors for entities in proc_ents,
      * by comparing global id tag values on vertices on skin of elements in
      * proc_ents.  Shared entities are assigned a tag that's either
-     * PARALLEL_SHARED_PROC_TAG_NAME, which is 2 integers in length, or 
+     * PARALLEL_SHARED_PROC_TAG_NAME, which is 1 integer in length, or 
      * PARALLEL_SHARED_PROCS_TAG_NAME, whose length depends on the maximum
      * number of sharing processors.  Values in these tags denote the ranks
-     * of sharing processors, and the list ends with the value -10*#procs.
+     * of sharing processors, and the list ends with the value -1.
      *
      * If shared_dim is input as -1 or not input, a value one less than the
      * maximum dimension of entities in proc_ents is used.
@@ -102,25 +163,24 @@
      * \param shared_dim Maximum dimension of shared entities to look for
      */
   MBErrorCode resolve_shared_ents(MBRange &proc_ents, 
-                                  int shared_dim = 0);
+                                  int shared_dim = -1);
   
-    /** Resolve shared entities between processors
+    /** \brief Resolve shared entities between processors
+     *
      * Same as resolve_shared_ents(MBRange&), except works for
      * all entities in instance of dimension dim.  
      *
-     * If dim = -1 or no dim input, uses entities of maximal
-     * dimension (3) in the instance.
-     *
      * If shared_dim is input as -1 or not input, a value one less than the
      * maximum dimension of entities is used.
 
-     * \param dim Maximal dimension of entities to be resolved
+     * \param dim Dimension of entities in the partition
      * \param shared_dim Maximum dimension of shared entities to look for
      */
-  MBErrorCode resolve_shared_ents(int dim = -1, 
-                                  int shared_dim = 0);
+  MBErrorCode resolve_shared_ents(int dim = 3, 
+                                  int shared_dim = -1);
   
-    /** Get entities shared with other processors, based on 
+    /** \brief Get entities shared with other processors, based on 
+     *
      * PARALLEL_SHARED_PROC_TAG_NAME and PARALLEL_SHARED_PROCS_TAG_NAME.
      *
      * \param dim Dimension of entities shared with other processors
@@ -129,27 +189,23 @@
   MBErrorCode get_shared_entities(int dim,
                                   MBRange &shared_ents);
 
-    //! pack a buffer (stored in this class instance) with ALL data for these entities
-  MBErrorCode pack_buffer(MBRange &entities, 
+    //! pack the buffer with ALL data for orig_ents; return entities actually
+    //! packed (including reference sub-entities) in final_ents
+  MBErrorCode pack_buffer(MBRange &orig_ents,
                           const bool adjacencies,
                           const bool tags,
-                          const bool just_count,
                           const bool store_remote_handles,
                           const int to_proc,
-                          MBRange &whole_range,
+                          MBRange &final_ents,
+                          std::vector<unsigned char> &buff,
                           int &buff_size);
   
     //! unpack a buffer; assume information is already in myBuffer
-  MBErrorCode unpack_buffer(MBRange &entities, 
-                            const bool store_remote_handles,
-                            int from_proc);
+  MBErrorCode unpack_buffer(unsigned char *buff_ptr,
+                            const bool store_remote_handles, 
+                            int from_proc,
+                            MBRange &entities);
 
-    //! set the buffer size; return true if size actually changed
-  bool buffer_size(const unsigned int new_size);
-
-    //! take the buffer from this instance; switches with vector passed in
-  void take_buffer(std::vector<unsigned char> &new_buff);
-
     //! Get proc config for this communication object
   const MBProcConfig &proc_config() const {return procConfig;}
   
@@ -175,62 +231,50 @@
     //! return pstatus tag
   MBTag pstatus_tag();
   
-    //! replace handles in from_vec with corresponding handles on
-    //! to_proc (by checking shared[p/h]_tag and shared[p/h]s_tag;
-    //! if no remote handle and new_ents is non-null, substitute
-    //! instead CREATE_HANDLE(MBMAXTYPE, index) where index is handle's
-    //! position in new_ents
-  MBErrorCode get_remote_handles(const bool store_remote_handles,
-                                 MBEntityHandle *from_vec, 
-                                 MBEntityHandle *to_vec_tmp,
-                                 int num_ents, int to_proc,
-                                 const MBRange &new_ents);
+    //! return iface_set tag
+  MBTag iface_sets_tag();
   
-    //! same as other version, except from_range and to_range should be
-    //! different here
-  MBErrorCode get_remote_handles(const bool store_remote_handles,
-                                 const MBRange &from_range, 
-                                 MBRange &to_range,
-                                 int to_proc,
-                                 const MBRange &new_ents);
-  
-    //! same as other version, except packs range into vector
-  MBErrorCode get_remote_handles(const bool store_remote_handles,
-                                 const MBRange &from_range, 
-                                 MBEntityHandle *to_vec,
-                                 int to_proc,
-                                 const MBRange &new_ents);
-  
-    //! goes through from_vec, and for any with type MBMAXTYPE, replaces with
-    //! new_ents value at index corresponding to id of entity in from_vec
-  MBErrorCode get_local_handles(MBEntityHandle *from_vec, 
-                                int num_ents,
-                                const MBRange &new_ents);
+private:
 
-    //! same as above except puts results in range
-  MBErrorCode get_local_handles(const MBRange &remote_handles,
-                                MBRange &local_handles,
-                                const MBRange &new_ents);
+  int num_subranges(const MBRange &this_range);
+
+    //! get (and possibly allocate) buffers for messages to/from to_proc; returns
+    //! index of to_proc in buffProcs vector
+  int get_buffers(int to_proc);
+
+    //! pack entities (with adjs, tags too) and send to to_proc; also post a recv
+    //! if store_remote_handles is true; pass back MPI_Request objects for these
+    //! messages, along with entities actually sent; this function calls:
+    //! - MPI_Irecv if store_remote_handles is true (posts recv for remote handles)
+    //! - MPI_Send if send buffer is larger than INITIAL_BUFF_SIZE
+    //! - MPI_Isend for sending entities
+  MBErrorCode pack_send_entities(const int to_proc,
+                                 MBRange &orig_ents,
+                                 const bool adjacencies,
+                                 const bool tags,
+                                 const bool store_remote_handles,
+                                 std::vector<unsigned char> &send_buff,
+                                 std::vector<unsigned char> &recv_buff,
+                                 MPI_Request &send_req,
+                                 MPI_Request &recv_req,
+                                 MBRange &final_ents);
   
-    //! adjust shared proc tags/handles to incude from_proc and remote_range
-  MBErrorCode set_remote_data(MBRange &local_range,
-                              MBRange &remote_range,
-                              int from_proc);
+    //! use integer size in buffer to resize buffer, then post an
+    //! Irecv to get message
+  MBErrorCode recv_size_buff(const int from_proc,
+                             std::vector<unsigned char> &recv_buff,
+                             MPI_Request &recv_req);
   
-    //! adjust shared proc tags/handles to incude from_proc and remote_range
-  MBErrorCode set_remote_data(MBEntityHandle *local_ents,
-                              MBEntityHandle *remote_ents,
-                              int num_ents,
-                              int other_proc);
+    //! process contents of receive buffer to get new entities; if store_remote_handles
+    //! is true, also Isend (using send_buff) handles for these entities back to 
+    //! source proc, returning request handle in &send_req
+  MBErrorCode recv_unpack_entities(const int from_proc,
+                                   const bool store_remote_handles,
+                                   std::vector<unsigned char> &recv_buff,
+                                   std::vector<unsigned char> &send_buff,
+                                   MPI_Request &send_req,
+                                   MBRange &recd_ents);
   
-    //! exchange ghost cells with with_proc, going through bridge_dim to to_dim
-  MBErrorCode exchange_ghost_cells(int to_dim, int bridge_dim, 
-                                   int num_layers, int to_proc);
-  
-private:
-
-  int num_subranges(const MBRange &this_range);
-  
   MBErrorCode pack_entities(MBRange &entities,
                             MBRange::const_iterator &start_rit,
                             MBRange &whole_range,
@@ -238,7 +282,10 @@
                             int &count,
                             const bool just_count,
                             const bool store_remote_handles,
-                            const int from_proc);
+                            const int to_proc,
+                            std::vector<MBEntityType> &ent_types, 
+                            std::vector<MBRange> &all_ranges, 
+                            std::vector<int> &verts_per_entity);
   
   MBErrorCode unpack_entities(unsigned char *&buff_ptr,
                               MBRange &entities,
@@ -252,7 +299,11 @@
                         int &count,
                         const bool just_count,
                         const bool store_handles,
-                        const int to_proc);
+                        const int to_proc,
+                        MBRange &set_range,
+                        std::vector<MBRange> &set_ranges,
+                        std::vector<int> &set_sizes,
+                        std::vector<unsigned int> &options_vec);
   
   MBErrorCode unpack_sets(unsigned char *&buff_ptr,
                           MBRange &entities,
@@ -280,7 +331,9 @@
                         int &count,
                         const bool just_count,
                         const bool store_handles,
-                        const int to_proc);
+                        const int to_proc,
+                        std::vector<MBTag> &all_tags,
+                        std::vector<MBRange> &tag_ranges);
 
   MBErrorCode unpack_tags(unsigned char *&buff_ptr,
                           MBRange &entities,
@@ -297,7 +350,7 @@
                               std::map<std::vector<int>, MBRange> &proc_nranges);
 
   MBErrorCode create_interface_sets(std::map<std::vector<int>, MBRange> &proc_nranges,
-                                    MBRange &iface_sets);
+                                    MBRange *iface_sets_ptr = NULL);
 
     //! resolve remote handles for shared non-vertex ents, assuming
     //! this has already been done for vertices
@@ -307,7 +360,75 @@
     //! of handles starting at actual_start
   MBErrorCode pack_range_map(MBRange &this_range, MBEntityHandle actual_start,
                              HandleMap &handle_map);
+
+    //! remove from the range all ents not owned by this proc or already
+    //! shared with to_proc
+  MBErrorCode remove_nonowned_shared(MBRange &ents,
+                                     int to_proc,
+                                     bool owned_test = true);
   
+    //! for a given interface set, gets a number of layers of bridge entities
+    //! of dimension to_dim going through bridge dimension bridge_dim
+  MBErrorCode get_ghost_layers(MBEntityHandle iface_set,
+                               int to_dim, int bridge_dim,
+                               int num_layers,
+                               MBRange &to_ents);
+  
+    //! returns true if the set is an interface shared with to_proc
+  bool is_iface_proc(MBEntityHandle this_set, int to_proc);
+  
+    //! replace handles in from_vec with corresponding handles on
+    //! to_proc (by checking shared[p/h]_tag and shared[p/h]s_tag;
+    //! if no remote handle and new_ents is non-null, substitute
+    //! instead CREATE_HANDLE(MBMAXTYPE, index) where index is handle's
+    //! position in new_ents
+  MBErrorCode get_remote_handles(const bool store_remote_handles,
+                                 MBEntityHandle *from_vec, 
+                                 MBEntityHandle *to_vec_tmp,
+                                 int num_ents, int to_proc,
+                                 const MBRange &new_ents);
+  
+    //! same as other version, except from_range and to_range should be
+    //! different here
+  MBErrorCode get_remote_handles(const bool store_remote_handles,
+                                 const MBRange &from_range, 
+                                 MBRange &to_range,
+                                 int to_proc,
+                                 const MBRange &new_ents);
+  
+    //! same as other version, except packs range into vector
+  MBErrorCode get_remote_handles(const bool store_remote_handles,
+                                 const MBRange &from_range, 
+                                 MBEntityHandle *to_vec,
+                                 int to_proc,
+                                 const MBRange &new_ents);
+  
+    //! goes through from_vec, and for any with type MBMAXTYPE, replaces with
+    //! new_ents value at index corresponding to id of entity in from_vec
+  MBErrorCode get_local_handles(MBEntityHandle *from_vec, 
+                                int num_ents,
+                                const MBRange &new_ents);
+
+    //! same as above except puts results in range
+  MBErrorCode get_local_handles(const MBRange &remote_handles,
+                                MBRange &local_handles,
+                                const MBRange &new_ents);
+  
+    //! adjust shared proc tags/handles to incude from_proc and remote_range
+  MBErrorCode set_remote_data(MBRange &local_range,
+                              MBRange &remote_range,
+                              int from_proc);
+  
+    //! adjust shared proc tags/handles to incude from_proc and remote_range
+  MBErrorCode set_remote_data(MBEntityHandle *local_ents,
+                              MBEntityHandle *remote_ents,
+                              int num_ents,
+                              int other_proc);
+  
+    //! returns the interface sets and union of sharing procs
+  MBErrorCode get_iface_sets_procs(MBRange &iface_sets,
+                                   std::vector<int> &sharing_procs);
+  
     //! MB interface associated with this writer
   MBInterface *mbImpl;
 
@@ -323,38 +444,19 @@
     //! data buffer used to communicate
   std::vector<unsigned char> myBuffer;
 
-    //! types of ranges to be communicated
-  std::vector<MBEntityType> entTypes;
+    //! more data buffers, proc-specific
+  std::vector<unsigned char> ownerRBuffs[MAX_SHARING_PROCS],
+    ownerSBuffs[MAX_SHARING_PROCS], ghostRBuffs[MAX_SHARING_PROCS],
+    ghostSBuffs[MAX_SHARING_PROCS];
 
-    //! ranges to be communicated
-  std::vector<MBRange> allRanges;
-  
-    //! vertices per entity in ranges
-  std::vector<int> vertsPerEntity;
+    //! request objects, may be used if store_remote_handles is used
+  MPI_Request sendReqs[2*MAX_SHARING_PROCS];
 
-    //! sets to be communicated
-  MBRange setRange;
+  std::vector<int> buffProcs;
   
-    //! ranges from sets to be communicated
-  std::vector<MBRange> setRanges;
-  
-    //! sizes of vector-based sets to be communicated
-  std::vector<int> setSizes;
-
-    //! tags to be communicated
-  std::vector<MBTag> allTags;
-
-    //! ranges from sparse tags to be communicated
-  std::vector<MBRange> tagRanges;
-
-    //! vector of set options for transferred sets
-  std::vector<unsigned int> optionsVec;
-  
-    //! numbers of parents/children for transferred sets
-  std::vector<int> setPcs;
-
     //! tags used to save sharing procs and handles
-  MBTag sharedpTag, sharedpsTag, sharedhTag, sharedhsTag, pstatusTag;
+  MBTag sharedpTag, sharedpsTag, sharedhTag, sharedhsTag, pstatusTag, 
+    ifaceSetsTag;
 
     //! interface sets, one set per unique combination of procs
   MBRange ifaceSets;
@@ -367,24 +469,19 @@
   
 };
 
-  //! return sharedp tag
-inline MBTag MBParallelComm::sharedp_tag()
-{return sharedpTag;}
+inline MBErrorCode MBParallelComm::get_shared_proc_tags(MBTag &sharedp,
+                                                        MBTag &sharedps,
+                                                        MBTag &sharedh,
+                                                        MBTag &sharedhs,
+                                                        MBTag &pstatus) 
+{
+  sharedp = sharedp_tag();
+  sharedps = sharedps_tag();
+  sharedh = sharedh_tag();
+  sharedhs = sharedhs_tag();
+  pstatus = pstatus_tag();
   
-  //! return sharedps tag
-inline MBTag MBParallelComm::sharedps_tag()
-{return sharedpsTag;}
-  
-  //! return sharedh tag
-inline MBTag MBParallelComm::sharedh_tag()
-{return sharedhTag;}
-  
-  //! return sharedhs tag
-inline MBTag MBParallelComm::sharedhs_tag()
-{return sharedhsTag;}
-  
-  //! return pstatus tag
-inline MBTag MBParallelComm::pstatus_tag()
-{return pstatusTag;}
-  
+  return MB_SUCCESS;
+}
+
 #endif

Modified: MOAB/trunk/parallel/ReadParallel.cpp
===================================================================
--- MOAB/trunk/parallel/ReadParallel.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/parallel/ReadParallel.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -11,21 +11,26 @@
 
 #include <iostream>
 #include <sstream>
+#include <algorithm>
 
-const bool debug = false;
+const bool debug = true;
 
 #define RR(a) if (MB_SUCCESS != result) {\
           dynamic_cast<MBCore*>(mbImpl)->get_error_handler()->set_last_error(a);\
           return result;}
 
 enum ParallelActions {PA_READ=0, PA_BROADCAST, PA_DELETE_NONLOCAL,
-                      PA_CHECK_GIDS_SERIAL, PA_GET_FILESET_ENTS};
+                      PA_CHECK_GIDS_SERIAL, PA_GET_FILESET_ENTS, 
+                      PA_RESOLVE_SHARED_ENTS,
+                      PA_EXCHANGE_GHOSTS};
 const char *ParallelActionsNames[] = {
   "PARALLEL READ",
   "PARALLEL BROADCAST", 
   "PARALLEL DELETE NONLOCAL",
   "PARALLEL CHECK_GIDS_SERIAL",
-  "PARALLEL GET_FILESET_ENTS"
+  "PARALLEL GET_FILESET_ENTS",
+  "PARALLEL RESOLVE_SHARED_ENTS",
+  "PARALLEL EXCHANGE_GHOSTS"
 };
 
 MBErrorCode ReadParallel::load_file(const char *file_name,
@@ -73,6 +78,41 @@
   result = opts.get_null_option("CPUTIME");
   if (MB_SUCCESS == result) cputime = true;
 
+    // get ghosting options
+  std::string ghost_str;
+  int bridge_dim, ghost_dim = -1, num_layers;
+  result = opts.get_str_option("PARALLEL_GHOSTS", ghost_str);
+  if (MB_TYPE_OUT_OF_RANGE == result) {
+    ghost_dim = 3;
+    bridge_dim = 0;
+    num_layers = 1;
+  }
+  else if (MB_SUCCESS == result) {
+    int num_fields = 
+      sscanf(ghost_str.c_str(), "%d.%d.%d", &ghost_dim, &bridge_dim, &num_layers);
+    if (3 != num_fields) {
+      merror->set_last_error( "Didn't read 3 fields from PARALLEL_GHOSTS string\n" );
+      return MB_FAILURE;
+    }
+  }
+
+    // get resolve_shared_ents option
+  std::string shared_str;
+  int resolve_dim = 3, shared_dim = -1;
+  result = opts.get_str_option("PARALLEL_RESOLVE_SHARED_ENTS", shared_str);
+  if (MB_TYPE_OUT_OF_RANGE == result) {
+    resolve_dim = 3;
+    shared_dim = -1;
+  }
+  else if (MB_SUCCESS == result) {
+    int num_fields = 
+      sscanf(ghost_str.c_str(), "%d.%d", &resolve_dim, &shared_dim);
+    if (2 != num_fields) {
+      merror->set_last_error( "Didn't read 2 fields from PARALLEL_RESOLVE_SHARED_ENTS string\n" );
+      return MB_FAILURE;
+    }
+  }
+
     // get MPI IO processor rank
   int reader_rank;
   result = opts.get_int_option( "MPI_IO_RANK", reader_rank );
@@ -127,10 +167,17 @@
     default:
       return MB_FAILURE;
   }
+
+  if (-1 != resolve_dim) pa_vec.push_back(PA_RESOLVE_SHARED_ENTS);
+
+  if (-1 != ghost_dim) pa_vec.push_back(PA_EXCHANGE_GHOSTS);
   
+  
   return load_file(file_name, file_set, parallel_mode, partition_tag_name,
                    partition_tag_vals, distrib, pa_vec, material_set_list,
-                   num_material_sets, opts, reader_rank, cputime);
+                   num_material_sets, opts, reader_rank, cputime, 
+                   resolve_dim, shared_dim,
+                   ghost_dim, bridge_dim, num_layers);
 }
     
 MBErrorCode ReadParallel::load_file(const char *file_name,
@@ -143,8 +190,13 @@
                                     const int* material_set_list,
                                     const int num_material_sets,
                                     const FileOptions &opts,
-                                    int reader_rank,
-                                    bool cputime) 
+                                    const int reader_rank,
+                                    const bool cputime,
+                                    const int resolve_dim,
+                                    const int shared_dim,
+                                    const int ghost_dim,
+                                    const int bridge_dim,
+                                    const int num_layers) 
 {
   MBErrorCode result = MB_SUCCESS;
   MBParallelComm pcom( mbImpl);
@@ -288,6 +340,23 @@
         break;
         
 //==================
+      case PA_RESOLVE_SHARED_ENTS:
+        if (debug)
+          std::cout << "Resolving shared entities." << std::endl;
+
+        tmp_result = pcom.resolve_shared_ents(resolve_dim, shared_dim);
+        break;
+        
+//==================
+      case PA_EXCHANGE_GHOSTS:
+        if (debug)
+          std::cout << "Exchanging ghost entities." << std::endl;
+
+        tmp_result = pcom.exchange_ghost_cells(ghost_dim, bridge_dim, 
+                                               num_layers, true);
+        break;
+        
+//==================
       default:
         return MB_FAILURE;
     }
@@ -468,7 +537,17 @@
   if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) {
     RR("Couldn't create/get partition set tag.");
   }
-  std::vector<int> pset_vals(partition_sets.size());
+
+  std::vector<int> pset_vals(partition_sets.size(), -1);
+  if (MB_ALREADY_ALLOCATED == result) {
+      // if all partition sets already marked, don't need to mark again
+    result = mbImpl->tag_get_data(partition_set_tag, partition_sets,
+                                  &pset_vals[0]);
+    if (MB_SUCCESS == result &&
+        std::find(pset_vals.begin(), pset_vals.end(), -1) ==
+        pset_vals.end()) return MB_SUCCESS;
+  }
+    
   std::fill(pset_vals.begin(), pset_vals.end(), mbImpl->proc_rank());
   result = mbImpl->tag_set_data(partition_set_tag, partition_sets, 
                                 &pset_vals[0]);

Modified: MOAB/trunk/parallel/ReadParallel.hpp
===================================================================
--- MOAB/trunk/parallel/ReadParallel.hpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/parallel/ReadParallel.hpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -43,8 +43,13 @@
                         const int* material_set_list,
                         const int num_material_sets,
                         const FileOptions &opts,
-                        int reader_rank,
-                        bool cputime);
+                        const int reader_rank,
+                        const bool cputime,
+                        const int resolve_dim,
+                        const int shared_dim,
+                        const int ghost_dim,
+                        const int bridge_dim,
+                        const int num_layers);
 
   MBErrorCode delete_nonlocal_entities(std::string &ptag_name,
                                        std::vector<int> &ptag_vals,

Modified: MOAB/trunk/parallel/WriteHDF5Parallel.cpp
===================================================================
--- MOAB/trunk/parallel/WriteHDF5Parallel.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/parallel/WriteHDF5Parallel.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -1765,9 +1765,6 @@
 MBErrorCode WriteHDF5Parallel::fix_remote_set_ids( RemoteSetData& data, long first_id )
 {
   const id_t id_diff = (id_t)(first_id - 1);
-  id_t file_id;
-  MBErrorCode rval;
-  
   MBRange::const_iterator i;
   std::vector<id_t> ids(data.range.size());
   std::vector<id_t>::iterator j = ids.begin();

Modified: MOAB/trunk/parallel/pcomm_unit.cpp
===================================================================
--- MOAB/trunk/parallel/pcomm_unit.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/parallel/pcomm_unit.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -70,27 +70,19 @@
   MBRange tmp_range;
   MBParallelComm pcomm( &moab );
   int size = 0;
-  rval = pcomm.pack_buffer( entities, false, true, true, false,
-                            -1, tmp_range, size );
+  std::vector<unsigned char> buff;
+  rval = pcomm.pack_buffer( entities, false, true, false,
+                            -1, tmp_range, buff, size );
   CHECK_ERR(rval);
-  pcomm.buffer_size( size );
-  rval = pcomm.pack_buffer( entities, false, true, false, false,
-                            -1, tmp_range, size );
-  CHECK_ERR(rval);
   
-  std::vector<unsigned char> buffer;
-  pcomm.take_buffer( buffer );
-  // Apparently returned size is bogus.
-  // CHECK_EQUAL( (size_t)size, buffer.size() );
-  
   moab.~MBCore();
   new (&moab) MBCore();
   
   pcomm.~MBParallelComm();
-  new (&pcomm) MBParallelComm( &moab, buffer );
+  new (&pcomm) MBParallelComm( &moab);
   
   entities.clear();
-  rval = pcomm.unpack_buffer( entities, false, -1 );
+  rval = pcomm.unpack_buffer( &buff[0], false, -1, entities );
   CHECK_ERR(rval);
 }
 void pack_unpack_mesh( MBCore& moab )

Modified: MOAB/trunk/tools/mbzoltan/MBZoltan.cpp
===================================================================
--- MOAB/trunk/tools/mbzoltan/MBZoltan.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/tools/mbzoltan/MBZoltan.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -51,7 +51,9 @@
 }
 
 MBErrorCode MBZoltan::balance_mesh(const char *zmethod,
-                                   const char *other_method) 
+                                   const char *other_method,
+                                   const bool write_as_sets,
+                                   const bool write_as_tags) 
 {
   if (!strcmp(zmethod, "RCB") && !strcmp(zmethod, "RIB") &&
       !strcmp(zmethod, "HSFC") && !strcmp(zmethod, "Hypergraph") &&
@@ -164,7 +166,8 @@
                    exportProcs, &assignment);
   
   if (mbImpl->proc_rank() == 0) {
-    MBErrorCode result = write_partition(mbImpl->proc_size(), elems, assignment);
+    MBErrorCode result = write_partition(mbImpl->proc_size(), elems, assignment,
+                                         write_as_sets, write_as_tags);
 
     if (MB_SUCCESS != result) return result;
 
@@ -192,10 +195,17 @@
 
 MBErrorCode MBZoltan::partition_mesh(const int nparts,
                                      const char *zmethod,
-                                     const char *other_method) 
+                                     const char *other_method,
+                                     const bool write_as_sets,
+                                     const bool write_as_tags,
+                                     const int part_dim) 
 {
     // should only be called in serial
-  if (mbImpl->proc_size() != 1) return MB_FAILURE;
+  if (mbImpl->proc_size() != 1) {
+    std::cout << "MBZoltan::partition_mesh must be called in serial." 
+              << std::endl;
+    return MB_FAILURE;
+  }
   
   if (NULL != zmethod && strcmp(zmethod, "RCB") && strcmp(zmethod, "RIB") &&
       strcmp(zmethod, "HSFC") && strcmp(zmethod, "Hypergraph") &&
@@ -217,7 +227,7 @@
 
   MBErrorCode result;
   
-  result = assemble_graph(3, pts, ids, adjs, length, elems); RR;
+  result = assemble_graph(part_dim, pts, ids, adjs, length, elems); RR;
   
   myNumPts = mbInitializePoints((int)ids.size(), &pts[0], &ids[0], &adjs[0],
                                 &length[0]);
@@ -296,7 +306,8 @@
   if (ZOLTAN_OK != retval) return MB_FAILURE;
   
   // take results & write onto MOAB partition sets
-  result = write_partition(nparts, elems, assign_parts);
+  result = write_partition(nparts, elems, assign_parts,
+                           write_as_sets, write_as_tags);
 
   if (MB_SUCCESS != result) return result;
 
@@ -345,7 +356,8 @@
 
       // get bridge adjacencies
     adjs.clear();
-    result = mtu.get_bridge_adjacencies(*rit, dimension-1, dimension, adjs); RR;
+    result = mtu.get_bridge_adjacencies(*rit, (dimension > 0 ? dimension-1 : 3), 
+                                        dimension, adjs); RR;
     
     
       // get the graph vertex ids of those
@@ -389,7 +401,9 @@
 
 MBErrorCode MBZoltan::write_partition(const int nparts,
                                       MBRange &elems, 
-                                      const int *assignment) 
+                                      const int *assignment,
+                                      const bool write_as_sets,
+                                      const bool write_as_tags) 
 {
   MBErrorCode result;
 
@@ -405,50 +419,57 @@
                                                 tagged_sets, MBInterface::UNION); RR;
   if (!tagged_sets.empty()) {
     result = mbImpl->clear_meshset(tagged_sets); RR;
+    if (!write_as_sets) {
+      result = mbImpl->tag_delete_data(part_set_tag, tagged_sets); RR;
+    }
   }
+
+  if (write_as_sets) {
+      // first, create partition sets and store in vector
+    MBEntityHandle *part_sets = new MBEntityHandle[nparts];
+    if (NULL == part_sets) return MB_FAILURE;
   
-    // first, create partition sets and store in vector
-  MBEntityHandle *part_sets = new MBEntityHandle[nparts];
-  if (NULL == part_sets) return MB_FAILURE;
-  
-  if (nparts > (int) tagged_sets.size()) {
-      // too few partition sets - create missing ones
-    int num_new = nparts - tagged_sets.size();
-    for (int i = 0; i < num_new; i++) {
-      MBEntityHandle new_set;
-      result = mbImpl->create_meshset(MESHSET_SET, new_set); RR;
-      tagged_sets.insert(new_set);
+    if (nparts > (int) tagged_sets.size()) {
+        // too few partition sets - create missing ones
+      int num_new = nparts - tagged_sets.size();
+      for (int i = 0; i < num_new; i++) {
+        MBEntityHandle new_set;
+        result = mbImpl->create_meshset(MESHSET_SET, new_set); RR;
+        tagged_sets.insert(new_set);
+      }
     }
-  }
-  else if (nparts < (int) tagged_sets.size()) {
-      // too many partition sets - delete extras
-    int num_del = tagged_sets.size() - nparts;
-    for (int i = 0; i < num_del; i++) {
-      MBEntityHandle old_set = tagged_sets.pop_back();
-      result = mbImpl->delete_entities(&old_set, 1); RR;
+    else if (nparts < (int) tagged_sets.size()) {
+        // too many partition sets - delete extras
+      int num_del = tagged_sets.size() - nparts;
+      for (int i = 0; i < num_del; i++) {
+        MBEntityHandle old_set = tagged_sets.pop_back();
+        result = mbImpl->delete_entities(&old_set, 1); RR;
+      }
     }
-  }
   
-    // assign partition sets to vector
-  MBRange::iterator rit = tagged_sets.begin();
-  int i = 0;
-  for (; i < nparts; rit++, i++) part_sets[i] = *rit;
+      // assign partition sets to vector
+    MBRange::iterator rit = tagged_sets.begin();
+    int i = 0;
+    for (; i < nparts; rit++, i++) part_sets[i] = *rit;
   
-    // write a tag to those sets denoting they're partition sets, with a value of the
-    // proc number
-  int *dum_ids = new int[nparts];
-  for (int i = 0; i < nparts; i++) dum_ids[i] = i;
+      // write a tag to those sets denoting they're partition sets, with a value of the
+      // proc number
+    int *dum_ids = new int[nparts];
+    for (int i = 0; i < nparts; i++) dum_ids[i] = i;
   
-  result = mbImpl->tag_set_data(part_set_tag, part_sets, nparts, dum_ids); RR;
+    result = mbImpl->tag_set_data(part_set_tag, part_sets, nparts, dum_ids); RR;
 
-    // assign entities to the relevant sets
-  for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
-    result = mbImpl->add_entities(part_sets[assignment[i]], &(*rit), 1); RR;
+      // assign entities to the relevant sets
+    for (rit = elems.begin(), i = 0; rit != elems.end(); rit++, i++) {
+      result = mbImpl->add_entities(part_sets[assignment[i]], &(*rit), 1); RR;
+    }
   }
-
-    // allocate integer-size partitions
-  result = mbImpl->tag_set_data(part_set_tag, elems, assignment); RR;
-
+  
+  if (write_as_tags) {
+      // allocate integer-size partitions
+    result = mbImpl->tag_set_data(part_set_tag, elems, assignment); RR;
+  }
+  
   return MB_SUCCESS;
 }
 

Modified: MOAB/trunk/tools/mbzoltan/MBZoltan.hpp
===================================================================
--- MOAB/trunk/tools/mbzoltan/MBZoltan.hpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/tools/mbzoltan/MBZoltan.hpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -71,11 +71,16 @@
     ~MBZoltan();
 
     MBErrorCode balance_mesh(const char *zmethod,
-                             const char *other_method);
+                             const char *other_method,
+                             const bool write_as_sets = true,
+                             const bool write_as_tags = false);
     
     MBErrorCode partition_mesh(const int nparts,
                                const char *zmethod,
-                               const char *other_method);
+                               const char *other_method,
+                               const bool write_as_sets = true,
+                               const bool write_as_tags = false,
+                               const int part_dim = 3);
     
     int get_mesh(std::vector<double> &pts, std::vector<int> &ids,
                  std::vector<int> &adjs, std::vector<int> &length,
@@ -83,7 +88,10 @@
 
       // given a processor assignment returned from Zoltan, write that as a
       // processor assignment to MOAB
-    MBErrorCode write_partition(const int nparts, MBRange &elems, const int *assignment);
+    MBErrorCode write_partition(const int nparts, MBRange &elems, 
+                                const int *assignment,
+                                const bool write_as_sets,
+                                const bool write_as_tags);
 
     MBErrorCode write_file(const char *filename, const char *out_file);
   

Modified: MOAB/trunk/tools/mbzoltan/main.cpp
===================================================================
--- MOAB/trunk/tools/mbzoltan/main.cpp	2008-05-01 19:56:11 UTC (rev 1789)
+++ MOAB/trunk/tools/mbzoltan/main.cpp	2008-05-02 13:25:23 UTC (rev 1790)
@@ -24,8 +24,12 @@
     std::cout << "Usage: mpirun -np <nprocs> " << argv[0]
               << " <# partitions> "
               << " <mesh_file> <write_out(y/n)> <output_mesh_file> "
+              << "[write_as_sets(1=default/0)]"
+              << "[write_as_tags(1/0=default)]" 
+              << "[partition_dim(default=3)]"
               << "[<method(RCB/RIB/HSFC/Hypergraph(PHG)/PARMETIS/OCTPART)>] "
-              << "[<parmetis_method>/<oct_method>]" << std::endl;
+              << "[<parmetis_method>/<oct_method>]"
+              << std::endl;
     return 1;
   }
 
@@ -52,13 +56,20 @@
   
   MBZoltan *mbz = new MBZoltan(mbImpl, false, argc, argv);
 
+  int as_sets = 1, as_tags = 0, part_dim = 3;
+  if (argc > 5) as_sets = atoi(argv[5]);
+  if (argc > 6) as_tags = atoi(argv[6]);
+
+  if (argc > 7) part_dim = atoi(argv[7]);
+  
   const char *other_method = NULL, *method = NULL;
-  if (argc > 5) method = argv[5];
-  if (argc > 6) other_method = argv[6];
+  if (argc > 8) method = argv[8];
+  if (argc > 9) other_method = argv[9];
   
   int nparts = atoi(argv[1]);
   
-  result = mbz->partition_mesh(nparts, method, other_method); RR;
+  result = mbz->partition_mesh(nparts, method, other_method,
+                               as_sets, as_tags, part_dim); RR;
   
   if (write_output) {
     result = mbImpl->write_mesh(argv[4]); RR;




More information about the moab-dev mailing list