root/MOAB/trunk/parallel/MBParallelComm.cpp @ 2976

Revision 2976, 166.2 KB (checked in by kraftche, 5 months ago)

limit size of bcasts to 258 MB

Line 
1#include "MBInterface.hpp"
2#include "MBParallelComm.hpp"
3#include "MBWriteUtilIface.hpp"
4#include "MBReadUtilIface.hpp"
5#include "SequenceManager.hpp"
6#include "EntitySequence.hpp"
7#include "TagServer.hpp"
8#include "MBTagConventions.hpp"
9#include "MBSkinner.hpp"
10#include "MBParallelConventions.h"
11#include "MBCore.hpp"
12#include "MBError.hpp"
13#include "ElementSequence.hpp"
14#include "MBCN.hpp"
15#include "RangeMap.hpp"
16
17#include <iostream>
18#include <algorithm>
19#include <numeric>
20
21#define MIN(a,b) (a < b ? a : b)
22#define MAX(a,b) (a > b ? a : b)
23const bool debug = false;
24const bool debug_packing = false;
25
26#include <math.h>
27#include <assert.h>
28
29
30extern "C" 
31{
32#include "minmax.h"
33#include "gs.h"
34#include "errmem.h"
35#include "types.h"
36#include "sort.h"
37#include "tuple_list.h"
38}
39
40#ifdef USE_MPI
41#include "mpi.h"
42#endif
43
44const int INITIAL_BUFF_SIZE = 1024;
45const int MAX_BCAST_SIZE = (1<<28);
46
47//#define DEBUG_PACKING 1
48#ifdef DEBUG_PACKING
49unsigned int __PACK_num = 0, __UNPACK_num = 0, __PACK_count = 0, __UNPACK_count = 0;
50std::string __PACK_string, __UNPACK_string;
51
52#define PC(n, m) {\
53          if (__PACK_num == (unsigned int)n && __PACK_string == m) __PACK_count++;\
54          else {\
55            if (__PACK_count > 1) std::cerr << " (" << __PACK_count << "x)";\
56            __PACK_count = 1; __PACK_string = m; __PACK_num = n;\
57            std::cerr << std::endl << "PACK: " << n << m;\
58          }}
59#define UPC(n, m) {\
60          if (__UNPACK_num == (unsigned int)n && __UNPACK_string == m) __UNPACK_count++;\
61          else {\
62            if (__UNPACK_count > 1) std::cerr << "(" << __UNPACK_count << "x)";\
63            __UNPACK_count = 1; __UNPACK_string = m; __UNPACK_num = n;\
64            std::cerr << std::endl << "UNPACK: " << n << m;\
65          }}
66#else
67#define PC(n, m)
68#define UPC(n, m)
69#endif
70
71#define PACK_INT(buff, int_val) {int tmp_val = int_val; PACK_INTS(buff, &tmp_val, 1);}
72
73#define PACK_INTS(buff, int_val, num) {memcpy(buff, int_val, (num)*sizeof(int)); buff += (num)*sizeof(int); PC(num, " ints");}
74
75#define PACK_DBL(buff, dbl_val, num) {memcpy(buff, dbl_val, (num)*sizeof(double)); buff += (num)*sizeof(double); PC(num, " doubles");}
76
77#define PACK_EH(buff, eh_val, num) {memcpy(buff, eh_val, (num)*sizeof(MBEntityHandle)); buff += (num)*sizeof(MBEntityHandle); PC(num, " handles");}
78
79#define PACK_CHAR_64(buff, char_val) {strcpy((char*)buff, char_val); buff += 64; PC(64, " chars");}
80
81#define PACK_VOID(buff, val, num) {memcpy(buff, val, num); buff += num; PC(num, " void");}
82
83#define PACK_BYTES(buff, val, num) PACK_INT(buff, num) PACK_VOID(buff, val, num)
84
85#define PACK_RANGE(buff, rng) {int num_subs = num_subranges(rng); PACK_INTS(buff, &num_subs, 1); PC(num_subs, "-subranged range"); \
86          for (MBRange::const_pair_iterator cit = rng.const_pair_begin(); cit != rng.const_pair_end(); cit++) { \
87            MBEntityHandle eh = (*cit).first; PACK_EH(buff, &eh, 1); \
88            eh = (*cit).second; PACK_EH(buff, &eh, 1);}; }
89
90#define UNPACK_INT(buff, int_val) {UNPACK_INTS(buff, &int_val, 1);}
91
92#define UNPACK_INTS(buff, int_val, num) {memcpy(int_val, buff, (num)*sizeof(int)); buff += (num)*sizeof(int); UPC(num, " ints");}
93
94#define UNPACK_DBL(buff, dbl_val, num) {memcpy(dbl_val, buff, (num)*sizeof(double)); buff += (num)*sizeof(double); UPC(num, " doubles");}
95
96#define UNPACK_EH(buff, eh_val, num) {memcpy(eh_val, buff, (num)*sizeof(MBEntityHandle)); buff += (num)*sizeof(MBEntityHandle); UPC(num, " handles");}
97
98#define UNPACK_CHAR_64(buff, char_val) {strcpy(char_val, (char*)buff); buff += 64; UPC(64, " chars");}
99
100#define UNPACK_VOID(buff, val, num) {memcpy(val, buff, num); buff += num; UPC(num, " void");}
101
102#define UNPACK_RANGE(buff, rng) {int num_subs; UNPACK_INTS(buff, &num_subs, 1); UPC(num_subs, "-subranged range"); MBEntityHandle _eh[2]; \
103          for (int i = 0; i < num_subs; i++) { UNPACK_EH(buff, _eh, 2); rng.insert(_eh[0], _eh[1]);}}
104
105#define RR(a) if (MB_SUCCESS != result) {\
106          dynamic_cast<MBCore*>(mbImpl)->get_error_handler()->set_last_error(a);\
107          return result;}
108
109#define RRA(a) if (MB_SUCCESS != result) {\
110      std::string tmp_str; mbImpl->get_last_error(tmp_str);\
111      tmp_str.append("\n"); tmp_str.append(a);\
112      dynamic_cast<MBCore*>(mbImpl)->get_error_handler()->set_last_error(tmp_str.c_str()); \
113      return result;}
114
115/** Name of tag used to store MBParallelComm Index on mesh paritioning sets */
116const char* PARTITIONING_PCOMM_TAG_NAME = "__PRTN_PCOMM";
117 
118/** \brief Tag storing parallel communication objects
119 *
120 * This tag stores pointers to MBParallelComm communication
121 * objects; one of these is allocated for each different
122 * communicator used to read mesh.  MBParallelComm stores
123 * partition and interface sets corresponding to its parallel mesh.
124 * By default, a parallel read uses the first MBParallelComm object
125 * on the interface instance; if instantiated with one, ReadParallel
126 * adds this object to the interface instance too.
127 *
128 * Tag type: opaque
129 * Tag size: MAX_SHARING_PROCS*sizeof(MBParallelComm*)
130 */
131#define PARALLEL_COMM_TAG_NAME "__PARALLEL_COMM"
132
133
134enum MBMessageTag {MB_MESG_ANY=MPI_ANY_TAG, 
135                   MB_MESG_SIZE,
136                   MB_MESG_ENTS,
137                   MB_MESG_REMOTE_HANDLES_RANGE,
138                   MB_MESG_REMOTE_HANDLES_VECTOR,
139                   MB_MESG_TAGS };
140   
141MBParallelComm::MBParallelComm(MBInterface *impl, MPI_Comm comm, int* id ) 
142    : mbImpl(impl), procConfig(comm), sharedpTag(0), sharedpsTag(0),
143      sharedhTag(0), sharedhsTag(0), pstatusTag(0), ifaceSetsTag(0),
144      partitionTag(0), globalPartCount(-1), partitioningSet(0)
145{
146  myBuffer.resize(INITIAL_BUFF_SIZE);
147
148  tagServer = dynamic_cast<MBCore*>(mbImpl)->tag_server();
149  sequenceManager = dynamic_cast<MBCore*>(mbImpl)->sequence_manager();
150
151  int flag = 1;
152  int retval = MPI_Initialized(&flag);
153  if (MPI_SUCCESS != retval || !flag) {
154    int argc = 0;
155    char **argv = NULL;
156   
157      // mpi not initialized yet - initialize here
158    retval = MPI_Init(&argc, &argv);
159  }
160
161  pcommID = add_pcomm(this);
162  if (id)
163    *id = pcommID;
164}
165
166MBParallelComm::MBParallelComm(MBInterface *impl,
167                               std::vector<unsigned char> &tmp_buff, 
168                               MPI_Comm comm,
169                               int* id) 
170    : mbImpl(impl), procConfig(comm), sharedpTag(0), sharedpsTag(0),
171      sharedhTag(0), sharedhsTag(0), pstatusTag(0), ifaceSetsTag(0),
172      partitionTag(0), globalPartCount(-1), partitioningSet(0)
173{
174  myBuffer.swap(tmp_buff);
175  int flag = 1;
176  int retval = MPI_Initialized(&flag);
177  if (MPI_SUCCESS != retval || !flag) {
178    int argc = 0;
179    char **argv = NULL;
180   
181      // mpi not initialized yet - initialize here
182    retval = MPI_Init(&argc, &argv);
183  }
184
185  pcommID = add_pcomm(this);
186  if (id)
187    *id = pcommID;
188}
189
190MBParallelComm::~MBParallelComm() 
191{
192  remove_pcomm(this);
193}
194
195int MBParallelComm::add_pcomm(MBParallelComm *pc) 
196{
197    // add this pcomm to instance tag
198  std::vector<MBParallelComm *> pc_array(MAX_SHARING_PROCS, 
199                                         (MBParallelComm*)NULL);
200  MBTag pc_tag = pcomm_tag(mbImpl, true);
201  assert(0 != pc_tag);
202 
203  MBErrorCode result = mbImpl->tag_get_data(pc_tag, 0, 0, (void*)&pc_array[0]);
204  if (MB_SUCCESS != result && MB_TAG_NOT_FOUND != result) 
205    return -1;
206  int index = 0;
207  while (index < MAX_SHARING_PROCS && pc_array[index]) index++;
208  if (index == MAX_SHARING_PROCS) {
209    index = -1;
210    assert(false);
211  }
212  else {
213    pc_array[index] = pc;
214    mbImpl->tag_set_data(pc_tag, 0, 0, (void*)&pc_array[0]);
215  }
216  return index;
217}
218
219void MBParallelComm::remove_pcomm(MBParallelComm *pc) 
220{
221    // remove this pcomm from instance tag
222  std::vector<MBParallelComm *> pc_array(MAX_SHARING_PROCS);
223  MBTag pc_tag = pcomm_tag(mbImpl, true);
224 
225  MBErrorCode result = mbImpl->tag_get_data(pc_tag, 0, 0, (void*)&pc_array[0]);
226  std::vector<MBParallelComm*>::iterator pc_it = 
227    std::find(pc_array.begin(), pc_array.end(), pc);
228  assert(MB_SUCCESS == result && 
229         pc_it != pc_array.end());
230  *pc_it = NULL;
231  mbImpl->tag_set_data(pc_tag, 0, 0, (void*)&pc_array[0]);
232}
233
234//! assign a global id space, for largest-dimension or all entities (and
235//! in either case for vertices too)
236MBErrorCode MBParallelComm::assign_global_ids(MBEntityHandle this_set,
237                                              const int dimension, 
238                                              const int start_id,
239                                              const bool largest_dim_only,
240                                              const bool parallel) 
241{
242  MBRange entities[4];
243  int local_num_elements[4];
244  MBErrorCode result;
245  std::vector<unsigned char> pstatus;
246  for (int dim = 0; dim <= dimension; dim++) {
247    if (dim == 0 || !largest_dim_only || dim == dimension) {
248      result = mbImpl->get_entities_by_dimension(this_set, dim, entities[dim]); 
249      RRA("Failed to get vertices in assign_global_ids.");
250    }
251
252      // need to filter out non-locally-owned entities!!!
253    pstatus.resize(entities[dim].size());
254    result = mbImpl->tag_get_data(pstatus_tag(), entities[dim], &pstatus[0]);
255    RRA("Failed to get pstatus in assign_global_ids.");
256   
257    MBRange dum_range;
258    MBRange::iterator rit;
259    unsigned int i;
260    for (rit = entities[dim].begin(), i = 0; rit != entities[dim].end(); rit++, i++)
261      if (pstatus[i] & PSTATUS_NOT_OWNED)
262        dum_range.insert(*rit);
263    entities[dim] = entities[dim].subtract(dum_range);
264   
265    local_num_elements[dim] = entities[dim].size();
266  }
267 
268    // communicate numbers
269  std::vector<int> num_elements(procConfig.proc_size()*4);
270#ifdef USE_MPI
271  if (procConfig.proc_size() > 1 && parallel) {
272    int retval = MPI_Alltoall(local_num_elements, 4, MPI_INT,
273                              &num_elements[0], procConfig.proc_size()*4, 
274                              MPI_INT, procConfig.proc_comm());
275    if (0 != retval) return MB_FAILURE;
276  }
277  else
278#endif
279    for (int dim = 0; dim < 4; dim++) num_elements[dim] = local_num_elements[dim];
280 
281    // my entities start at one greater than total_elems[d]
282  int total_elems[4] = {start_id, start_id, start_id, start_id};
283 
284  for (unsigned int proc = 0; proc < procConfig.proc_rank(); proc++) {
285    for (int dim = 0; dim < 4; dim++) total_elems[dim] += num_elements[4*proc + dim];
286  }
287 
288    //assign global ids now
289  MBTag gid_tag;
290  int zero = 0;
291  result = mbImpl->tag_create(GLOBAL_ID_TAG_NAME, sizeof(int), 
292                              MB_TAG_DENSE, MB_TYPE_INTEGER, gid_tag,
293                              &zero, true);
294  if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) return result;
295 
296  for (int dim = 0; dim < 4; dim++) {
297    if (entities[dim].empty()) continue;
298    num_elements.resize(entities[dim].size());
299    int i = 0;
300    for (MBRange::iterator rit = entities[dim].begin(); rit != entities[dim].end(); rit++)
301      num_elements[i++] = total_elems[dim]++;
302   
303    result = mbImpl->tag_set_data(gid_tag, entities[dim], &num_elements[0]); 
304    RRA("Failed to set global id tag in assign_global_ids.");
305  }
306 
307  return MB_SUCCESS;
308}
309
310MBErrorCode MBParallelComm::send_entities(const int to_proc,
311                                          MBRange &orig_ents,
312                                          const bool adjs,
313                                          const bool tags,
314                                          const bool store_remote_handles,
315                                          MBRange &final_ents,
316                                          bool wait_all) 
317{
318
319    // find a spot in the proc buffers vector
320  int index = get_buffers(to_proc);
321 
322    // pack/send the entities to the destination
323  MPI_Request req_vec[2] = {MPI_REQUEST_NULL,  // send req (ownerSBuff)
324                             MPI_REQUEST_NULL}; // recv req (remote handles)
325  MBErrorCode result = pack_send_entities(to_proc, orig_ents, 
326                                          adjs, tags, store_remote_handles, false,
327                                          ownerSBuffs[index], ownerRBuffs[index],
328                                          req_vec[0], req_vec[1], final_ents);
329  RRA("Failed to pack-send entities.");
330
331  MPI_Status statuses[2];
332
333    // if we're storing remote handles, process the return message
334  if (store_remote_handles) {
335    assert(MPI_REQUEST_NULL != req_vec[1]);
336    MPI_Wait(&req_vec[1], &statuses[1]);
337    MBRange remote_range;
338    unsigned char *buff_ptr = &ownerRBuffs[index][0];
339    UNPACK_RANGE(buff_ptr, remote_range);
340    result = set_remote_data(final_ents, remote_range, to_proc);
341    RRA("Trouble setting remote data range on sent entities.");
342  }
343
344  if (wait_all) {
345      // wait for all to finish
346    int success = MPI_Waitall(2, req_vec, statuses);
347    if (success != MPI_SUCCESS) {
348      result = MB_FAILURE;
349      RRA("Failed in waitall in send_entities.");
350    }
351  }
352 
353  return MB_SUCCESS;
354}
355
356MBErrorCode MBParallelComm::recv_entities(const int from_proc,
357                                          const bool store_remote_handles,
358                                          MBRange &final_ents,
359                                          bool wait_all) 
360{
361  MBErrorCode result;
362 
363    // find a spot in the proc buffers vector
364  int index = get_buffers(from_proc);
365 
366    // recv/unpack entities from the sender
367  MPI_Request req = MPI_REQUEST_NULL;
368  MPI_Status status;
369  int success = MPI_Recv(&ghostRBuffs[index][0], ghostRBuffs[index].size(), 
370                         MPI_UNSIGNED_CHAR, from_proc, 
371                         MB_MESG_ANY, procConfig.proc_comm(), 
372                         &status);
373  if (MPI_SUCCESS != success) {
374    result = MB_FAILURE;
375    RRA("Recv failed in recv_ents.");
376  }
377
378    // check type, and if it's just the size, resize buffer and re-call recv
379  if (MB_MESG_SIZE == status.MPI_TAG) {
380    result = recv_size_buff(from_proc,
381                            ghostRBuffs[index],
382                            req, MB_MESG_ANY);
383    RRA("Failed to resize recv buffer.");
384    MPI_Wait(&req, &status);
385  }
386 
387    // ok, got the actual entities, now unpack
388  result = recv_unpack_entities(from_proc, store_remote_handles, false,
389                                ghostRBuffs[index], ghostSBuffs[index], 
390                                req, final_ents);
391  RRA("Failed to recv-unpack message.");
392
393  if (wait_all) {
394      // wait for last message to finish
395    int success = MPI_Wait(&req, &status);
396    if (success != MPI_SUCCESS) {
397      result = MB_FAILURE;
398      RRA("Failed in wait in recv_entities.");
399    }
400  }
401
402  return result;
403}
404
405int MBParallelComm::get_buffers(int to_proc) 
406{
407  int ind = -1;
408  std::vector<int>::iterator vit = 
409    std::find(buffProcs.begin(), buffProcs.end(), to_proc);
410  if (vit == buffProcs.end()) {
411    ind = buffProcs.size();
412    buffProcs.push_back(to_proc);
413    ownerSBuffs[ind].resize(INITIAL_BUFF_SIZE);
414    ghostRBuffs[ind].resize(INITIAL_BUFF_SIZE);
415      // allocate these other buffs in case we're storing remote handles
416    ownerRBuffs[ind].resize(INITIAL_BUFF_SIZE);
417    ghostSBuffs[ind].resize(INITIAL_BUFF_SIZE);
418     
419  }
420  else ind = vit - buffProcs.begin();
421  assert(ind < MAX_SHARING_PROCS);
422  return ind;
423}
424
425MBErrorCode MBParallelComm::pack_send_entities(const int to_proc,
426                                               MBRange &orig_ents,
427                                               const bool adjacencies,
428                                               const bool tags,
429                                               const bool store_remote_handles,
430                                               const bool iface_layer,
431                                               std::vector<unsigned char> &send_buff,
432                                               std::vector<unsigned char> &recv_buff,
433                                               MPI_Request &send_req,
434                                               MPI_Request &recv_req,
435                                               MBRange &final_ents) 
436{
437#ifndef USE_MPI
438  return MB_FAILURE;
439#else
440
441  MBErrorCode result = MB_SUCCESS;
442  MBRange whole_range;
443  int buff_size;
444   
445  result = pack_buffer(orig_ents, adjacencies, tags, 
446                       store_remote_handles, iface_layer, to_proc,
447                       final_ents, send_buff, buff_size); 
448  RRA("Failed to pack buffer in pack_send.");
449
450    // now that we know how many entities, post a receive for the
451    // remote range, if requested
452  int success;
453  if (store_remote_handles && iface_layer) {
454    recv_buff.resize(final_ents.size()*sizeof(MBEntityHandle) + sizeof(int));
455   
456    success = MPI_Irecv(&recv_buff[0], recv_buff.size(), MPI_UNSIGNED_CHAR, to_proc, 
457                        MB_MESG_REMOTE_HANDLES_VECTOR, procConfig.proc_comm(), 
458                        &recv_req);
459    if (success != MPI_SUCCESS) return MB_FAILURE;
460  }
461  else if (store_remote_handles && !iface_layer) {
462    recv_buff.resize(2*num_subranges(final_ents)*sizeof(MBEntityHandle) + sizeof(int));
463   
464    success = MPI_Irecv(&recv_buff[0], recv_buff.size(), MPI_UNSIGNED_CHAR, to_proc, 
465                        MB_MESG_REMOTE_HANDLES_RANGE, procConfig.proc_comm(), 
466                        &recv_req);
467    if (success != MPI_SUCCESS) return MB_FAILURE;
468  }
469
470    // if the message is large, send a first message to tell how large
471  if (INITIAL_BUFF_SIZE < buff_size) {
472    int tmp_buff_size = -buff_size;
473    int success = MPI_Send(&tmp_buff_size, sizeof(int), MPI_UNSIGNED_CHAR, 
474                           to_proc, MB_MESG_SIZE, procConfig.proc_comm());
475    if (success != MPI_SUCCESS) return MB_FAILURE;
476  }
477   
478    // send the buffer
479  success = MPI_Isend(&send_buff[0], buff_size, MPI_UNSIGNED_CHAR, to_proc, 
480                      MB_MESG_ENTS, procConfig.proc_comm(), &send_req);
481  if (success != MPI_SUCCESS) return MB_FAILURE;
482
483  return result;
484#endif
485}
486
487MBErrorCode MBParallelComm::recv_size_buff(const int from_proc,
488                                           std::vector<unsigned char> &recv_buff,
489                                           MPI_Request &recv_req,
490                                           int mesg_tag) 
491{
492    // use the received size to resize buffer, then post another irecv
493  recv_buff.resize(-(*((int*)&recv_buff[0])));
494  int success = MPI_Irecv(&recv_buff[0], recv_buff.size(), MPI_UNSIGNED_CHAR, from_proc, 
495                          mesg_tag, procConfig.proc_comm(), &recv_req);
496  if (MPI_SUCCESS != success) {
497    MBErrorCode result = MB_FAILURE;
498    RRA("Failed call to Irecv in recv_size_buff.");
499  }
500 
501  return MB_SUCCESS;
502}
503 
504MBErrorCode MBParallelComm::recv_unpack_entities(const int from_proc,
505                                                 const bool store_remote_handles,
506                                                 const bool iface_layer,
507                                                 std::vector<unsigned char> &recv_buff,
508                                                 std::vector<unsigned char> &send_buff,
509                                                 MPI_Request &send_req,
510                                                 MBRange &recd_ents)
511{
512#ifndef USE_MPI
513  return MB_FAILURE;
514#else
515
516  MBErrorCode result = MB_SUCCESS;
517 
518    // unpack the buffer
519  if (iface_layer) {
520    std::vector<MBEntityHandle> recd_ents_tmp;
521    unsigned char *buff_ptr = &recv_buff[0];
522    result = unpack_iface_entities(buff_ptr, from_proc, recd_ents_tmp);
523    RRA("Failed to unpack buffer in recv_unpack.");
524    if (store_remote_handles) {
525      int recd_size = recd_ents_tmp.size()*sizeof(MBEntityHandle) +
526          sizeof(int);
527      send_buff.resize(recd_size);
528      unsigned char *buff_ptr = &send_buff[0];
529      PACK_INT(buff_ptr, recd_ents_tmp.size());
530      PACK_EH(buff_ptr, &recd_ents_tmp[0], recd_ents_tmp.size());
531      int success = MPI_Isend(&send_buff[0], recd_size, MPI_UNSIGNED_CHAR, from_proc, 
532                              MB_MESG_REMOTE_HANDLES_VECTOR, procConfig.proc_comm(), &send_req);
533      if (success != MPI_SUCCESS) {
534        result = MB_FAILURE;
535        RRA("Failed to send handles in recv_unpack.");
536      }
537    }
538    std::copy(recd_ents_tmp.begin(), recd_ents_tmp.end(), mb_range_inserter(recd_ents));
539  }
540  else {
541    result = unpack_buffer(&recv_buff[0], store_remote_handles, from_proc, recd_ents); 
542    RRA("Failed to unpack buffer in recv_unpack.");
543    if (store_remote_handles) {
544      int recd_size = 2*num_subranges(recd_ents)*sizeof(MBEntityHandle) + sizeof(int);
545      send_buff.resize(recd_size);
546      unsigned char *buff_ptr = &send_buff[0];
547      PACK_RANGE(buff_ptr, recd_ents);
548      int success = MPI_Isend(&send_buff[0], recd_size, MPI_UNSIGNED_CHAR, from_proc, 
549                          MB_MESG_REMOTE_HANDLES_RANGE, procConfig.proc_comm(), &send_req);
550      if (success != MPI_SUCCESS) {
551        result = MB_FAILURE;
552        RRA("Failed to send handles in recv_unpack.");
553      }
554    }
555  }
556
557  return result;
558#endif
559}
560
561MBErrorCode MBParallelComm::broadcast_entities( const int from_proc,
562                                                MBRange &entities,
563                                                const bool adjacencies,
564                                                const bool tags) 
565{
566#ifndef USE_MPI
567  return MB_FAILURE;
568#else
569 
570  MBErrorCode result = MB_SUCCESS;
571  int success;
572  MBRange whole_range;
573  int buff_size;
574 
575  std::vector<unsigned char> buff;
576  if ((int)procConfig.proc_rank() == from_proc) {
577    result = pack_buffer( entities, adjacencies, tags, 
578                          false, false, -1,
579                          whole_range, buff, buff_size); 
580    RRA("Failed to compute buffer size in broadcast_entities.");
581  }
582
583  success = MPI_Bcast( &buff_size, 1, MPI_INT, from_proc, procConfig.proc_comm() );
584  if (MPI_SUCCESS != success) {
585    result = MB_FAILURE;
586    RRA("MPI_Bcast of buffer size failed.");
587  }
588 
589  if (!buff_size) // no data
590    return MB_SUCCESS;
591
592  if ((int)procConfig.proc_rank() != from_proc) 
593    buff.resize(buff_size);
594
595  size_t offset = 0;
596  while (buff_size) {
597    int size = std::min( buff_size, MAX_BCAST_SIZE );
598    success = MPI_Bcast( &buff[offset], size, MPI_UNSIGNED_CHAR, from_proc, procConfig.proc_comm() );
599    if (MPI_SUCCESS != success) {
600      result = MB_FAILURE;
601      RRA("MPI_Bcast of buffer failed.");
602    }
603   
604    offset += size;
605    buff_size -= size;
606  }
607
608  if ((int)procConfig.proc_rank() != from_proc) {
609    result = unpack_buffer(&buff[0], false, from_proc, entities);
610    RRA("Failed to unpack buffer in broadcast_entities.");
611  }
612
613  return MB_SUCCESS;
614#endif
615}
616
617MBErrorCode MBParallelComm::pack_buffer(MBRange &orig_ents, 
618                                        const bool adjacencies,
619                                        const bool tags,
620                                        const bool store_remote_handles,
621                                        const bool iface_layer,
622                                        const int to_proc,
623                                        MBRange &final_ents,
624                                        std::vector<unsigned char> &buff,
625                                        int &buff_size) 
626{
627    // pack the buffer with the entity ranges, adjacencies, and tags sections
628    //
629    // Note: new entities used in subsequent connectivity lists, sets, or tags,
630    //   are referred to as (MBMAXTYPE + index), where index is into vector
631    //   of new entities, 0-based
632    //
633    // DATA LAYOUT IN BUFFER:
634    // . w/ handles ? (0-no, 1-yes, range, 2-yes, vector)
635    // ENTITIES:
636    // . for all types:
637    //   - ent_type -- end of data indicated by ent_type == MBMAXTYPE
638    //   - range(ent type) -- #ents = range.size()
639    //   - if (ent_type == MBVERTEX) xxx[#ents], yyy[#ents], zzz[#ents]
640    //   - else {
641    //     . nodes_per_ent
642    //     . connect[#ents * nodes_per_ent]
643    //   - }
644    //   - if (handles) range/vector of remote handles
645    // SETS:
646    // . range of set handles -- (#sets = range.size())
647    // . options[#sets] (unsigned int)
648    // . if (unordered) set range
649    // . else if ordered
650    //   - #ents in set
651    //   - handles[#ents]
652    // . #parents
653    // . if (#parents) handles[#parents]
654    // . #children
655    // . if (#children) handles[#children]
656    // ADJACENCIES:
657    // (no adjs for now)
658    // TAGS:
659    // . #tags
660    // . for each tag
661    //   - tag size
662    //   - tag type
663    //   - data type
664    //   - if (default value)
665    //     . 1
666    //     . default value
667    //   - else
668    //     . 0
669    //   - name (null-terminated string, in char[64])
670    //   - range (size = #ents)
671    //   - tag_vals[#ents]
672
673  MBErrorCode result;
674
675  std::vector<MBEntityType> ent_types;
676  std::vector<MBRange> all_ranges;
677  std::vector<int> verts_per_entity;
678  MBRange set_range;
679  std::vector<MBRange> set_ranges;
680  std::vector<MBTag> all_tags;
681  std::vector<MBRange> tag_ranges;
682  std::vector<int> set_sizes;
683  std::vector<unsigned int> options_vec;
684
685  buff_size = 0;
686  MBRange::const_iterator rit;
687 
688    //=================
689    // count first...
690    //=================
691
692  unsigned char *buff_ptr = NULL;
693 
694    // entities
695  result = pack_entities(orig_ents, rit, final_ents, buff_ptr,
696                         buff_size, true, store_remote_handles, 
697                         iface_layer, to_proc, ent_types, all_ranges, 
698                         verts_per_entity); 
699  RRA("Packing entities (count) failed.");
700 
701    // sets
702  result = pack_sets(orig_ents, rit, final_ents, buff_ptr, buff_size, true,
703                     store_remote_handles, to_proc, set_range, set_ranges,
704                     set_sizes, options_vec); 
705  RRA("Packing sets (count) failed.");
706 
707    // adjacencies
708  if (adjacencies) {
709    result = pack_adjacencies(orig_ents, rit, final_ents, buff_ptr, 
710                              buff_size, true,
711                              store_remote_handles, to_proc);
712    RRA("Packing adjs (count) failed.");
713  }
714   
715    // tags
716  if (tags) {
717    result = get_tag_send_list( final_ents, all_tags, tag_ranges );
718    RRA("Failed to get tagged entities.")
719    result = pack_tags(orig_ents, rit, final_ents, buff_ptr, 
720                       buff_size, true, store_remote_handles, to_proc, 
721                       all_tags, tag_ranges);
722    RRA("Packing tags (count) failed.");
723  }
724
725    //=================
726    // now do the real packing
727    //=================
728
729  assert(0 <= buff_size);
730  buff.resize(buff_size);
731  int orig_buff_size = buff_size;
732  buff_size = 0;
733  buff_ptr = &buff[0];
734 
735    // entities
736  result = pack_entities(orig_ents, rit, final_ents, buff_ptr,
737                         buff_size, false, store_remote_handles, 
738                         iface_layer, to_proc, ent_types, 
739                         all_ranges, verts_per_entity); 
740  RRA("Packing entities (real) failed.");
741#ifdef DEBUG_PACKING
742  std::cerr << "pack_entities buffer space: " << buff_ptr - &buff[0] << " bytes." << std::endl;
743  unsigned char *tmp_buff = buff_ptr;
744#endif 
745 
746    // sets
747  result = pack_sets(orig_ents, rit, final_ents, buff_ptr, buff_size, false,
748                     store_remote_handles, to_proc, set_range, set_ranges,
749                     set_sizes, options_vec); 
750  RRA("Packing sets (real) failed.");
751#ifdef DEBUG_PACKING
752  std::cerr << "pack_sets buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
753  tmp_buff = buff_ptr;
754#endif 
755 
756    // adjacencies
757  if (adjacencies) {
758    result = pack_adjacencies(orig_ents, rit, final_ents, buff_ptr, 
759                              buff_size, false,
760                              store_remote_handles, to_proc);
761    RRA("Packing adjs (real) failed.");
762  }
763   
764    // tags
765  if (tags) {
766    result = pack_tags(orig_ents, rit, final_ents, buff_ptr, 
767                       buff_size, false, store_remote_handles, to_proc, all_tags,
768                       tag_ranges);
769    RRA("Packing tags (real) failed.");
770#ifdef DEBUG_PACKING
771    std::cerr << "pack_tags buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
772    tmp_buff = buff_ptr;
773#endif 
774  }
775
776    // original buffer size might be larger, because some
777    // ranges of local handles pack into more compact ranges of
778    // remote handles (because they're expressed using MBMAXTYPE plus
779    // index in new entity range, and that list of entities is likely
780    // to be compact)
781  assert(orig_buff_size >= buff_size);
782
783  return result;
784}
785 
786MBErrorCode MBParallelComm::unpack_buffer(unsigned char *buff_ptr,
787                                          const bool store_remote_handles,
788                                          int from_proc,
789                                          MBRange &final_ents)
790{
791  if (myBuffer.capacity() == 0) return MB_FAILURE;
792 
793#ifdef DEBUG_PACKING
794    unsigned char *tmp_buff = buff_ptr;
795#endif 
796  MBErrorCode result = unpack_entities(buff_ptr, store_remote_handles,
797                                       from_proc, final_ents);
798  RRA("Unpacking entities failed.");
799#ifdef DEBUG_PACKING
800    std::cerr << "unpack_entities buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
801    tmp_buff = buff_ptr;
802#endif 
803  result = unpack_sets(buff_ptr, final_ents, store_remote_handles, 
804                       from_proc);
805  RRA("Unpacking sets failed.");
806#ifdef DEBUG_PACKING
807    std::cerr << "unpack_sets buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
808    tmp_buff = buff_ptr;
809#endif 
810  result = unpack_tags(buff_ptr, final_ents, store_remote_handles,
811                       from_proc);
812  RRA("Unpacking tags failed.");
813#ifdef DEBUG_PACKING
814    std::cerr << "unpack_tags buffer space: " << buff_ptr - tmp_buff << " bytes." << std::endl;
815    tmp_buff = buff_ptr;
816#endif 
817
818#ifdef DEBUG_PACKING
819  std::cerr << std::endl;
820#endif
821 
822  return MB_SUCCESS;
823}
824
825int MBParallelComm::num_subranges(const MBRange &this_range)
826{
827    // ok, have all the ranges we'll pack; count the subranges
828  int num_sub_ranges = 0;
829  for (MBRange::const_pair_iterator pit = this_range.const_pair_begin(); 
830       pit != this_range.const_pair_end(); pit++)
831    num_sub_ranges++;
832
833  return num_sub_ranges;
834}
835
836MBErrorCode MBParallelComm::pack_entities(MBRange &entities,
837                                          MBRange::const_iterator &start_rit,
838                                          MBRange &whole_range,
839                                          unsigned char *&buff_ptr,
840                                          int &count,
841                                          const bool just_count,
842                                          const bool store_remote_handles,
843                                          const bool iface_layer,
844                                          const int to_proc,
845                                          std::vector<MBEntityType> &ent_types, 
846                                          std::vector<MBRange> &all_ranges, 
847                                          std::vector<int> &verts_per_entity) 
848{
849    // (. w/ handles ? (0-no, 1-yes, range, 2-yes, vector))
850    // ENTITIES:
851    // . for all types:
852    //   - ent_type -- end of data indicated by ent_type == MBMAXTYPE
853    //   - #ents
854    //   - if (ent_type == MBVERTEX) xxx[#ents], yyy[#ents], zzz[#ents]
855    //   - else {
856    //     . nodes_per_ent
857    //     . connect[#ents * nodes_per_ent]
858    //   - }
859    //   - if (handles) range/vector of remote handles
860
861  unsigned char *orig_buff_ptr = buff_ptr;
862  MBErrorCode result;
863  MBWriteUtilIface *wu = NULL;
864  if (!just_count) {
865    result = mbImpl->query_interface(std::string("MBWriteUtilIface"), 
866                                     reinterpret_cast<void**>(&wu));
867    RRA("Couldn't get MBWriteUtilIface.");
868
869  }
870 
871    // pack vertices
872  if (just_count) {
873      // don't count size of verts until after all entities are included
874    ent_types.push_back(MBVERTEX);
875    verts_per_entity.push_back(1);
876    all_ranges.push_back(entities.subset_by_type(MBVERTEX));
877  }
878  else {
879    if (!all_ranges[0].empty()) {
880      PACK_INT(buff_ptr, ((int) MBVERTEX));
881      PACK_INT(buff_ptr, ((int) all_ranges[0].size()));
882      int num_verts = all_ranges[0].size();
883      std::vector<double*> coords(3);
884      for (int i = 0; i < 3; i++)
885        coords[i] = reinterpret_cast<double*>(buff_ptr + i * num_verts * sizeof(double));
886
887      assert(NULL != wu);
888   
889      result = wu->get_node_arrays(3, num_verts, all_ranges[0], 0, 0, coords);
890      RRA("Couldn't allocate node space.");
891      PC(3*num_verts, " doubles");
892
893      buff_ptr += 3 * num_verts * sizeof(double);
894
895      if (store_remote_handles)
896        PACK_RANGE(buff_ptr, all_ranges[0]);
897
898#ifdef DEBUG_PACKING
899      std::cerr << "Packed " << all_ranges[0].size() << " vertices." << std::endl;
900#endif     
901    }
902  }
903
904    // place an iterator at the first non-vertex entity
905  if (!all_ranges[0].empty()) {
906    start_rit = entities.find(*all_ranges[0].rbegin());
907    start_rit++;
908  }
909  else {
910    start_rit = entities.begin();
911  }
912 
913  MBRange::const_iterator end_rit = start_rit;
914  std::vector<MBRange>::iterator allr_it = all_ranges.begin();
915 
916    // pack entities
917  if (just_count) {   
918
919      // get all ranges of entities that have different #'s of vertices or different types
920    while (end_rit != entities.end() && TYPE_FROM_HANDLE(*start_rit) != MBENTITYSET) {
921
922        // get the sequence holding this entity
923      EntitySequence *seq;
924      ElementSequence *eseq;
925      result = sequenceManager->find(*start_rit, seq);
926      RRA("Couldn't find entity sequence.");
927
928      if (NULL == seq) return MB_FAILURE;
929      eseq = dynamic_cast<ElementSequence*>(seq);
930
931        // if type and nodes per element change, start a new range
932      if (eseq->type() != *ent_types.rbegin() || 
933          (int) eseq->nodes_per_element() != *verts_per_entity.rbegin()) {
934        ent_types.push_back(eseq->type());
935        verts_per_entity.push_back(eseq->nodes_per_element());
936        all_ranges.push_back(MBRange());
937        allr_it++;
938      }
939   
940        // get position in entities list one past end of this sequence
941      end_rit = entities.lower_bound(start_rit, entities.end(), eseq->end_handle()+1);
942
943        // put these entities in the last range
944      std::copy(start_rit, end_rit, mb_range_inserter(*all_ranges.rbegin()));
945
946        // remove any which are already shared
947      if (store_remote_handles && !iface_layer) {
948        result = remove_nonowned_shared(*all_ranges.rbegin(), to_proc, false);
949        RRA("Failed nonowned_shared test.");
950      }
951
952      whole_range.merge(*all_ranges.rbegin());
953     
954        // now start where we last left off
955      start_rit = end_rit;
956    }
957
958      // update vertex range to cover vertices included in other entities
959      // and remove entities already there
960    result = mbImpl->get_adjacencies(whole_range, 0, false, all_ranges[0], 
961                                     MBInterface::UNION);
962    RRA("Failed get_adjacencies.");
963
964    if (store_remote_handles) {
965      whole_range = whole_range.subtract(all_ranges[0]);
966      result = remove_nonowned_shared(all_ranges[0], to_proc, false);
967      RRA("Failed nonowned_shared test.");
968    }
969   
970      // count those data, now that we know which
971      // entities get communicated
972    whole_range.merge(all_ranges[0]);
973    count += 3 * sizeof(double) * all_ranges[0].size();
974   
975      // space for the ranges
976    std::vector<MBRange>::iterator vit = all_ranges.begin();
977    std::vector<int>::iterator iit = verts_per_entity.begin();
978    std::vector<MBEntityType>::iterator eit = ent_types.begin();
979    for (; vit != all_ranges.end(); vit++, iit++, eit++) {
980        // entity type of this range, but passed as int
981      count += sizeof(int);
982     
983        // number of entities
984      count += sizeof(int);
985
986        // nodes per entity
987      if (iit != verts_per_entity.begin()) count += sizeof(int);
988
989        // connectivity of subrange
990      if (iit != verts_per_entity.begin()) {
991        count += *iit * sizeof(MBEntityHandle)*(*vit).size();
992      }
993     
994        // remote handles, if desired
995      if (store_remote_handles)
996        count += sizeof(int) + 2*sizeof(MBEntityHandle)*num_subranges(*vit);
997    }
998
999      // extra entity type at end, passed as int
1000    count += sizeof(int);
1001  }
1002  else {
1003      // for each range beyond the first
1004    allr_it++;
1005    std::vector<int>::iterator nv_it = verts_per_entity.begin();
1006    std::vector<MBEntityType>::iterator et_it = ent_types.begin();
1007    std::vector<MBEntityHandle> dum_connect;
1008    nv_it++; et_it++;
1009   
1010    for (; allr_it != all_ranges.end(); allr_it++, nv_it++, et_it++) {
1011        // pack the entity type
1012      PACK_INT(buff_ptr, ((int)*et_it));
1013
1014        // pack # ents
1015      PACK_INT(buff_ptr, (*allr_it).size());
1016     
1017        // pack the nodes per entity
1018      PACK_INT(buff_ptr, *nv_it);
1019     
1020        // pack the connectivity
1021      const MBEntityHandle *connect;
1022      int num_connect;
1023      MBEntityHandle *start_vec = (MBEntityHandle*)buff_ptr;
1024      for (MBRange::const_iterator rit = allr_it->begin(); rit != allr_it->end(); rit++) {
1025        result = mbImpl->get_connectivity(*rit, connect, num_connect, false,
1026                                          &dum_connect);
1027        RRA("Failed to get connectivity.");
1028        assert(num_connect == *nv_it);
1029        PACK_EH(buff_ptr, &connect[0], num_connect);
1030      }
1031
1032        // substitute destination handles
1033      result = get_remote_handles(store_remote_handles, start_vec, start_vec,
1034                                  *nv_it*(*allr_it).size(), to_proc,
1035                                  whole_range);
1036      RRA("Trouble getting remote handles when packing entities.");
1037
1038        // pack the handles
1039      if (store_remote_handles)
1040        PACK_RANGE(buff_ptr, (*allr_it));
1041
1042#ifdef DEBUG_PACKING
1043      std::cerr << "Packed " << (*allr_it).size() << " ents of type " 
1044                << MBCN::EntityTypeName(TYPE_FROM_HANDLE(*(allr_it->begin()))) << std::endl;
1045#endif     
1046     
1047    }
1048
1049      // pack MBMAXTYPE to indicate end of ranges
1050    PACK_INT(buff_ptr, ((int)MBMAXTYPE));
1051
1052    count += buff_ptr - orig_buff_ptr;
1053  }
1054
1055  if (debug_packing) std::cerr << std::endl << "Done packing entities." << std::endl;
1056
1057  return MB_SUCCESS;
1058}
1059
1060MBErrorCode MBParallelComm::get_remote_handles(const bool store_remote_handles,
1061                                               MBEntityHandle *from_vec, 
1062                                               MBEntityHandle *to_vec_tmp,
1063                                               int num_ents, int to_proc,
1064                                               const MBRange &new_ents) 
1065{
1066    // NOTE: THIS IMPLEMENTATION IS JUST LIKE THE RANGE-BASED VERSION, NO REUSE
1067    // AT THIS TIME, SO IF YOU FIX A BUG IN THIS VERSION, IT MAY BE IN THE
1068    // OTHER VERSION TOO!!!
1069  if (0 == num_ents) return MB_SUCCESS;
1070 
1071    // use a local destination ptr in case we're doing an in-place copy
1072  std::vector<MBEntityHandle> tmp_vector;
1073  MBEntityHandle *to_vec = to_vec_tmp;
1074  if (to_vec == from_vec) {
1075    tmp_vector.resize(num_ents);
1076    to_vec = &tmp_vector[0];
1077  }
1078
1079  if (!store_remote_handles) {
1080    int err;
1081      // in this case, substitute position in new_ents list
1082    for (int i = 0; i < num_ents; i++) {
1083      int ind = new_ents.index(from_vec[i]);
1084      to_vec[i] = CREATE_HANDLE(MBMAXTYPE, ind, err);
1085      assert(to_vec[i] != 0 && !err && -1 != ind);
1086    }
1087  }
1088  else {
1089    MBTag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
1090    MBErrorCode result = get_shared_proc_tags(sharedp_tag, sharedps_tag, 
1091                                              sharedh_tag, sharedhs_tag, pstatus_tag);
1092 
1093      // get single-proc destination handles and shared procs
1094    std::vector<int> sharing_procs(num_ents);
1095    result = mbImpl->tag_get_data(sharedh_tag, from_vec, num_ents,
1096                                  to_vec);
1097    RRA("Failed to get shared handle tag for remote_handles.");
1098    result = mbImpl->tag_get_data(sharedp_tag, from_vec, num_ents, &sharing_procs[0]);
1099    RRA("Failed to get sharing proc tag in remote_handles.");
1100    for (int j = 0; j < num_ents; j++) {
1101      if (to_vec[j] && sharing_procs[j] != to_proc)
1102        to_vec[j] = 0;
1103    }
1104   
1105    MBEntityHandle tmp_handles[MAX_SHARING_PROCS];
1106    int tmp_procs[MAX_SHARING_PROCS];
1107    int i;
1108      // go through results, and for 0-valued ones, look for multiple shared proc
1109    MBEntityHandle *tmp_eh;
1110    for (tmp_eh = to_vec, i = 0; i < num_ents; i++) {
1111      if (!to_vec[i]) {
1112        result = mbImpl->tag_get_data(sharedps_tag, from_vec+i, 1, tmp_procs);
1113        if (MB_SUCCESS == result) {
1114          for (int j = 0; j < MAX_SHARING_PROCS; j++) {
1115            if (-1 == tmp_procs[j]) break;
1116            else if (tmp_procs[j] == to_proc) {
1117              result = mbImpl->tag_get_data(sharedhs_tag, from_vec+i, 1, tmp_handles);
1118              RRA("Trouble getting sharedhs tag.");
1119              to_vec[i] = tmp_handles[j];
1120              assert(to_vec[i]);
1121              break;
1122            }
1123          }
1124        }
1125        if (!to_vec[i]) {
1126          int j = new_ents.index(from_vec[i]);
1127          if (-1 == j) {
1128            result = MB_FAILURE;
1129            RRA("Failed to find new entity in send list.");
1130          }
1131          int err;
1132          to_vec[i] = CREATE_HANDLE(MBMAXTYPE, j, err);
1133          if (err) {
1134            result = MB_FAILURE;
1135            RRA("Failed to create handle in remote_handles.");
1136          }
1137        }
1138      }
1139    }
1140  }
1141 
1142    // memcpy over results if from_vec and to_vec are the same
1143  if (to_vec_tmp == from_vec) 
1144    memcpy(from_vec, to_vec, num_ents * sizeof(MBEntityHandle));
1145 
1146  return MB_SUCCESS;
1147}
1148
1149MBErrorCode MBParallelComm::get_remote_handles(const bool store_remote_handles,
1150                                               const MBRange &from_range, 
1151                                               MBEntityHandle *to_vec,
1152                                               int to_proc,
1153                                               const MBRange &new_ents) 
1154{
1155    // NOTE: THIS IMPLEMENTATION IS JUST LIKE THE VECTOR-BASED VERSION, NO REUSE
1156    // AT THIS TIME, SO IF YOU FIX A BUG IN THIS VERSION, IT MAY BE IN THE
1157    // OTHER VERSION TOO!!!
1158  if (from_range.empty()) return MB_SUCCESS;
1159 
1160  if (!store_remote_handles) {
1161    int err;
1162      // in this case, substitute position in new_ents list
1163    MBRange::iterator rit;
1164    unsigned int i;
1165    for (rit = from_range.begin(), i = 0; rit != from_range.end(); rit++, i++) {
1166      int ind = new_ents.index(*rit);
1167      to_vec[i] = CREATE_HANDLE(MBMAXTYPE, ind, err);
1168      assert(to_vec[i] != 0 && !err && -1 != ind);
1169    }
1170  }
1171  else {
1172    MBTag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
1173    MBErrorCode result = get_shared_proc_tags(sharedp_tag, sharedps_tag, 
1174                                              sharedh_tag, sharedhs_tag, pstatus_tag);
1175 
1176      // get single-proc destination handles and shared procs
1177    std::vector<int> sharing_procs(from_range.size());
1178    result = mbImpl->tag_get_data(sharedh_tag, from_range, to_vec);
1179    RRA("Failed to get shared handle tag for remote_handles.");
1180    result = mbImpl->tag_get_data(sharedp_tag, from_range, &sharing_procs[0]);
1181    RRA("Failed to get sharing proc tag in remote_handles.");
1182    for (unsigned int j = 0; j < from_range.size(); j++) {
1183      if (to_vec[j] && sharing_procs[j] != to_proc)
1184        to_vec[j] = 0;
1185    }
1186   
1187    MBEntityHandle tmp_handles[MAX_SHARING_PROCS];
1188    int tmp_procs[MAX_SHARING_PROCS];
1189      // go through results, and for 0-valued ones, look for multiple shared proc
1190    MBRange::iterator rit;
1191    unsigned int i;
1192    for (rit = from_range.begin(), i = 0; rit != from_range.end(); rit++, i++) {
1193      if (!to_vec[i]) {
1194        result = mbImpl->tag_get_data(sharedhs_tag, &(*rit), 1, tmp_handles);
1195        if (MB_SUCCESS == result) {
1196          result = mbImpl->tag_get_data(sharedps_tag, &(*rit), 1, tmp_procs);
1197          RRA("Trouble getting sharedps tag.");
1198          for (int j = 0; j < MAX_SHARING_PROCS; j++)
1199            if (tmp_procs[j] == to_proc) {
1200              to_vec[i] = tmp_handles[j];
1201              break;
1202            }
1203        }
1204     
1205        if (!to_vec[i]) {
1206          int j = new_ents.index(*rit);
1207          if (-1 == j) {
1208            result = MB_FAILURE;
1209            RRA("Failed to find new entity in send list.");
1210          }
1211          int err;
1212          to_vec[i] = CREATE_HANDLE(MBMAXTYPE, j, err);
1213          if (err) {
1214            result = MB_FAILURE;
1215            RRA("Failed to create handle in remote_handles.");
1216          }
1217        }
1218      }
1219    }
1220  }
1221 
1222  return MB_SUCCESS;
1223}
1224
1225MBErrorCode MBParallelComm::get_remote_handles(const bool store_remote_handles,
1226                                               const MBRange &from_range, 
1227                                               MBRange &to_range,
1228                                               int to_proc,
1229                                               const MBRange &new_ents) 
1230{
1231  std::vector<MBEntityHandle> to_vector(from_range.size());
1232
1233  MBErrorCode result =
1234    get_remote_handles(store_remote_handles, from_range, &to_vector[0],
1235                       to_proc, new_ents);
1236  RRA("Trouble getting remote handles.");
1237  std::copy(to_vector.begin(), to_vector.end(), mb_range_inserter(to_range));
1238  return result;
1239}
1240
1241MBErrorCode MBParallelComm::unpack_entities(unsigned char *&buff_ptr,
1242                                            const bool store_remote_handles,
1243                                            const int from_proc,
1244                                            MBRange &entities) 
1245{
1246  MBErrorCode result;
1247  bool done = false;
1248  MBReadUtilIface *ru = NULL;
1249  result = mbImpl->query_interface(std::string("MBReadUtilIface"), 
1250                                   reinterpret_cast<void**>(&ru));
1251  RRA("Failed to get MBReadUtilIface.");
1252 
1253 
1254  while (!done) {
1255    MBEntityType this_type;
1256    MBEntityHandle actual_start;
1257    UNPACK_INT(buff_ptr, this_type);
1258    assert(this_type >= MBVERTEX && 
1259           (this_type == MBMAXTYPE || this_type < MBENTITYSET));
1260
1261      // MBMAXTYPE signifies end of entities data
1262    if (MBMAXTYPE == this_type) break;
1263   
1264      // get the number of ents
1265    int num_ents;
1266    UNPACK_INT(buff_ptr, num_ents);
1267   
1268    if (MBVERTEX == this_type) {
1269        // unpack coords
1270      if (num_ents) {
1271        std::vector<double*> coords(3);
1272        result = ru->get_node_arrays(3, num_ents, 0, 
1273                                     actual_start, coords);
1274        RRA("Failed to allocate node arrays.");
1275
1276        entities.insert(actual_start, actual_start+num_ents-1);
1277     
1278          // unpack the buffer data directly into coords
1279        for (int i = 0; i < 3; i++) 
1280          memcpy(coords[i], buff_ptr+i*num_ents*sizeof(double), 
1281                 num_ents*sizeof(double));
1282        buff_ptr += 3*num_ents * sizeof(double);
1283        UPC(3*num_ents, " doubles");
1284
1285          // unpack source handles
1286        if (store_remote_handles) {
1287          MBRange this_range;
1288          this_range.insert(actual_start, actual_start+num_ents-1);
1289          MBRange dum_range;
1290          UNPACK_RANGE(buff_ptr, dum_range);
1291          result = set_remote_data(this_range, dum_range, from_proc);
1292          RRA("Couldn't set sharing data");
1293        }
1294      }
1295    }
1296
1297    else {
1298      int verts_per_entity;
1299     
1300        // unpack the nodes per entity
1301      UNPACK_INT(buff_ptr, verts_per_entity);
1302     
1303      MBEntityHandle *connect;
1304      result = ru->get_element_array(num_ents, verts_per_entity, this_type,
1305                                     0, actual_start,
1306                                     connect);
1307      RRA("Failed to allocate element arrays.");
1308
1309        // unpack the connectivity
1310      UNPACK_EH(buff_ptr, connect, (num_ents*verts_per_entity));
1311      entities.insert(actual_start, actual_start+num_ents-1);
1312
1313        // convert to local handles
1314      result = get_local_handles(connect, num_ents*verts_per_entity,
1315                                 entities);
1316      RRA("Couldn't get local handles.");
1317
1318      if (store_remote_handles) {
1319          // unpack source handles
1320        MBRange this_range;
1321        this_range.insert(actual_start, actual_start+num_ents-1);
1322        MBRange dum_range;
1323        UNPACK_RANGE(buff_ptr, dum_range);
1324        result = set_remote_data(this_range, dum_range, from_proc);
1325        RRA("Couldn't set sharing data");
1326      }
1327
1328        // update adjacencies
1329      result = ru->update_adjacencies(actual_start, num_ents, 
1330                                      verts_per_entity, connect);
1331      RRA("Failed to update adjacencies.");
1332    }
1333
1334#ifdef DEBUG_PACKING
1335      std::cerr << "Unpacked " << num_ents << " ents of type " 
1336                << MBCN::EntityTypeName(TYPE_FROM_HANDLE(actual_start)) << std::endl;
1337#endif     
1338
1339  }
1340 
1341 
1342  if (debug_packing) std::cerr << std::endl << "Done unpacking entities." << std::endl;
1343
1344  return MB_SUCCESS;
1345}
1346
1347MBErrorCode MBParallelComm::unpack_iface_entities(unsigned char *&buff_ptr,
1348                                                  const int from_proc, 
1349                                                  std::vector<MBEntityHandle> &recd_ents) 
1350{
1351    // for all the entities in the received buffer; for each, save
1352    // entities in this instance which match connectivity, or zero if none found
1353  MBErrorCode result;
1354  bool done = false;
1355  std::vector<MBEntityHandle> connect;
1356 
1357  while (!done) {
1358    MBEntityType this_type;
1359    UNPACK_INT(buff_ptr, this_type);
1360    assert(this_type > MBVERTEX && 
1361           (this_type == MBMAXTYPE || this_type < MBENTITYSET));
1362
1363      // MBMAXTYPE signifies end of entities data
1364    if (MBMAXTYPE == this_type) break;
1365   
1366      // get the number of ents
1367    int num_ents;
1368    UNPACK_INT(buff_ptr, num_ents);
1369   
1370    int verts_per_entity;
1371     
1372      // unpack the verts per entity
1373    UNPACK_INT(buff_ptr, verts_per_entity);
1374
1375    connect.resize(verts_per_entity * num_ents);
1376   
1377      // unpack the connectivity
1378    UNPACK_EH(buff_ptr, &connect[0], (num_ents*verts_per_entity));
1379
1380      // unpack source handles
1381    MBRange source_range, tmp_range;
1382    UNPACK_RANGE(buff_ptr, source_range);
1383
1384      // save matching local entities, or 0 if none found
1385    for (int i = 0; i < num_ents; i++) {
1386        // test for existing entity
1387      result = mbImpl->get_adjacencies(&connect[0]+i*verts_per_entity, verts_per_entity, 
1388                                       MBCN::Dimension(this_type), false, tmp_range);
1389      if (MB_MULTIPLE_ENTITIES_FOUND == result) {
1390        RRA("Multiple entities found.");
1391      }
1392      if (!tmp_range.empty()) {
1393          // found a corresponding entity - save target
1394        assert(1 == tmp_range.size());
1395        recd_ents.push_back(*tmp_range.begin());
1396        tmp_range.clear();
1397      }
1398      else
1399        recd_ents.push_back(0);
1400    }
1401
1402#ifdef DEBUG_PACKING
1403    std::cerr << "Unpacked " << num_ents << " ents of type " 
1404              << MBCN::EntityTypeName(TYPE_FROM_HANDLE(actual_start)) << std::endl;
1405#endif     
1406
1407  }
1408 
1409 
1410  if (debug_packing) std::cerr << std::endl << "Done unpacking iface entities." << std::endl;
1411
1412  return MB_SUCCESS;
1413}
1414
1415MBErrorCode MBParallelComm::get_local_handles(const MBRange &remote_handles,
1416                                              MBRange &local_handles,
1417                                              const MBRange &new_ents) 
1418{
1419  std::vector<MBEntityHandle> rh_vec;
1420  rh_vec.reserve(remote_handles.size());
1421  std::copy(remote_handles.begin(), remote_handles.end(), std::back_inserter(rh_vec));
1422  MBErrorCode result = get_local_handles(&rh_vec[0], remote_handles.size(), new_ents);
1423  std::copy(rh_vec.begin(), rh_vec.end(), mb_range_inserter(local_handles));
1424  return result;
1425}
1426 
1427MBErrorCode MBParallelComm::get_local_handles(MBEntityHandle *from_vec, 
1428                                              int num_ents,
1429                                              const MBRange &new_ents) 
1430{
1431  for (int i = 0; i < num_ents; i++) {
1432    if (TYPE_FROM_HANDLE(from_vec[i]) == MBMAXTYPE) {
1433      assert(ID_FROM_HANDLE(from_vec[i]) < (int) new_ents.size());
1434      from_vec[i] = new_ents[ID_FROM_HANDLE(from_vec[i])];
1435    }
1436  }
1437 
1438  return MB_SUCCESS;
1439}
1440
1441MBErrorCode MBParallelComm::set_remote_data(MBRange &local_range,
1442                                            MBRange &remote_range,
1443                                            int other_proc) 
1444{
1445    // NOTE: THIS IMPLEMENTATION IS JUST LIKE THE VECTOR-BASED VERSION, NO REUSE
1446    // AT THIS TIME, SO IF YOU FIX A BUG IN THIS VERSION, IT MAY BE IN THE
1447    // OTHER VERSION TOO!!!
1448
1449  MBTag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
1450  MBErrorCode result = get_shared_proc_tags(sharedp_tag, sharedps_tag, 
1451                                            sharedh_tag, sharedhs_tag, pstatus_tag);
1452
1453    // get remote procs tag, if any
1454  MBRange tmp_range, tmp_local_range = local_range;
1455  std::vector<int> remote_proc(local_range.size());
1456  std::vector<int> remote_procs(MAX_SHARING_PROCS);
1457  std::vector<MBEntityHandle> remote_handle(local_range.size());
1458  std::vector<MBEntityHandle> remote_handles(MAX_SHARING_PROCS);
1459  std::fill(remote_procs.begin(), remote_procs.end(), -1);
1460  std::fill(remote_handles.begin(), remote_handles.end(), 0);
1461  result = mbImpl->tag_get_data(sharedp_tag, local_range,
1462                                &remote_proc[0]);
1463  RRA("Couldn't get sharedp tag (range).");
1464  result = mbImpl->tag_get_data(sharedh_tag, local_range,
1465                                &remote_handle[0]);
1466  RRA("Couldn't get sharedh tag (range).");
1467  MBRange::iterator rit, rit2;
1468  int i = 0;
1469
1470    // for each pair of local/remote handles:
1471  for (rit = tmp_local_range.begin(), rit2 = remote_range.begin(); 
1472       rit != tmp_local_range.end(); rit++, rit2++, i++) {
1473
1474      // get existing remote proc(s), handle(s) for this local handle
1475    remote_procs[0] = remote_proc[i];
1476    if (-1 != remote_procs[0]) remote_handles[0] = remote_handle[i];
1477    else {
1478      result = mbImpl->tag_get_data(sharedps_tag, &(*rit), 1,
1479                                    &remote_procs[0]);
1480      if (MB_SUCCESS == result) {
1481        result = mbImpl->tag_get_data(sharedhs_tag, &(*rit), 1,
1482                                      &remote_handles[0]);
1483        RRA("Couldn't get sharedhs tag (range).");
1484      }
1485    }
1486
1487      // now insert other_proc, handle into these, and set the tags
1488    if (-1 == remote_procs[0]) {
1489      remote_procs[0] = other_proc;
1490      remote_handles[0] = *rit2;
1491      result = mbImpl->tag_set_data(sharedp_tag, &(*rit), 1, &remote_procs[0]);
1492      RRA("Couldn't set sharedp tag (range)");
1493      result = mbImpl->tag_set_data(sharedh_tag, &(*rit), 1, &remote_handles[0]);
1494      RRA("Couldn't set sharedh tag (range)");
1495      remote_procs[0] = -1;
1496      remote_handles[0] = 0;
1497    }
1498    else {
1499      std::vector<int>::iterator vit = remote_procs.begin();
1500      std::vector<MBEntityHandle>::iterator vit2 = remote_handles.begin();
1501      while (-1 != *vit && vit != remote_procs.end() && other_proc > *vit) {
1502        vit++; vit2++;
1503      }
1504      assert(*vit != other_proc);
1505      remote_procs.insert(vit, other_proc);
1506      remote_handles.insert(vit2, *rit2);
1507        // need to pop 'cuz we're using an insert above
1508      remote_procs.pop_back();
1509      remote_handles.pop_back();
1510      result = mbImpl->tag_set_data(sharedps_tag, &(*rit), 1, &remote_procs[0]);
1511      RRA("Couldn't set sharedps tag (range)");
1512      result = mbImpl->tag_set_data(sharedhs_tag, &(*rit), 1, &remote_handles[0]);
1513      RRA("Couldn't set sharedhs tag (range)");
1514      std::fill(remote_procs.begin(), remote_procs.end(), -1);
1515      std::fill(remote_handles.begin(), remote_handles.end(), 0);
1516        // need to clear sharedp_tag and sharedh_tag if prev
1517        // data came from there
1518      if (-1 != remote_proc[i]) {
1519        remote_proc[i] = -1;
1520        remote_handle[i] = 0;
1521        result = mbImpl->tag_set_data(sharedp_tag, &*rit, 1, &remote_proc[i] );
1522        RRA("Couldn't set sharedp tag");
1523        result = mbImpl->tag_set_data(sharedh_tag, &*rit, 1, &remote_handle[i] );
1524        RRA("Couldn't set sharedp tag");
1525      }
1526    }
1527  }
1528
1529    // also update shared flag for these ents
1530  unsigned char *shared_flags = (unsigned char*) &remote_proc[0];
1531  result = mbImpl->tag_get_data(pstatus_tag, local_range, shared_flags);
1532  RRA("Couldn't get pstatus tag (range)");
1533  for (unsigned int i = 0; i < local_range.size(); i++)
1534    shared_flags[i] |= PSTATUS_SHARED;
1535  result = mbImpl->tag_set_data(pstatus_tag, local_range, shared_flags);
1536  RRA("Couldn't set pstatus tag (range)");
1537 
1538 
1539  return MB_SUCCESS;
1540}
1541 
1542MBErrorCode MBParallelComm::set_remote_data(MBEntityHandle *local_ents,
1543                                            MBEntityHandle *remote_ents,
1544                                            int num_ents,
1545                                            int other_proc) 
1546{
1547  if (0 == num_ents)
1548    return MB_SUCCESS;
1549
1550    // NOTE: THIS IMPLEMENTATION IS JUST LIKE THE RANGE-BASED VERSION, NO REUSE
1551    // AT THIS TIME, SO IF YOU FIX A BUG IN THIS VERSION, IT MAY BE IN THE
1552    // OTHER VERSION TOO!!!
1553  MBTag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
1554  MBErrorCode result = get_shared_proc_tags(sharedp_tag, sharedps_tag, 
1555                                            sharedh_tag, sharedhs_tag, pstatus_tag);
1556
1557    // get remote procs tag, if any
1558  MBRange tmp_range;
1559  std::vector<int> remote_proc(num_ents);
1560  int remote_procs[MAX_SHARING_PROCS];
1561  std::vector<MBEntityHandle> remote_handle(num_ents);
1562  MBEntityHandle remote_handles[MAX_SHARING_PROCS];
1563  std::vector<unsigned char> pstatus_vals(num_ents);
1564  result = mbImpl->tag_get_data(sharedp_tag, local_ents, num_ents,
1565                                &remote_proc[0]);
1566  RRA("Couldn't get sharedp tag (vector)");
1567  result = mbImpl->tag_get_data(sharedh_tag, local_ents, num_ents,
1568                                &remote_handle[0]);
1569  RRA("Couldn't get sharedh tag (vector)");
1570  result = mbImpl->tag_get_data(pstatus_tag, local_ents, num_ents,
1571                                &pstatus_vals[0]);
1572  RRA("Couldn't get sharedh tag (vector)");
1573
1574    // for each local/remote handle pair
1575  for (int i = 0; i != num_ents; i++) {
1576
1577      // get existing remote proc(s), handle(s) for this local handle
1578    if (-1 != remote_proc[i]) {
1579      remote_procs[0] = remote_proc[i];
1580      remote_handles[0] = remote_handle[i];
1581      std::fill(remote_procs+1, remote_procs+MAX_SHARING_PROCS, -1);
1582      std::fill(remote_handles+1, remote_handles+MAX_SHARING_PROCS, 0);
1583    }
1584    else {
1585      result = mbImpl->tag_get_data(sharedps_tag, local_ents+i, 1,
1586                                    remote_procs);
1587      RRA("Couldn't get sharedps tag (vector)");
1588     
1589      result = mbImpl->tag_get_data(sharedhs_tag, local_ents+i, 1,
1590                                    remote_handles);
1591      RRA("Couldn't get sharedhs tag (vector)");
1592    }
1593
1594      // now either insert other_proc, handle into these, or remove if
1595      // remote handle is 0
1596    if (0 == remote_ents[i]) {
1597      result = rmv_remote_proc(local_ents[i], remote_procs, remote_handles,
1598                               other_proc);
1599      RRA(" ");
1600    }
1601    else {
1602      result = add_remote_proc(local_ents[i], remote_procs, remote_handles,
1603                               other_proc, remote_ents[i]);
1604      RRA(" ");
1605    }
1606  }
1607
1608  return MB_SUCCESS;
1609}
1610
1611MBErrorCode MBParallelComm::rmv_remote_proc(MBEntityHandle ent,
1612                                            int *remote_procs,
1613                                            MBEntityHandle *remote_hs,
1614                                            int remote_proc) 
1615{
1616  int i = std::find(remote_procs, remote_procs+MAX_SHARING_PROCS, -1) - remote_procs;
1617  int j = std::find(remote_procs, remote_procs+i, remote_proc) - remote_procs;
1618  MBErrorCode result;
1619
1620    // remote_proc must be in this list
1621  assert(j != i);
1622 
1623  for (; j != i; j++) {
1624    remote_procs[j] = remote_procs[j+1];
1625    remote_hs[j] = remote_hs[j+1];
1626  }
1627
1628  if (i == 1) {
1629      // only had one proc, and now have none; have to set the values,
1630      // since they're sparse tags
1631    result = mbImpl->tag_set_data(sharedp_tag(), &ent, 1, remote_procs);
1632    result = mbImpl->tag_set_data(sharedh_tag(), &ent, 1, remote_hs);
1633      // if it's not shared, it's also not a ghost, interface, or !owned entity
1634    unsigned char not_shared = 0;
1635    result = mbImpl->tag_set_data(pstatus_tag(), &ent, 1, &not_shared);
1636  }
1637  else if (i == 2) {
1638      // went from 2 to 1, need to unset 1 and set the other
1639    result = mbImpl->tag_set_data(sharedp_tag(), &ent, 1, remote_procs);
1640    RRA("Couldn't set sharedp tag");
1641    result = mbImpl->tag_set_data(sharedh_tag(), &ent, 1, remote_hs);
1642    RRA("Couldn't set sharedh tag");
1643    result = mbImpl->tag_delete_data(sharedps_tag(), &ent, 1);
1644    RRA("Couldn't remove sharedps tag");
1645    result = mbImpl->tag_delete_data(sharedhs_tag(), &ent, 1);
1646    RRA("Couldn't remove sharedhs tag");
1647  }
1648  else {
1649    result = mbImpl->tag_set_data(sharedps_tag(), &ent, 1, remote_procs);
1650    RRA("Couldn't set sharedps tag");
1651    result = mbImpl->tag_set_data(sharedhs_tag(), &ent, 1, remote_hs);
1652    RRA("Couldn't set sharedhs tag");
1653  }
1654 
1655  return MB_SUCCESS;
1656}
1657
1658template <typename T> void
1659insert_in_array( T* array, size_t array_size, size_t location, T value )
1660{
1661  assert( location+1 < array_size );
1662  for (size_t i = array_size-1; i > location; --i)
1663    array[i] = array[i-1];
1664  array[location] = value;
1665}
1666
1667MBErrorCode MBParallelComm::add_remote_proc(MBEntityHandle ent,
1668                                            int *remote_procs,
1669                                            MBEntityHandle *remote_hs,
1670                                            int remote_proc,
1671                                            MBEntityHandle remote_handle) 
1672{
1673  int* ptr = std::find( remote_procs, remote_procs+MAX_SHARING_PROCS, -1 );
1674  const size_t n = ptr - remote_procs;
1675  ptr = std::lower_bound( remote_procs, remote_procs+n, remote_proc );
1676  const size_t i = ptr - remote_procs;
1677 
1678  MBErrorCode result;
1679  const int invalid_proc = -1;
1680  const MBEntityHandle invalid_handle = 0;
1681  if (i == n || remote_procs[i] != remote_proc) {
1682    insert_in_array( remote_procs, MAX_SHARING_PROCS, i, remote_proc );
1683    insert_in_array( remote_hs, MAX_SHARING_PROCS, i, remote_handle );
1684   
1685    switch (n) {
1686      case 0:
1687        result = mbImpl->tag_set_data( sharedp_tag(), &ent, 1, remote_procs );
1688        RRA("Couldn't set sharedp tag");
1689        result = mbImpl->tag_set_data( sharedh_tag(), &ent, 1, remote_hs );
1690        RRA("Couldn't set sharedh tag");
1691        break;
1692      case 1:
1693          // going from 1 -> many, so clear single-value tag
1694        result = mbImpl->tag_set_data(  sharedp_tag(), &ent, 1, &invalid_proc );
1695        RRA("Couldn't set sharedp tag");
1696        result = mbImpl->tag_set_data( sharedh_tag(), &ent, 1, &invalid_handle );
1697        RRA("Couldn't set sharedh tag");
1698          // NO BREAK: fall through to next block to set many-valued tags
1699      default:
1700        result = mbImpl->tag_set_data(  sharedps_tag(), &ent, 1, remote_procs );
1701        RRA("Couldn't set sharedps tag");
1702        result = mbImpl->tag_set_data( sharedhs_tag(), &ent, 1, remote_hs );
1703        RRA("Couldn't set sharedhs tag");
1704        break;
1705    }
1706  }
1707  else if (remote_hs[i] != remote_handle) {
1708    assert(remote_hs[i] == invalid_handle);
1709    remote_hs[i] = remote_handle;
1710    if (n == 1) {
1711      result = mbImpl->tag_set_data( sharedh_tag(), &ent, 1, remote_hs );
1712      RRA("Couldn't set sharedh tag");
1713    }
1714    else {
1715      result = mbImpl->tag_set_data( sharedhs_tag(), &ent, 1, remote_hs );
1716      RRA("Couldn't set sharedhs tag");
1717    }
1718  }
1719 
1720  return MB_SUCCESS;
1721}
1722
1723MBErrorCode MBParallelComm::pack_range_map(MBRange &key_range, MBEntityHandle val_start,
1724                                           HandleMap &handle_map) 
1725{
1726  for (MBRange::const_pair_iterator key_it = key_range.const_pair_begin(); 
1727       key_it != key_range.const_pair_end(); key_it++) {
1728    int tmp_num = (*key_it).second - (*key_it).first + 1;
1729    handle_map.insert((*key_it).first, val_start, tmp_num);
1730    val_start += tmp_num;
1731  }
1732
1733  return MB_SUCCESS;
1734}
1735
1736MBErrorCode MBParallelComm::pack_sets(MBRange &entities,
1737                                      MBRange::const_iterator &start_rit,
1738                                      MBRange &whole_range,
1739                                      unsigned char *&buff_ptr,
1740                                      int &count,
1741                                      const bool just_count,
1742                                      const bool store_remote_handles,
1743                                      const int to_proc,
1744                                      MBRange &set_range,
1745                                      std::vector<MBRange> &set_ranges,
1746                                      std::vector<int> &set_sizes,
1747                                      std::vector<unsigned int> &options_vec)
1748{
1749    // SETS:
1750    // . #sets
1751    // . for each set:
1752    //   - options[#sets] (unsigned int)
1753    //   - if (unordered) set range
1754    //   - else if ordered
1755    //     . #ents in set
1756    //     . handles[#ents]
1757    //   - #parents
1758    //   - if (#parents) handles[#parents]
1759    //   - #children
1760    //   - if (#children) handles[#children]
1761 
1762    // now the sets; assume any sets the application wants to pass are in the entities list
1763  unsigned char *orig_buff_ptr = buff_ptr;
1764  MBErrorCode result;
1765
1766  if (just_count) {
1767    int ranges_size = 0, vecs_size = 0, tot_parch = 0;
1768   
1769    for (; start_rit != entities.end(); start_rit++) {
1770      set_range.insert(*start_rit);
1771   
1772      unsigned int options;
1773      result = mbImpl->get_meshset_options(*start_rit, options);
1774      RRA("Failed to get meshset options.");
1775      options_vec.push_back(options);
1776
1777      if (options & MESHSET_SET) {
1778          // range-based set; count the subranges
1779        set_ranges.push_back(MBRange());
1780        result = mbImpl->get_entities_by_handle(*start_rit, *set_ranges.rbegin());
1781        RRA("Failed to get set entities.");
1782
1783          // set range
1784        ranges_size += 2 * sizeof(MBEntityHandle) * num_subranges(*set_ranges.rbegin()) + 
1785          sizeof(int);
1786      }
1787      else if (options & MESHSET_ORDERED) {
1788          // just get the number of entities in the set
1789        int num_ents;
1790        result = mbImpl->get_number_entities_by_handle(*start_rit, num_ents);
1791        RRA("Failed to get number entities in ordered set.");
1792        set_sizes.push_back(num_ents);
1793
1794          // set vec
1795        vecs_size += sizeof(MBEntityHandle) * num_ents + sizeof(int);
1796      }
1797
1798        // get numbers of parents/children
1799      int num_par, num_ch;
1800      result = mbImpl->num_child_meshsets(*start_rit, &num_ch);
1801      RRA("Failed to get num children.");
1802
1803      result = mbImpl->num_parent_meshsets(*start_rit, &num_par);
1804      RRA("Failed to get num parents.");
1805
1806      tot_parch += num_ch + num_par;
1807     
1808    }
1809
1810      // num of sets
1811    count += sizeof(int);
1812   
1813      // options
1814    count += set_range.size() * sizeof(unsigned int);
1815
1816      // range, vector sizes
1817    count += ranges_size + vecs_size;
1818   
1819      // set children, parents
1820    count += 2 * set_range.size() * sizeof(int) + tot_parch * sizeof(MBEntityHandle);
1821
1822        // set handles
1823    if (!set_range.empty() && store_remote_handles)
1824      count += sizeof(int) + 2*sizeof(MBEntityHandle)*num_subranges(set_range);
1825
1826    whole_range.merge(set_range);
1827  }
1828  else {
1829   
1830      // set handle range
1831    PACK_INT(buff_ptr, set_range.size());
1832
1833      // option values
1834    if (!set_range.empty())
1835      PACK_VOID(buff_ptr, &options_vec[0], set_range.size()*sizeof(unsigned int));
1836
1837    std::vector<unsigned int>::const_iterator opt_it = options_vec.begin();
1838    std::vector<MBRange>::const_iterator rit = set_ranges.begin();
1839    std::vector<int>::const_iterator mem_it = set_sizes.begin();
1840    static std::vector<MBEntityHandle> members;
1841
1842    for (MBRange::const_iterator set_it = set_range.begin(); set_it != set_range.end(); 
1843         set_it++, opt_it++) {
1844      if ((*opt_it) & MESHSET_SET) {
1845          // pack entities as a range
1846        MBRange dum_range;
1847        result = get_remote_handles(store_remote_handles,
1848                                    (*rit), dum_range, to_proc,
1849                                    whole_range);
1850        RRA("Trouble getting remote handles for unordered set contents.");
1851        PACK_RANGE(buff_ptr, dum_range);
1852        rit++;
1853      }
1854      else if ((*opt_it) & MESHSET_ORDERED) {
1855          // pack entities as vector, with length
1856        PACK_INT(buff_ptr, *mem_it);
1857        members.clear();
1858        result = mbImpl->get_entities_by_handle(*set_it, members);
1859        RRA("Failed to get set entities.");
1860        result = get_remote_handles(store_remote_handles,
1861                                    &members[0], &members[0], 
1862                                    members.size(), to_proc,
1863                                    whole_range);
1864        RRA("Trouble getting remote handles for ordered set contents.");
1865        PACK_EH(buff_ptr, &members[0], *mem_it);
1866        mem_it++;
1867      }
1868    }
1869   
1870      // pack numbers of parents/children
1871    unsigned int tot_pch = 0;
1872    for (MBRange::const_iterator set_it = set_range.begin(); set_it != set_range.end(); 
1873         set_it++) {
1874        // pack parents
1875      int num_pch;
1876      result = mbImpl->num_parent_meshsets(*set_it, &num_pch);
1877      RRA("Failed to get num parents.");
1878      PACK_INT(buff_ptr, num_pch);
1879      tot_pch += num_pch;
1880      result = mbImpl->num_child_meshsets(*set_it, &num_pch);
1881      RRA("Failed to get num children.");
1882      PACK_INT(buff_ptr, num_pch);
1883      tot_pch += num_pch;
1884    }
1885
1886      // now pack actual parents/children
1887    members.clear();
1888    members.reserve(tot_pch);
1889    std::vector<MBEntityHandle> tmp_pch;
1890    for (MBRange::const_iterator set_it = set_range.begin(); set_it != set_range.end(); 
1891         set_it++) {
1892      result = mbImpl->get_parent_meshsets(*set_it, tmp_pch);
1893      RRA("Failed to get parents.");
1894      std::copy(tmp_pch.begin(), tmp_pch.end(), std::back_inserter(members));
1895      tmp_pch.clear();
1896      result = mbImpl->get_child_meshsets(*set_it, tmp_pch);
1897      RRA("Failed to get children.");
1898      std::copy(tmp_pch.begin(), tmp_pch.end(), std::back_inserter(members));
1899      tmp_pch.clear();
1900    }
1901    assert(members.size() == tot_pch);
1902    if (!members.empty()) {
1903      result = get_remote_handles(store_remote_handles,
1904                                  &members[0], &members[0], 
1905                                  members.size(), to_proc,
1906                                  whole_range);
1907      RRA("Trouble getting remote handles for set parent/child sets.");
1908#ifndef NDEBUG
1909        // check that all handles are either sets or maxtype
1910      for (unsigned int __j = 0; __j < members.size(); __j++)
1911        assert((TYPE_FROM_HANDLE(members[__j]) == MBMAXTYPE &&
1912                ID_FROM_HANDLE(members[__j]) < (int)whole_range.size()) ||
1913               TYPE_FROM_HANDLE(members[__j]) == MBENTITYSET);
1914#endif       
1915      PACK_EH(buff_ptr, &members[0], members.size());
1916    }
1917   
1918    // pack the handles
1919    if (store_remote_handles && !set_range.empty())
1920      PACK_RANGE(buff_ptr, set_range);
1921
1922    count += buff_ptr - orig_buff_ptr;
1923  }
1924
1925  if (debug_packing) std::cerr << std::endl << "Done packing sets." << std::endl;
1926
1927  return MB_SUCCESS;
1928}
1929
1930MBErrorCode MBParallelComm::unpack_sets(unsigned char *&buff_ptr,
1931                                        MBRange &entities,
1932                                        const bool store_remote_handles,
1933                                        const int from_proc)
1934{
1935 
1936    // now the sets; assume any sets the application wants to pass are in the entities list
1937  MBErrorCode result;
1938
1939  MBRange new_sets;
1940  int num_sets;
1941  UNPACK_INT(buff_ptr, num_sets);
1942
1943  if (!num_sets) return MB_SUCCESS;
1944         
1945  std::vector<MBEntityHandle> members;
1946  int num_ents;
1947  std::vector<unsigned int> options_vec(num_sets);
1948      // option value
1949  if (num_sets)
1950    UNPACK_VOID(buff_ptr, &options_vec[0], num_sets*sizeof(unsigned int));
1951
1952    // create sets
1953  int i;
1954  MBRange::const_iterator rit;
1955  for (i = 0; i < num_sets; i++) {
1956   
1957      // create the set
1958    MBEntityHandle set_handle;
1959    result = mbImpl->create_meshset(options_vec[i], set_handle);
1960    RRA("Failed to create set in unpack.");
1961
1962    // make sure new sets handles are monotonically increasing
1963    assert(set_handle > *new_sets.rbegin());
1964
1965    new_sets.insert(set_handle);
1966  }
1967
1968  entities.merge(new_sets);
1969 
1970  for (rit = new_sets.begin(), i = 0; rit != new_sets.end(); rit++, i++) {
1971    if (options_vec[i] & MESHSET_SET) {
1972        // unpack entities as a range
1973      MBRange set_range, tmp_range;
1974      UNPACK_RANGE(buff_ptr, tmp_range);
1975      result = get_local_handles(tmp_range, set_range, entities);     
1976      RRA("Failed to get local handles for unordered set contents.");
1977      result = mbImpl->add_entities(*rit, set_range);
1978      RRA("Failed to add ents to unordered set in unpack.");
1979    }
1980    else if (options_vec[i] & MESHSET_ORDERED) {
1981        // unpack entities as vector, with length
1982      UNPACK_INT(buff_ptr, num_ents);
1983      members.resize(num_ents);
1984      if (num_ents) UNPACK_EH(buff_ptr, &members[0], num_ents);
1985      result = get_local_handles(&members[0], num_ents, entities);
1986      RRA("Failed to get local handles for ordered set contents.");
1987      result = mbImpl->add_entities(*rit, &members[0], num_ents);
1988      RRA("Failed to add ents to ordered set in unpack.");
1989    }
1990  }
1991
1992  std::vector<int> num_pch(2*new_sets.size());
1993  std::vector<int>::iterator vit;
1994  int tot_pch = 0;
1995  for (vit = num_pch.begin(); vit != num_pch.end(); vit++) {
1996    UNPACK_INT(buff_ptr, *vit);
1997    tot_pch += *vit;
1998  }
1999 
2000  members.resize(tot_pch);
2001  UNPACK_EH(buff_ptr, &members[0], tot_pch);
2002  result = get_local_handles(&members[0], tot_pch, entities);
2003  RRA("Couldn't get local handle for parent/child sets.");
2004
2005  int num = 0;
2006  MBEntityHandle *mem_ptr = &members[0];
2007  for (rit = new_sets.begin(); rit != new_sets.end(); rit++) {
2008      // unpack parents/children
2009    int num_par = num_pch[num++], num_child = num_pch[num++];
2010    if (num_par+num_child) {
2011      for (i = 0; i < num_par; i++) {
2012        assert(0 != mem_ptr[i]);
2013        result = mbImpl->add_parent_meshset(*rit, mem_ptr[i]);
2014        RRA("Failed to add parent to set in unpack.");
2015      }
2016      mem_ptr += num_par;
2017      for (i = 0; i < num_child; i++) {
2018        assert(0 != mem_ptr[i]);
2019        result = mbImpl->add_child_meshset(*rit, mem_ptr[i]);
2020        RRA("Failed to add child to set in unpack.");
2021      }
2022      mem_ptr += num_child;
2023    }
2024  }
2025
2026    // unpack source handles
2027  MBRange dum_range;
2028  if (store_remote_handles && !new_sets.empty()) {
2029    UNPACK_RANGE(buff_ptr, dum_range);
2030    result = set_remote_data(new_sets, dum_range, from_proc);
2031    RRA("Couldn't set sharing data for sets");
2032  }
2033
2034  if (debug_packing) std::cerr << std::endl << "Done unpacking sets." << std::endl;
2035
2036  return MB_SUCCESS;
2037}
2038
2039MBErrorCode MBParallelComm::pack_adjacencies(MBRange &entities,
2040                                             MBRange::const_iterator &start_rit,
2041                                             MBRange &whole_range,
2042                                             unsigned char *&buff_ptr,
2043                                             int &count,
2044                                             const bool just_count,
2045                                             const bool store_handles,
2046                                             const int to_proc)
2047{
2048  return MB_FAILURE;
2049}
2050
2051MBErrorCode MBParallelComm::unpack_adjacencies(unsigned char *&buff_ptr,
2052                                               MBRange &entities,
2053                                               const bool store_handles,
2054                                               const int from_proc)
2055{
2056  return MB_FAILURE;
2057}
2058
2059MBErrorCode MBParallelComm::pack_tags(MBRange &entities,
2060                                      MBRange::const_iterator &start_rit,
2061                                      const MBRange &whole_range,
2062                                      unsigned char *&buff_ptr,
2063                                      int &count,
2064                                      const bool just_count,
2065                                      const bool store_remote_handles,
2066                                      const int to_proc,
2067                                      const std::vector<MBTag> &all_tags,
2068                                      const std::vector<MBRange> &tag_ranges)
2069{
2070    // get all the tags
2071
2072  MBErrorCode result;
2073  std::vector<MBTag>::const_iterator tag_it;
2074  std::vector<MBRange>::const_iterator rit;
2075
2076  if (just_count) {
2077   
2078    for (tag_it = all_tags.begin(), rit = tag_ranges.begin(); 
2079         tag_it != all_tags.end(); tag_it++, rit++) {
2080
2081      result = packed_tag_size( *tag_it, *rit, count );
2082      if (MB_SUCCESS != result)
2083        return result;
2084    }
2085   
2086      // number of tags
2087    count += sizeof(int);
2088  }
2089
2090  else {
2091
2092    PACK_INT(buff_ptr, all_tags.size());
2093    count += sizeof(int);
2094   
2095    for (tag_it = all_tags.begin(), rit = tag_ranges.begin(); 
2096         tag_it != all_tags.end(); tag_it++, rit++) {
2097         
2098   
2099      result = pack_tag( *tag_it, *tag_it, *rit, whole_range, buff_ptr, 
2100                         count, store_remote_handles, to_proc );
2101      if (MB_SUCCESS != result)
2102        return result;
2103    }
2104  }
2105 
2106  if (debug_packing) std::cerr << std::endl << "Done packing tags." << std::endl;
2107
2108  return MB_SUCCESS;
2109}
2110         
2111
2112MBErrorCode MBParallelComm::packed_tag_size( MBTag tag,
2113                                             const MBRange &tagged_entities,
2114                                             int &count )
2115{
2116    // for dense tags, compute size assuming all entities have that tag
2117    // for sparse tags, get number of entities w/ that tag to compute size
2118
2119  std::vector<int> var_len_sizes;
2120  std::vector<const void*> var_len_values;
2121   
2122  const TagInfo *tinfo = tagServer->get_tag_info(tag);
2123    // default value
2124  count += sizeof(int);
2125  if (NULL != tinfo->default_value()) 
2126    count += tinfo->default_value_size();
2127
2128    // size, type, data type
2129  count += 3*sizeof(int);
2130
2131    // name
2132  count += sizeof(int);
2133  count += tinfo->get_name().size();
2134
2135    // range of tag
2136  count += sizeof(int) + tagged_entities.size() * sizeof(MBEntityHandle);
2137
2138  if (tinfo->get_size() == MB_VARIABLE_LENGTH) {
2139    const int num_ent = tagged_entities.size();
2140      // send a tag size for each entity
2141    count += num_ent * sizeof(int);
2142      // send tag data for each entity
2143    var_len_sizes.resize( num_ent );
2144    var_len_values.resize( num_ent );
2145    MBErrorCode result = tagServer->get_data( tag,
2146                                              tagged_entities, 
2147                                              &var_len_values[0], 
2148                                              &var_len_sizes[0] );
2149    RRA("Failed to get lenghts of variable-length tag values.");
2150    count += std::accumulate( var_len_sizes.begin(), var_len_sizes.end(), 0 );
2151  }
2152  else {
2153      // tag data values for range or vector
2154    count += tagged_entities.size() * tinfo->get_size();
2155  }
2156 
2157  return MB_SUCCESS;
2158}
2159
2160
2161MBErrorCode MBParallelComm::pack_tag( MBTag src_tag,
2162                                      MBTag dst_tag,
2163                                      const MBRange &tagged_entites,
2164                                      const MBRange &whole_range,
2165                                      unsigned char *&buff_ptr,
2166                                      int &count,
2167                                      const bool store_remote_handles,
2168                                      const int to_proc )
2169{
2170  unsigned char *orig_buff_ptr = buff_ptr;
2171  MBErrorCode result;
2172  std::vector<int> var_len_sizes;
2173  std::vector<const void*> var_len_values;
2174
2175  const TagInfo* tinfo = tagServer->get_tag_info(src_tag);
2176  if (!tinfo)
2177    return MB_TAG_NOT_FOUND;
2178   
2179  const TagInfo* dst_tinfo;
2180  if (src_tag == dst_tag) {
2181    dst_tinfo = tinfo;
2182  }
2183  else {
2184    dst_tinfo = tagServer->get_tag_info(dst_tag);
2185    if (!dst_tinfo)
2186      return MB_TAG_NOT_FOUND;
2187    if (dst_tinfo->get_size() != tinfo->get_size())
2188      return MB_TYPE_OUT_OF_RANGE;
2189    if (dst_tinfo->get_data_type() != tinfo->get_data_type() && 
2190        dst_tinfo->get_data_type() != MB_TYPE_OPAQUE &&
2191            tinfo->get_data_type() != MB_TYPE_OPAQUE)
2192      return MB_TYPE_OUT_OF_RANGE;
2193  }
2194   
2195   
2196
2197    // size, type, data type
2198  PACK_INT(buff_ptr, tinfo->get_size());
2199  MBTagType this_type;
2200  result = mbImpl->tag_get_type(dst_tag, this_type);
2201  PACK_INT(buff_ptr, (int)this_type);
2202  PACK_INT(buff_ptr, (int)(tinfo->get_data_type()));
2203
2204    // default value
2205  if (NULL == tinfo->default_value()) {
2206    PACK_INT(buff_ptr, 0);
2207  }
2208  else {
2209    PACK_BYTES(buff_ptr, tinfo->default_value(), tinfo->default_value_size());
2210  }
2211
2212    // name
2213  PACK_BYTES(buff_ptr, dst_tinfo->get_name().c_str(), dst_tinfo->get_name().size());
2214
2215#ifdef DEBUG_PACKING
2216std::cerr << "Packing tag \"" << tinfo->get_name() << "\"";
2217if (tinfo != dst_tinfo)
2218  std::cerr << " (as tag \"" << dst_tinfo->get_name() << "\")";
2219std::cerr << std::endl;
2220#endif   
2221    // pack entities
2222  PACK_INT(buff_ptr, tagged_entites.size());
2223  result = get_remote_handles(store_remote_handles,
2224                              tagged_entites, (MBEntityHandle*)buff_ptr, to_proc,
2225                              whole_range);
2226#ifdef DEBUG_PACKING
2227  if (MB_SUCCESS != result) {
2228    std::cerr << "Trouble getting remote handles for tagged entities:" << std::endl;
2229    tagged_entites.print("  ");
2230  }
2231#else
2232  RRA("Trouble getting remote handles for tagged entities.");
2233#endif
2234
2235  buff_ptr += tagged_entites.size() * sizeof(MBEntityHandle);
2236
2237  const size_t num_ent = tagged_entites.size();
2238  if (tinfo->get_size() == MB_VARIABLE_LENGTH) {
2239    var_len_sizes.resize( num_ent, 0 );
2240    var_len_values.resize( num_ent, 0 );
2241    result = mbImpl->tag_get_data(src_tag, tagged_entites, &var_len_values[0], 
2242                                  &var_len_sizes[0] );
2243    RRA("Failed to get variable-length tag data in pack_tags.");
2244    PACK_INTS(buff_ptr, &var_len_sizes[0], num_ent);
2245    for (unsigned int i = 0; i < num_ent; ++i)
2246      PACK_VOID(buff_ptr, var_len_values[i], var_len_sizes[i]);
2247  }
2248  else {
2249    result = mbImpl->tag_get_data(src_tag, tagged_entites, buff_ptr);
2250    RRA("Failed to get tag data in pack_tags.");
2251    buff_ptr += num_ent * tinfo->get_size();
2252    PC(num_ent*tinfo->get_size(), " void");
2253  }
2254
2255  count += buff_ptr - orig_buff_ptr;
2256
2257  return MB_SUCCESS;
2258}
2259
2260MBErrorCode MBParallelComm::get_tag_send_list( const MBRange& whole_range,
2261                                               std::vector<MBTag>& all_tags,
2262                                               std::vector<MBRange>& tag_ranges )
2263{
2264  std::vector<MBTag> tmp_tags;
2265  MBErrorCode result = tagServer->get_tags(tmp_tags);
2266  RRA("Failed to get tags in pack_tags.");
2267
2268  std::vector<MBTag>::iterator tag_it;
2269  for (tag_it = tmp_tags.begin(); tag_it != tmp_tags.end(); tag_it++) {
2270    std::string tag_name;
2271    result = mbImpl->tag_get_name(*tag_it, tag_name);
2272    if (tag_name.c_str()[0] == '_' && tag_name.c_str()[1] == '_')
2273      continue;
2274
2275    MBRange tmp_range;
2276    result = tagServer->get_entities(*tag_it, tmp_range);
2277    RRA("Failed to get entities for tag in pack_tags.");
2278    tmp_range = tmp_range.intersect(whole_range);
2279
2280    if (tmp_range.empty()) continue;
2281       
2282      // ok, we'll be sending this tag
2283    all_tags.push_back( *tag_it );
2284    tag_ranges.push_back( MBRange() );
2285    tag_ranges.back().swap( tmp_range );
2286  }
2287 
2288  return MB_SUCCESS;
2289}
2290
2291
2292
2293MBErrorCode MBParallelComm::unpack_tags(unsigned char *&buff_ptr,
2294                                        MBRange &entities,
2295                                        const bool store_remote_handles,
2296                                        const int from_proc)
2297{
2298    // tags
2299    // get all the tags
2300    // for dense tags, compute size assuming all entities have that tag
2301    // for sparse tags, get number of entities w/ that tag to compute size
2302
2303  MBErrorCode result;
2304 
2305  int num_tags;
2306  UNPACK_INT(buff_ptr, num_tags);
2307  std::vector<MBEntityHandle> tag_ents;
2308  std::vector<const void*> var_len_vals;
2309  std::vector<int> var_lengths;
2310
2311  for (int i = 0; i < num_tags; i++) {
2312   
2313        // tag handle
2314    MBTag tag_handle;
2315
2316      // size, data type
2317    int tag_size, tag_data_type, tag_type;
2318    UNPACK_INT(buff_ptr, tag_size);
2319    UNPACK_INT(buff_ptr, tag_type);
2320    UNPACK_INT(buff_ptr, tag_data_type);
2321     
2322      // default value
2323    int def_val_size;
2324    UNPACK_INT(buff_ptr, def_val_size);
2325    void *def_val_ptr = NULL;
2326    if (def_val_size) {
2327      def_val_ptr = buff_ptr;
2328      buff_ptr += def_val_size;
2329      UPC(tag_size, " void");
2330    }
2331   
2332      // name
2333    int name_len;
2334    UNPACK_INT(buff_ptr, name_len);
2335    std::string tag_name( reinterpret_cast<char*>(buff_ptr), name_len );
2336    buff_ptr += name_len;
2337    UPC(64, " chars");
2338#ifdef DEBUG_PACKING
2339    std::cerr << "Unpacking tag " << tag_name << std::endl;
2340#endif   
2341
2342      // create the tag
2343    if (tag_size == MB_VARIABLE_LENGTH) 
2344      result = mbImpl->tag_create_variable_length( tag_name.c_str(), (MBTagType)tag_type,
2345                                                   (MBDataType)tag_data_type, tag_handle,
2346                                                   def_val_ptr, def_val_size );
2347    else
2348      result = mbImpl->tag_create(tag_name.c_str(), tag_size, (MBTagType) tag_type, 
2349                                  (MBDataType) tag_data_type, tag_handle,
2350                                  def_val_ptr);
2351    if (MB_ALREADY_ALLOCATED == result) {
2352        // already allocated tag, check to make sure it's the same size, type, etc.
2353      const TagInfo *tag_info = tagServer->get_tag_info(tag_name.c_str());
2354      MBTagType this_type;
2355      result = mbImpl->tag_get_type(tag_handle, this_type);
2356      if (tag_size != tag_info->get_size() ||
2357          tag_type != this_type ||
2358          tag_data_type != tag_info->get_data_type() ||
2359          (def_val_ptr && !tag_info->default_value()) ||
2360          (!def_val_ptr && tag_info->default_value())) {
2361        RRA("Didn't get correct tag info when unpacking tag.");
2362      }
2363    }
2364    else if (MB_SUCCESS != result) return result;
2365
2366      // go through handle vec (in buffer) and convert to local handles in-place
2367    int num_ents;
2368    UNPACK_INT(buff_ptr, num_ents);
2369    MBEntityHandle *handle_vec = (MBEntityHandle*)buff_ptr;
2370    result = get_local_handles(handle_vec, num_ents, entities);
2371    RRA("Failed to get local handles for tagged entities.");
2372    buff_ptr += num_ents * sizeof(MBEntityHandle);
2373
2374      // if it's a handle type, also convert tag vals in-place in buffer
2375    if (MB_TYPE_HANDLE == tag_type) {
2376      MBEntityHandle *val_vec = (MBEntityHandle*)buff_ptr;
2377      result = get_local_handles(val_vec, num_ents, entities);
2378      RRA("Failed to get local handles for tag vals.");
2379    }
2380
2381    if (tag_size == MB_VARIABLE_LENGTH) {
2382        // Be careful of alignment here.  If the integers are aligned
2383        // in the buffer, we can use them directly.  Otherwise we must
2384        // copy them.
2385      const int* size_arr;
2386      if (((size_t)buff_ptr)%4) {
2387        var_lengths.resize( num_ents );
2388        memcpy( &var_lengths[0], buff_ptr, num_ents*sizeof(int) );
2389        size_arr = &var_lengths[0];
2390      }
2391      else {
2392        size_arr = reinterpret_cast<const int*>(buff_ptr);
2393      }
2394      buff_ptr += sizeof(int) * num_ents;
2395      UPC(sizeof(int) * num_ents, " void");
2396     
2397        // get pointers into buffer for each tag value
2398      var_len_vals.resize(num_ents);
2399      for (std::vector<MBEntityHandle>::size_type i = 0; 
2400           i < (std::vector<MBEntityHandle>::size_type) num_ents; ++i) {
2401        var_len_vals[i] = buff_ptr;
2402        buff_ptr += size_arr[i];
2403        UPC(size_arr[i], " void");
2404      }
2405      result = mbImpl->tag_set_data( tag_handle, handle_vec, num_ents,
2406                                     &var_len_vals[0], size_arr );
2407      RRA("Trouble setting tag data when unpacking variable-length tag.");
2408    }
2409    else {
2410      result = mbImpl->tag_set_data(tag_handle, handle_vec,
2411                                    num_ents, buff_ptr);
2412      RRA("Trouble setting range-based tag data when unpacking tag.");
2413      buff_ptr += num_ents * tag_size;
2414      UPC(num_ents * tag_size, " void");
2415    }
2416  }
2417 
2418  if (debug_packing) std::cerr << std::endl << "Done unpacking tags." << std::endl;
2419
2420  return MB_SUCCESS;
2421}
2422
2423MBErrorCode MBParallelComm::resolve_shared_ents(MBEntityHandle this_set,
2424                                                int resolve_dim,
2425                                                int shared_dim) 
2426{
2427  MBErrorCode result;
2428  MBRange proc_ents;
2429      // get the entities in the partition sets
2430  for (MBRange::iterator rit = partitionSets.begin(); rit != partitionSets.end(); rit++) {
2431    MBRange tmp_ents;
2432    result = mbImpl->get_entities_by_handle(*rit, tmp_ents, true);
2433    if (MB_SUCCESS != result) return result;
2434    proc_ents.merge(tmp_ents);
2435  }
2436
2437    // resolve dim is maximal dim of entities in proc_ents
2438  if (-1 == resolve_dim) {
2439    resolve_dim = mbImpl->dimension_from_handle(*proc_ents.rbegin()); 
2440    RRA("Couldn't get dimension.");
2441   
2442  }
2443
2444    // proc_ents should all be of same dimension
2445  if (resolve_dim > shared_dim &&
2446      mbImpl->dimension_from_handle(*proc_ents.rbegin()) !=
2447      mbImpl->dimension_from_handle(*proc_ents.begin())) {
2448    MBRange::iterator lower = proc_ents.lower_bound(MBCN::TypeDimensionMap[0].first),
2449      upper = proc_ents.upper_bound(MBCN::TypeDimensionMap[resolve_dim-1].second);
2450    proc_ents.erase(lower, upper);
2451  }
2452 
2453    // must call even if we don't have any entities, to make sure
2454    // collective comm'n works
2455  return resolve_shared_ents(this_set, proc_ents, resolve_dim, shared_dim);
2456}
2457 
2458MBErrorCode MBParallelComm::resolve_shared_ents(MBEntityHandle this_set,
2459                                                MBRange &proc_ents,
2460                                                int resolve_dim,
2461                                                int shared_dim) 
2462{
2463  MBErrorCode result;
2464  if (debug) std::cerr << "Resolving shared entities." << std::endl;
2465
2466  if (-1 == shared_dim) {
2467    if (0 == resolve_dim) {
2468      result = mbImpl->get_dimension(shared_dim); 
2469      RRA("Couldn't get dimension.");
2470    }
2471    else shared_dim = mbImpl->dimension_from_handle(*proc_ents.begin())-1;
2472  }
2473  assert(shared_dim >= 0 && resolve_dim >= 0);
2474 
2475    // get the skin entities by dimension
2476  MBRange skin_ents[4];
2477  std::vector<int> gid_data;
2478  std::vector<MBEntityHandle> handle_vec;
2479  int skin_dim;
2480
2481    // get the entities to be skinned
2482  if (resolve_dim < shared_dim) {
2483      // for vertex-based partition, it's the elements adj to the vertices
2484    result = mbImpl->get_adjacencies(proc_ents, shared_dim,
2485                                     false, skin_ents[resolve_dim],
2486                                     MBInterface::UNION);
2487    RRA("Failed getting skinned entities.");
2488    skin_dim = shared_dim-1;
2489  }
2490  else {
2491      // for element-based partition, it's just the elements
2492    skin_ents[resolve_dim] = proc_ents;
2493    skin_dim = resolve_dim-1;
2494  }
2495
2496    // find the skin
2497  MBSkinner skinner(mbImpl);
2498  result = skinner.find_skin(skin_ents[skin_dim+1], skin_ents[skin_dim],
2499                             skin_ents[skin_dim], true);
2500  RRA("Failed to find skin.");
2501  if (debug) std::cerr << "Found skin, now resolving." << std::endl;
2502
2503    // get entities adjacent to skin ents from shared_dim down to
2504    // zero; don't create them if they don't exist already
2505  for (int this_dim = skin_dim-1; this_dim >= 0; this_dim--) {
2506    result = mbImpl->get_adjacencies(skin_ents[skin_dim], this_dim,
2507                                     false, skin_ents[this_dim],
2508                                     MBInterface::UNION);
2509    RRA("Failed getting skin adjacencies.");
2510  }
2511
2512    // resolve shared vertices first
2513
2514    // global id tag
2515  MBTag gid_tag; int def_val = -1;
2516  result = mbImpl->tag_create(GLOBAL_ID_TAG_NAME, sizeof(int),
2517                              MB_TAG_DENSE, MB_TYPE_INTEGER, gid_tag,
2518                              &def_val, true);
2519  if (MB_FAILURE == result) return result;
2520
2521  else if (MB_ALREADY_ALLOCATED != result) {
2522      // just created it, so we need global ids
2523    result = assign_global_ids(0, skin_dim+1);
2524    RRA("Failed assigning global ids.");
2525  }
2526
2527    // store index in temp tag; reuse gid_data
2528  gid_data.resize(2*skin_ents[0].size());
2529  int idx = 0;
2530  for (MBRange::iterator rit = skin_ents[0].begin(); 
2531       rit != skin_ents[0].end(); rit++) 
2532    gid_data[idx] = idx, idx++;
2533  MBTag idx_tag;
2534  result = mbImpl->tag_create("__idx_tag", sizeof(int), MB_TAG_DENSE,
2535                              MB_TYPE_INTEGER, idx_tag, &def_val, true);
2536  if (MB_SUCCESS != result && MB_ALREADY_ALLOCATED != result) return result;
2537  result = mbImpl->tag_set_data(idx_tag, skin_ents[0], &gid_data[0]);
2538  RRA("Couldn't assign index tag.");
2539
2540    // get gids for skin ents in a vector, to pass to gs
2541  result = mbImpl->tag_get_data(gid_tag, skin_ents[0], &gid_data[0]);
2542  RRA("Couldn't get gid tag for skin vertices.");
2543
2544    // put handles in vector for passing to gs setup
2545  std::copy(skin_ents[0].begin(), skin_ents[0].end(), 
2546            std::back_inserter(handle_vec));
2547 
2548    // get a crystal router
2549  crystal_data *cd = procConfig.crystal_router();
2550 
2551    // get total number of entities; will overshoot highest global id, but
2552    // that's ok
2553  int num_total = 0, num_local;
2554  result = mbImpl->get_number_entities_by_dimension(0, 0, num_local);
2555  if (MB_SUCCESS != result) return result;
2556  int failure = MPI_Allreduce(&num_local, &num_total, 1,
2557                              MPI_INT, MPI_SUM, procConfig.proc_comm());
2558  if (failure) {
2559    result = MB_FAILURE;
2560    RRA("Allreduce for total number of shared ents failed.");
2561  }
2562 
2563    // call gather-scatter to get shared ids & procs
2564  gs_data *gsd;
2565  assert(sizeof(ulong_) == sizeof(MBEntityHandle));
2566  if (sizeof(int) != sizeof(ulong_)) {
2567    std::vector<long> lgid_data(gid_data.size());
2568    std::copy(gid_data.begin(), gid_data.end(), lgid_data.begin());
2569    gsd = gs_data_setup(skin_ents[0].size(), &lgid_data[0], 
2570                        (ulong_*)&handle_vec[0], 2, 1, 1, cd);
2571  }
2572  else {
2573    gsd = gs_data_setup(skin_ents[0].size(), (long*)&gid_data[0], 
2574                        (ulong_*)&handle_vec[0], 2, 1, 1, cd);
2575  }
2576 
2577  if (NULL == gsd) {
2578    result = MB_FAILURE;
2579    RRA("Couldn't create gs data.");
2580  }
2581
2582    // get shared proc tags
2583  MBTag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
2584  result = get_shared_proc_tags(sharedp_tag, sharedps_tag, 
2585                                sharedh_tag, sharedhs_tag, pstatus_tag);
2586  RRA("Couldn't get shared proc tags.");
2587 
2588    // load shared verts into a tuple, then sort by index
2589  tuple_list shared_verts;
2590  tuple_list_init_max(&shared_verts, 2, 0, 1, 0, 
2591                      skin_ents[0].size()*(MAX_SHARING_PROCS+1));
2592  unsigned int i = 0, j = 0;
2593  for (unsigned int p = 0; p < gsd->nlinfo->np; p++) 
2594    for (unsigned int np = 0; np < gsd->nlinfo->nshared[p]; np++) {
2595      shared_verts.vi[i++] = gsd->nlinfo->sh_ind[j];
2596      shared_verts.vi[i++] = gsd->nlinfo->target[p];
2597      shared_verts.vul[j] = gsd->nlinfo->ulabels[j];
2598      j++;
2599      shared_verts.n++;
2600    }
2601 
2602  int max_size = skin_ents[0].size()*(MAX_SHARING_PROCS+1);
2603  std::vector<int> sort_buffer(max_size);
2604  tuple_list_sort(&shared_verts, 0,(buffer*)&sort_buffer[0]);
2605
2606    // set sharing procs and handles tags on skin ents
2607  int maxp = -1;
2608  std::vector<int> sharing_procs(MAX_SHARING_PROCS);
2609  std::fill(sharing_procs.begin(), sharing_procs.end(), maxp);
2610  j = 0; i = 0;
2611
2612    // get ents shared by 1 or n procs
2613  std::map<std::vector<int>, MBRange> proc_nranges;
2614  MBRange proc_verts;
2615  result = mbImpl->get_adjacencies(proc_ents, 0, false, proc_verts,
2616                                   MBInterface::UNION);
2617  RRA("Couldn't get proc_verts.");
2618 
2619  result = tag_shared_verts(shared_verts, skin_ents,
2620                            proc_nranges, proc_verts);
2621  RRA("Trouble tagging shared verts.");
2622
2623    // get entities shared by 1 or n procs
2624  result = tag_shared_ents(resolve_dim, shared_dim, shared_verts, skin_ents,
2625                           proc_nranges);
2626  RRA("Trouble tagging shared entities.");
2627
2628  if (debug) {
2629    for (std::map<std::vector<int>, MBRange>::const_iterator mit = proc_nranges.begin();
2630         mit != proc_nranges.end(); mit++) {
2631      std::cout << "Iface: ";
2632      for (std::vector<int>::const_iterator vit = (mit->first).begin();
2633           vit != (mit->first).end(); vit++) std::cout << " " << *vit;
2634      std::cout << std::endl;
2635    }
2636  }
2637 
2638    // create the sets for each interface; store them as tags on
2639    // the interface instance
2640  MBRange iface_sets;
2641  result = create_interface_sets(proc_nranges, this_set, resolve_dim, shared_dim);
2642  RRA("Trouble creating iface sets.");
2643
2644    // resolve shared entity remote handles; implemented in ghost cell exchange
2645    // code because it's so similar
2646  result = exchange_ghost_cells(-1, -1, 0, true, true);
2647  RRA("Trouble resolving shared entity remote handles.");
2648
2649    // now set the shared/interface tag on non-vertex entities on interface
2650  result = tag_iface_entities();
2651  RRA("Failed to tag iface entities.");
2652
2653    // now build parent/child links for interface sets
2654  result = create_iface_pc_links();
2655  RRA("Trouble creating interface parent/child links.");
2656 
2657    // done
2658  return result;
2659}
2660
2661MBErrorCode MBParallelComm::tag_iface_entities() 
2662{
2663  MBRange all_ents, if_ents;
2664  MBErrorCode result;
2665  for (MBRange::iterator if_it = interfaceSets.begin(); if_it != interfaceSets.end(); if_it++) {
2666      // get all ents
2667    result = mbImpl->get_entities_by_handle(*if_it, if_ents);
2668    RRA("Trouble getting iface entities.");
2669  }
2670  std::vector<unsigned char> tvals(if_ents.size());
2671  result = mbImpl->tag_get_data(pstatus_tag(), if_ents, &tvals[0]);
2672  RRA("Failed to get pstatus tag values.");
2673 
2674  for (unsigned int i = 0; i < tvals.size(); i++)
2675    tvals[i] |= PSTATUS_INTERFACE;
2676 
2677  result = mbImpl->tag_set_data(pstatus_tag(), if_ents, &tvals[0]);
2678  RRA("Failed to set pstatus tag values.");
2679 
2680  return MB_SUCCESS;
2681}
2682
2683MBErrorCode MBParallelComm::set_pstatus_entities(MBRange &pstatus_ents,
2684                                                 unsigned char pstatus_val,
2685                                                 bool lower_dim_ents,
2686                                                 bool verts_too,
2687                                                 int operation) 
2688{
2689  std::vector<unsigned char> pstatus_vals(pstatus_ents.size());
2690  MBRange all_ents, *range_ptr = &pstatus_ents;
2691  MBErrorCode result;
2692  if (lower_dim_ents || verts_too) {
2693    all_ents = pstatus_ents;
2694    range_ptr = &all_ents;
2695    int start_dim = (lower_dim_ents ? mbImpl->dimension_from_handle(*pstatus_ents.rbegin())-1 : 0);
2696    for (; start_dim >= 0; start_dim--) {
2697      result = mbImpl->get_adjacencies(all_ents, start_dim, true, all_ents,
2698                                       MBInterface::UNION);
2699      RRA(" ");
2700    }
2701  }
2702  if (MBInterface::UNION == operation) {
2703    result = mbImpl->tag_get_data(pstatus_tag(), *range_ptr, &pstatus_vals[0]);
2704    RRA("Couldn't get pstatus tag value.");
2705    for (unsigned int i = pstatus_ents.size()-1; i >= 0; i--)
2706      pstatus_vals[i] |= pstatus_val;
2707  }
2708  else {
2709    for (unsigned int i = pstatus_ents.size()-1; i >= 0; i--)
2710      pstatus_vals[i] = pstatus_val;
2711  }
2712  result = mbImpl->tag_set_data(pstatus_tag(), *range_ptr, &pstatus_vals[0]);
2713  RRA("Couldn't set pstatus tag value.");
2714 
2715  return MB_SUCCESS;
2716}
2717 
2718MBErrorCode MBParallelComm::create_interface_sets(std::map<std::vector<int>, MBRange> &proc_nranges,
2719                                                  MBEntityHandle this_set,
2720                                                  int resolve_dim, int shared_dim) 
2721{
2722  if (proc_nranges.empty()) return MB_SUCCESS;
2723 
2724  int proc_ids[MAX_SHARING_PROCS];
2725  MBTag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
2726  MBErrorCode result = get_shared_proc_tags(sharedp_tag, sharedps_tag, 
2727                                            sharedh_tag, sharedhs_tag,
2728                                            pstatus_tag);
2729  RRA("Trouble getting shared proc tags in create_interface_sets.");
2730  MBRange::iterator rit;
2731
2732    // create interface sets, tag them, and tag their contents with iface set tag
2733  std::vector<MBEntityHandle> tag_vals;
2734  std::vector<unsigned char> pstatus;
2735  for (std::map<std::vector<int>,MBRange>::iterator mit = proc_nranges.begin();
2736       mit != proc_nranges.end(); mit++) {
2737      // create the set
2738    MBEntityHandle new_set;
2739    result = mbImpl->create_meshset(MESHSET_SET, new_set); 
2740    RRA("Failed to create interface set.");
2741    interfaceSets.insert(new_set);
2742
2743      // add entities
2744    result = mbImpl->add_entities(new_set, mit->second); 
2745    RRA("Failed to add entities to interface set.");
2746      // tag set with the proc rank(s)
2747    if (mit->first.size() == 1)
2748      result = mbImpl->tag_set_data(sharedp_tag, &new_set, 1, 
2749                                    &(mit->first)[0]); 
2750    else {
2751      // pad tag data out to MAX_SHARING_PROCS with -1
2752      assert( mit->first.size() <= MAX_SHARING_PROCS );
2753      std::copy( mit->first.begin(), mit->first.end(), proc_ids );
2754      std::fill( proc_ids + mit->first.size(), proc_ids + MAX_SHARING_PROCS, -1 );
2755      result = mbImpl->tag_set_data(sharedps_tag, &new_set, 1, proc_ids );
2756    }
2757    RRA("Failed to tag interface set with procs.");
2758   
2759      // get the owning proc, then set the pstatus tag on iface set
2760    int min_proc = (mit->first)[0];
2761    unsigned char pval = (PSTATUS_SHARED | PSTATUS_INTERFACE);
2762    if (min_proc < (int) procConfig.proc_rank()) pval |= PSTATUS_NOT_OWNED;
2763    result = mbImpl->tag_set_data(pstatus_tag, &new_set, 1, &pval); 
2764    RRA("Failed to tag interface set with pstatus.");
2765
2766      // tag the entities with the same thing
2767    pstatus.clear();
2768    pstatus.resize(mit->second.size(), pval);
2769    result = mbImpl->tag_set_data(pstatus_tag, mit->second, &pstatus[0]); 
2770    RRA("Failed to tag interface set entities with pstatus.");
2771  }
2772
2773  return MB_SUCCESS;
2774}
2775
2776MBErrorCode MBParallelComm::create_iface_pc_links() 
2777{
2778    // now that we've resolved the entities in the iface sets,
2779    // set parent/child links between the iface sets
2780
2781    // first tag all entities in the iface sets
2782  MBTag tmp_iface_tag;
2783  MBEntityHandle tmp_iface_set = 0;
2784  MBErrorCode result = mbImpl->tag_create("__tmp_iface", sizeof(MBEntityHandle),
2785                                          MB_TAG_DENSE, MB_TYPE_HANDLE,
2786                                          tmp_iface_tag, &tmp_iface_set);
2787  if (MB_ALREADY_ALLOCATED != result && MB_SUCCESS != result) 
2788    RRA("Failed to create temporary iface set tag.");
2789
2790  MBRange iface_ents;
2791  std::vector<MBEntityHandle> tag_vals;
2792  MBRange::iterator rit;
2793 
2794  for (rit = interfaceSets.begin(); rit != interfaceSets.end(); rit++) {
2795      // tag entities with interface set
2796    iface_ents.clear();
2797    result = mbImpl->get_entities_by_handle(*rit, iface_ents);
2798    RRA("Couldn't get entities in iface set.");
2799   
2800    if (iface_ents.empty()) continue;
2801   
2802    tag_vals.resize(iface_ents.size());
2803    std::fill(tag_vals.begin(), tag_vals.end(), *rit);
2804    result = mbImpl->tag_set_data(tmp_iface_tag, iface_ents, &tag_vals[0]); 
2805    RRA("Failed to tag iface entities with interface set.");
2806  }
2807 
2808    // now go back through interface sets and add parent/child links
2809  MBRange tmp_ents2;
2810  for (int d = 2; d >= 0; d--) {
2811    for (rit = interfaceSets.begin(); rit != interfaceSets.end(); rit++) {
2812        // get entities on this interface
2813      iface_ents.clear();
2814      result = mbImpl->get_entities_by_handle(*rit, iface_ents, true);
2815      RRA("Couldn't get entities by dimension.");
2816      if (iface_ents.empty() ||
2817          mbImpl->dimension_from_handle(*iface_ents.rbegin()) != d) continue;
2818
2819        // get higher-dimensional entities and their interface sets
2820      result = mbImpl->get_adjacencies(&(*iface_ents.begin()), 1, d+1,
2821                                       false, tmp_ents2);
2822      RRA("Couldn't get adjacencies for interface sets.");
2823      tag_vals.resize(tmp_ents2.size());
2824      result = mbImpl->tag_get_data(tmp_iface_tag, tmp_ents2, &tag_vals[0]);
2825      RRA("Couldn't get iface set tag for interface sets.");
2826     
2827        // go through and for any on interface make it a parent
2828      MBEntityHandle last_set = 0;
2829      for (unsigned int i = 0; i < tag_vals.size(); i++) {
2830        if (tag_vals[i] && tag_vals[i] != last_set) {
2831          result = mbImpl->add_parent_child(tag_vals[i], *rit);
2832          RRA("Couldn't add parent/child link for interface set.");
2833          last_set = tag_vals[i];
2834        }
2835      }
2836    }
2837  }
2838 
2839    // delete the temporary tag
2840  result = mbImpl->tag_delete(tmp_iface_tag);
2841  RRA("Couldn't delete tmp iface tag.");
2842
2843  return MB_SUCCESS;
2844}
2845
2846MBErrorCode MBParallelComm::tag_shared_ents(int resolve_dim,
2847        Â