Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_Directory.hpp
Go to the documentation of this file.
1 /*
2  * @HEADER
3  *
4  * ***********************************************************************
5  *
6  * Zoltan2 Directory for Load-balancing, Partitioning, Ordering and Coloring
7  * Copyright 2012 Sandia Corporation
8  *
9  * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10  * the U.S. Government retains certain rights in this software.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are
14  * met:
15  *
16  * 1. Redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer.
18  *
19  * 2. Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the distribution.
22  *
23  * 3. Neither the name of the Corporation nor the names of the
24  * contributors may be used to endorse or promote products derived from
25  * this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  * Questions? Contact Karen Devine kddevin@sandia.gov
40  * Erik Boman egboman@sandia.gov
41  *
42  * ***********************************************************************
43  *
44  * @HEADER
45  */
46 
47 #ifndef ZOLTAN2_DIRECTORY_H_
48 #define ZOLTAN2_DIRECTORY_H_
49 
50 #include <Teuchos_DefaultComm.hpp> // currently using Teuchos comm throughout
51 #include <Teuchos_CommHelpers.hpp>
52 
53 #ifndef HAVE_MPI
54 // support mpi serial - directory currently has a mix of Teuchos mpi commands
55 // and original MPI commands so as this gets better organized the serial support
56 // can be handled more naturally. Currently the tests call an MPI_Init for serial
57 // so this can all work. I've mostly added the serial support just to make
58 // debugging easier.
59 #include <mpi.h>
60 #endif
61 
62 #include <Kokkos_UnorderedMap.hpp> // unordered map stores the local nodes
63 
64 namespace Zoltan2 {
65 
66 // The new Kokkos mode maps over the gid using unordered map
67 // Originally was thinking we don't want ptrs here and want the user data
68 // to be a natural type so it can cleanly support std::vector. However as this
69 // evolved I am not sure this is the best decision and can be more costly for
70 // memory. Now that all the unit testing is in place it would be easier to
71 // refactor this back to the original packed ptr style if necessary.
72 template <typename gid_t, typename lid_t, typename user_t>
74  public:
75  // TODO: This free is an outstanding issue - follows original format and
76  // allows me to search the Kokkos::UnorderedMap by index and distinguish
77  // between empty slots and filled. But I am not quite understanding this
78  // and is there a way to search the filled slots without referring to the
79  // keys.
81  int owner; /* processor hosting global ID object */
82  int partition; /* Optional data */
83  int errcheck; /* Error checking(inconsistent updates) */
84  lid_t lid; /* lid value */
85  user_t userData; /* user data */
86  int free; /* flag whether node is free or used */
87 };
88 
89 // TODO: These message structures should become MPI datatypes(KDD)
90 // Currently these are implemented as they were in the original zoltan code.
91 template <typename gid_t, typename lid_t>
92 class Zoltan2_DD_Update_Msg { /* Only used by Zoltan_DD_Update() */
93  public:
94  char lid_flag; /* indicates if LID data are present */
95  char user_flag; /* indicates if USER data are present */
96  char partition_flag; /* indicates if optional partition data */
97  int owner; /* range [0, nproc-1] or -1 */
98  int partition;
99  gid_t adjData[1]; /* TODO: refactor - includes gid & lid & user */
100 };
101 
102 template <typename gid_t, typename lid_t>
103 class Zoltan2_DD_Find_Msg { /* Only used by Zoltan_DD_Find() */
104  public:
105  int proc; /* destination or location */
107  int index; /* to put things back in order afterward */
108  gid_t adjData[1]; /* TODO: refactor - includes gid and user */
109 };
110 
111 template <typename gid_t, typename lid_t>
112 class Zoltan2_DD_Remove_Msg { /* Only used by Zoltan_DD_Remove() */
113  public:
114  int owner; /* range [0, nproc-1] or -1 */
115  gid_t adjData[1]; /* TODO: refactor - includes gid */
116 };
117 
124 template <typename gid_t, typename lid_t, typename user_t>
126  public:
128  enum Update_Mode {
129  Replace = 0,
130  Add,
140  };
141 
144  Teuchos::RCP<const Teuchos::Comm<int> > comm_,
146  bool use_lid_,
147  int debug_level_)
148  : comm(comm_), use_lid(use_lid_),
149  debug_level(debug_level_)
150  {
151  }
152 
154  virtual ~Zoltan2_Directory() {
155  }
156 
158  int update(
159  size_t length, /* number of gids */
160  const gid_t * gid,
161  const lid_t * lid,
162  const user_t * user,
163  const int * partition,
164  Update_Mode update_mode);
167  int find(
168  size_t length, /* number of gids */
169  const gid_t * gid,
170  lid_t * lid,
171  user_t * user,
172  int * partition,
173  int * owner,
174  bool throw_if_missing = true);
179  int remove(
180  size_t length, /* number of gids */
181  const gid_t * gid);
184  int print() const;
185 
187  void stats() const;
188 
190  bool is_use_lid() const { return use_lid; }
191 
192  void get_locally_managed_gids(std::vector<gid_t> & local_gids) const {
193  // resize
194  local_gids.resize(node_map.size());
195 
196  // fill
197  size_t cnt = 0;
198  for(size_t n = 0; n < node_map.capacity(); ++n) {
199  if(node_map.value_at(n).free == 0) {
200  local_gids[cnt++] = node_map.key_at(n);
201  }
202  }
203 
204  if(cnt != node_map.size()) {
205  throw std::logic_error("Unexpected counts. Internal error with the"
206  " node_map behavior.");
207  }
208  }
209 
211  // This process follows the pattern of the original unique ids setup
212  // It assumes we have updated the directory with keys (as the gid_t) and
213  // also created empty user data. Each key is converted to a unique integer
214  // and written into the user data.
215  typedef long long mpi_t;
216  mpi_t nDDEntries = static_cast<mpi_t>(node_map.size());
217  mpi_t firstIdx;
218  Teuchos::scan(*comm, Teuchos::REDUCE_SUM,
219  1, &nDDEntries, &firstIdx);
220  firstIdx -= nDDEntries; // do not include this rank's entries in prefix sum
221  size_t cnt = 0;
222  for(size_t n = 0; n < node_map.capacity(); ++n) {
223  if(node_map.value_at(n).free == 0) {
225  node_map.value_at(n);
226  node.userData = firstIdx + cnt;
227  cnt++;
228  }
229  }
230  }
231 
232  size_t node_map_size() const {
233  return node_map.size();
234  }
235 
236  protected:
237  // handled updating the local node information when the proc receives
238  // a new gid to store or updated data for a preexisting node
239  int update_local(gid_t* gid, lid_t* lid, user_t *user,
240  int partition, int owner);
241 
242  // collect data on the local proc which has been requested by the directory.
243  int find_local(gid_t* gid, lid_t* lid, user_t *user,
244  int *partition, int *owner, bool throw_if_missing = true) const;
245 
246  // remove the locally stored node for this gid
247  int remove_local(gid_t* gid);
248 
249  size_t find_msg_size; /* Total allocation for Zoltan2_DD_FindMsg */
250  size_t update_msg_size; /* Total allocation for Zoltan2_DD_Update_Msg */
251  size_t remove_msg_size; /* Total allocation for Zoltan2_DD_Remove_Msg */
252 
253  // originally the nodes are stored in a hash but in the new Kokkos mode
254  // they are stored using Kokkos::UnorderedMap
255  typedef Kokkos::UnorderedMap<gid_t,
258 
259  // this method exists so constructor and copy constructor don't duplicate
260  void allocate();
261 
262  // this method exists so operator= and copy constructor don't duplicate
264 
265  // TODO: Decide if this stays and how to incorporate with variable length
266  // data. See comments in Zoltan2_Directory_Impl.hpp
267  // size_t align_size_t(size_t a) const;
268 
269  // take a gid and hash to proc - determines which proc wil own the gid data
270  unsigned int hash_proc(const gid_t & gid) const;
271 
272  // stores the comm provided by the user
273  Teuchos::RCP<const Teuchos::Comm<int> > comm;
274 
275  bool use_lid; /* If false not using lid */
276  int debug_level; /* Determines actions to multiple updates */
277 
278  size_t max_id_size; /* Stores: max(sizeof(gid_t),sizeof(lid_t)) */
279  Update_Mode mode; /* Last mode sent using update */
280 
281  // abstract methods are implemented below by Zoltan2_Directory_Simple
282  // or Zoltan2_Directory_Vector. These methods contain all the places where
283  // the code had to be specialized for normal user type (int, long, etc) or
284  // std::vector user type of variable length. Possibly we could consider
285  // making this all work by templating but exactly how to do that cleanly
286  // I am not sure. The class inheritance approach may be easier to understand
287  // but it does mean the user has to pick the right class to use.
288  virtual bool is_Zoltan2_Directory_Vector() const { return false; };
289  virtual void update_local_user(const user_t * pRaw, user_t & dst) {};
290  virtual void user_to_raw(const user_t & src, user_t * pRaw) const {};
291  virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {};
292  virtual size_t size_of_value_type() const { return 0; };
293  virtual size_t get_update_msg_size(const user_t & data) const { return 0; };
294  virtual size_t get_update_msg_size(const user_t * pRaw) const { return 0; };
295  virtual size_t get_local_find_msg_size(gid_t *gid,
296  bool throw_if_missing = true) const { return 0; };
298  Zoltan2_DD_Find_Msg<gid_t,lid_t>* msg) const { return 0; };
299 
300  private:
301  void rehash_node_map(size_t new_hash_size) {
302  node_map.rehash(new_hash_size);
303  }
304 };
305 
306 template <typename gid_t, typename lid_t, typename user_t>
307 class Zoltan2_Directory_Simple : public Zoltan2_Directory<gid_t, lid_t, user_t> {
308  public:
310 
312  Zoltan2_Directory_Simple(Teuchos::RCP<const Teuchos::Comm<int> > comm_, bool use_lid_,
313  int debug_level_) :
314  Zoltan2_Directory<gid_t, lid_t, user_t>(comm_, use_lid_,
315  debug_level_) {
316  // Note that allocate() must be called in the derived class, not the
317  // base class or inheritance of the methods will break
318  this->allocate();
319  }
320 
324  Zoltan2_Directory<gid_t, lid_t, user_t>(src.comm, src.use_lid,
325  src.debug_level) {
326  this->allocate();
327  this->copy(src);
328  }
329 
333  this->comm = src.comm;
334  this->use_lid = src.use_lid;
335  this->debug_level = src.debug_level;
336  this->allocate(); // operator= was setup in derived class so this inherits
337  this->copy(src);
338  return *this;
339  }
340 
341  protected:
342  // awkward to have this at all - so maybe to refactor out with future progress
343  virtual bool is_Zoltan2_Directory_Vector() const { return false; }
344 
345  // given raw data from the MPI stream we update user data based on mode
346  virtual void update_local_user(const user_t * pRaw, user_t & dst) {
347  switch(this->mode) {
349  dst = *pRaw;
350  break;
352  dst += *pRaw;
353  break;
355  throw std::logic_error("Aggregate doesn't mean anything for single "
356  "types. Must use Zoltan2_Directory_Vector class.");
358  throw std::logic_error("AggregateAdd doesn't mean anything for single "
359  "types. Must use Zoltan2_Directory_Vector class.");
360  }
361  }
362 
363  // convert user data to raw data - simple conversion for this class
364  virtual void user_to_raw(const user_t & src, user_t * pRaw) const {
365  *pRaw = src;
366  }
367 
368  // convert raw data to user data - simple conversion for this class
369  virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {
370  dst = *pRaw;
371  }
372 
373  // get size of the user type which is simply sizeof(user_t) for this class
374  virtual size_t size_of_value_type() const { return sizeof(user_t); }
375 
376  // for this class, update_msg_size is simple (not variable length)
377  virtual size_t get_update_msg_size(const user_t & data) const {
378  return this->update_msg_size;
379  }
380 
381  // for this class, update_msg_size is simple (not variable length)
382  virtual size_t get_update_msg_size(const user_t * pRaw) const {
383  return this->update_msg_size;
384  }
385 
386  // for this class, find_msg_size is simple (not variable length)
387  virtual size_t get_local_find_msg_size(gid_t *gid,
388  bool throw_if_missing = true) const {
389  return this->find_msg_size;
390  }
391 
392  // for this class, find_msg_size is simple (not variable length)
395  return this->find_msg_size;
396  }
397 };
398 
399 template <typename gid_t, typename lid_t, typename user_t>
400 class Zoltan2_Directory_Vector : public Zoltan2_Directory<gid_t, lid_t, user_t> {
401  public:
402  typedef typename user_t::value_type user_val_t;
403 
405  Zoltan2_Directory_Vector(Teuchos::RCP<const Teuchos::Comm<int> > comm_, bool use_lid_,
406  int debug_level_) :
407  Zoltan2_Directory<gid_t, lid_t, user_t>(comm_, use_lid_,
408  debug_level_) {
409  // Note that allocate() must be called in the derived class, not the
410  // base class or inheritance of the methods will break
411  this->allocate();
412  }
413 
417  Zoltan2_Directory<gid_t, lid_t, user_t>(src.comm, src.use_lid,
418  src.debug_level) {
419  this->allocate(); // operator= was setup in derived class so this inherits
420  this->copy(src);
421  }
422 
426  this->comm = src.comm;
427  this->use_lid = src.use_lid;
428  this->debug_level = src.debug_level;
429  this->allocate(); // operator= was setup in derived class so this inherits
430  this->copy(src);
431  return *this;
432  }
433 
434  protected:
435  // awkward to have this at all - so maybe to refactor out with future progress
436  virtual bool is_Zoltan2_Directory_Vector() const { return true; }
437 
438  // given raw data from the MPI stream we update user data based on mode
439  virtual void update_local_user(const user_t * pRaw, user_t & dst) {
440  // we're reading raw data of form: size_t, val, val, val ...
441  size_t * pLength = (size_t*)(pRaw);
442  size_t read_array_length = *pLength;
443  ++pLength; // move up to first element
444  user_val_t * pRead = (user_val_t*)(pLength);
445  switch(this->mode) {
447  // Note this is the raw_to_user method and we could just call it
448  // but Add and Aggregate don't have the equivalent so I've done it
449  // this way to keep the pattern.
450  dst.resize(read_array_length); // change to new
451  for(size_t i = 0; i < read_array_length; ++i) {
452  dst[i] = *pRead;
453  ++pRead;
454  }
455  }
456  break;
458  // ADD currently requires equal length vectors to add each element
459  if(dst.size() != static_cast<size_t>(read_array_length)) {
460  throw std::logic_error("The data lengths are not the same size");
461  }
462  // loop through and do the addition
463  for(size_t i = 0; i < dst.size(); ++i) {
464  dst[i] += *pRead;
465  ++pRead;
466  }
467  }
468  break;
470  // Add only unique elements
471  // Preserve ordering
472  // First scan the new incoming data
473  //
474  // For example we can have data of:
475  // [1,4,5,7]
476  // Then new incoming data is:
477  // [4,5,6,10]
478  // Then result would be:
479  // [1,4,5,6,7,10]
480  for(size_t i = 0; i < read_array_length; ++i) {
481  // handle the cases of dst no size or adding past last element
482  if(dst.size() == 0 || (*pRead) > dst[dst.size()-1]) {
483  dst.push_back(*pRead); // add first element or at end
484  }
485  else {
486  // otherwise we are going to insert unless it's not unique
487  for(auto itr = dst.begin(); itr != dst.end(); ++itr) {
488  if((*itr) == (*pRead)) { // do they match
490  Update_Mode::AggregateAdd) {
491  (*itr) += (*pRead); // do the AggregateAdd action using +=
492  }
493  break; // break because it's already in there - do nothing
494  }
495  else if((*itr) > (*pRead)) { // is scanned element larger?
496  dst.insert(itr, (*pRead)); // preserve ordering
497  break; // break because once we add it we are done
498  }
499  }
500  }
501  ++pRead; // get the next incoming array element (*pRead)
502  }
503  }
504  break;
506  // AggregateAdd is similar to Aggregate except that when two items
507  // match through the operator==, they are combined using operator+=
508  // instead of excluding the duplicate. This reliance on operator==
509  // and operator+= allows the user to define the behavior for the
510  // struct but needs design discussion. This example struct was taken
511  // from Zoltan2_GraphMetricsUtility.hpp which was the origina reason
512  // for adding this mode.
513  /*
514  struct part_info {
515  part_info() : sum_weights(0) {
516  }
517  const part_info & operator+=(const part_info & src) {
518  sum_weights += src.sum_weights;
519  return *this; // return old value
520  }
521  bool operator>(const part_info & src) {
522  return (target_part > src.target_part);
523  }
524  bool operator==(const part_info & src) {
525  return (target_part == src.target_part);
526  }
527  part_t target_part; // the part this part_info refers to
528  t_scalar_t sum_weights; // the sum of weights
529  };
530  */
531  // Then if we use AggregateAdd the following example shows how the
532  // struct with part_t 1 will have sum_weights combined:
533  //
534  // Proc 1 Proc 2 Result
535  // part_t 0 1 1 3 0 1 3
536  // sum_weights 1.0 1.0 2.0 2.0 1.0 3.0 2.0
537  //
538  // TODO: We could make this almost identical to above Aggregate and
539  // preserve ordering. Then the only difference is that Aggregate just
540  // does nothing when two elements are the same while AggregateAdd will
541  // combine them with += operator. Did not implement yet since
542  // Zoltan2_GraphMetricsUtility.hpp didn't have parts ordered and I
543  // wasn't sure yet if we'd want to make that a requirement.
544  for(size_t i = 0; i < read_array_length; ++i) {
545  bool bMatch = false;
546  for(auto itr = dst.begin(); itr != dst.end(); ++itr) {
547  if((*itr) == (*pRead)) { // determine if they go together using ==
548  (*itr) += (*pRead); // do the AggregateAdd action using +=
549  bMatch = true;
550  break;
551  }
552  }
553  if(!bMatch) {
554  dst.push_back(*pRead); // add first element or at end
555  }
556  ++pRead; // get the next incoming array element (*pRead)
557  }
558  }
559  break;
560 
561  }
562  }
563 
564  // write the std::vector as length, x1, x2, x3 ...
565  virtual void user_to_raw(const user_t & src, user_t * pRaw) const {
566  // we're writing raw data of form: size_t, val, val, val ...
567  size_t *pLength = (size_t*)(pRaw);
568  *pLength = src.size(); // first write the length
569  ++pLength; // move up to first element
570  user_val_t *pWrite = (user_val_t*)(pLength);
571  for(size_t n = 0; n < src.size(); ++n) {
572  *pWrite = src[n]; // now write each element
573  ++pWrite;
574  }
575  }
576 
577  // raw comes in as length, x1, x2, x3 ...
578  virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {
579  // we're reading raw of form: size_t, val, val, val ...
580  size_t* pLength = (size_t*) pRaw;
581  dst.resize(static_cast<size_t>(*pLength)); // first read the length
582  ++pLength; // move up to first element
583  user_val_t* pRead = (user_val_t*) pLength;
584  for(size_t n = 0; n < dst.size(); ++n) {
585  dst[n] = *pRead; // now read each element
586  ++pRead;
587  }
588  }
589 
590  // for the std::vector directory, value type is the size of the std::vector
591  // template parameter, so for std::vector<int> we want sizeof(int)(
592  virtual size_t size_of_value_type() const {
593  return sizeof(typename user_t::value_type);
594  }
595 
596  // the update msg is the base size (includes vector length) plus the size
597  // of all the elements.
598  virtual size_t get_update_msg_size(const user_t & data) const {
599  return this->update_msg_size + data.size() * size_of_value_type();
600  }
601 
602  // the update msg is the base size (includes vector length) plus the size
603  // of all the elements. This is same idea as above method but here we are
604  // intepreting raw data (which comes in as length, x1, x2, x3...) so we
605  // read the size as the first element. That's all we need to determine the
606  // total update_msg_size.
607  virtual size_t get_update_msg_size(const user_t * pRaw) const {
608  // the first element is size_t (length of the vector)
609  size_t * pLength = (size_t*) (pRaw);
610  return this->update_msg_size +
611  (pRaw ? ((*pLength) * size_of_value_type()) : 0);
612  }
613 
614  // to get the local find msg size we need to verify the node exists and then
615  // read the std::vector size (which is added to base length find_msg_size.
616  virtual size_t get_local_find_msg_size(gid_t * gid,
617  bool throw_if_missing = true) const {
618  if(this->node_map.exists(*gid)) {
620  this->node_map.value_at(this->node_map.find(*gid));
621  return this->find_msg_size + node.userData.size() * sizeof(user_val_t);
622  }
623  else if(throw_if_missing) {
624  throw std::logic_error( "Could not find gid in map." );
625  }
626  else {
627  // not clear yet if we ever want to handle this case or always err out
628  // I'm using this right now for the unit testing to validate that the
629  // remove command actually works.
630  return this->find_msg_size; // will not have any data content
631  }
632  }
633 
634  // here we have a find msg coming in and we need to extract the vector length
635  // which is always at the same place in the message.
638  if(msg->proc == -1) {
639  // this happens if we called find for an element which was removed
640  // eventually we might just throw on find_local but for the testing,
641  // this is allowed, the data is left untouched, and the test validates
642  // that the results are as expected based on remove events
643  return this->find_msg_size; // no extra data for unfound node
644  }
645  // the first element of the user data is size_t (length of the vector)
646  size_t * pVectorLength =
647  (size_t*)(reinterpret_cast<char*>(msg->adjData) + this->max_id_size);
648  return this->find_msg_size + (*pVectorLength) * sizeof(user_val_t);
649  }
650 };
651 
652 } // end namespace Zoltan2
653 
654 #endif
virtual size_t get_local_find_msg_size(gid_t *gid, bool throw_if_missing=true) const
int find(size_t length, const gid_t *gid, lid_t *lid, user_t *user, int *partition, int *owner, bool throw_if_missing=true)
Can be Replace, Add, or Aggregate.
virtual size_t get_local_find_msg_size(gid_t *gid, bool throw_if_missing=true) const
int update(size_t length, const gid_t *gid, const lid_t *lid, const user_t *user, const int *partition, Update_Mode update_mode)
update is called by user to submit new data.
virtual bool is_Zoltan2_Directory_Vector() const
For std::vector user data, aggregates all data so for example [1,2,5] and [3,5] becomes [1...
Zoltan2_Directory(Teuchos::RCP< const Teuchos::Comm< int > > comm_, bool use_lid_, int debug_level_)
Construct Zoltan2_Directory (abstract class).
virtual void update_local_user(const user_t *pRaw, user_t &dst)
All values from different procs are summed.
virtual bool is_Zoltan2_Directory_Vector() const
void stats() const
stats. New Kokkos mode needs further development.
virtual void raw_to_user(const user_t *pRaw, user_t &dst) const
int print() const
gids to remove.
virtual size_t size_of_value_type() const
void get_locally_managed_gids(std::vector< gid_t > &local_gids) const
virtual size_t get_update_msg_size(const user_t *pRaw) const
int copy(const Zoltan2_Directory< gid_t, lid_t, user_t > &dd)
virtual void user_to_raw(const user_t &src, user_t *pRaw) const
virtual size_t size_of_value_type() const
The new value replaces the original value.
int update_local(gid_t *gid, lid_t *lid, user_t *user, int partition, int owner)
Update_Mode
Update_Mode determines how update executes.
virtual size_t get_update_msg_size(const user_t *pRaw) const
virtual size_t get_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) const
Teuchos::RCP< const Teuchos::Comm< int > > comm
virtual void update_local_user(const user_t *pRaw, user_t &dst)
virtual size_t get_local_find_msg_size(gid_t *gid, bool throw_if_missing=true) const
virtual ~Zoltan2_Directory()
Destructor currently does nothing.
virtual void raw_to_user(const user_t *pRaw, user_t &dst) const
virtual size_t get_update_msg_size(const user_t &data) const
unsigned int hash_proc(const gid_t &gid) const
virtual size_t get_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) const
Zoltan2_Directory_Vector(const Zoltan2_Directory_Vector< gid_t, lid_t, user_t > &src)
Copy constructor.
virtual size_t get_update_msg_size(const user_t &data) const
virtual void user_to_raw(const user_t &src, user_t *pRaw) const
virtual size_t get_update_msg_size(const user_t &data) const
int find_local(gid_t *gid, lid_t *lid, user_t *user, int *partition, int *owner, bool throw_if_missing=true) const
Kokkos::UnorderedMap< gid_t, Zoltan2_Directory_Node< gid_t, lid_t, user_t >, Kokkos::HostSpace > node_map_t
bool is_use_lid() const
returns true if the directory is handling local ids.
virtual bool is_Zoltan2_Directory_Vector() const
virtual size_t get_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) const
virtual size_t size_of_value_type() const
virtual void update_local_user(const user_t *pRaw, user_t &dst)
Zoltan2_Directory_Simple(const Zoltan2_Directory_Simple< gid_t, lid_t, user_t > &src)
Copy constructor.
virtual size_t get_update_msg_size(const user_t *pRaw) const
virtual void user_to_raw(const user_t &src, user_t *pRaw) const
Zoltan2_Directory is an abstract base class.
In progress and needs discussion. Currently this mode will use operator== to determine if two items m...
Zoltan2_Directory_Vector(Teuchos::RCP< const Teuchos::Comm< int > > comm_, bool use_lid_, int debug_level_)
Constructo directory which handles std::vector user data types.
virtual void raw_to_user(const user_t *pRaw, user_t &dst) const
Zoltan2_Directory_Simple(Teuchos::RCP< const Teuchos::Comm< int > > comm_, bool use_lid_, int debug_level_)
Constructo directory which handles simple user data types.
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition: Metric.cpp:74