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 
52 #ifndef HAVE_MPI
53 // support mpi serial - directory currently has a mix of Teuchos mpi commands
54 // and original MPI commands so as this gets better organized the serial support
55 // can be handled more naturally. Currently the tests call an MPI_Init for serial
56 // so this can all work. I've mostly added the serial support just to make
57 // debugging easier.
58 #include <mpi.h>
59 #endif
60 
61 #include <Kokkos_UnorderedMap.hpp> // unordered map stores the local nodes
62 
63 namespace Zoltan2 {
64 
65 // The new Kokkos mode maps over the gid using unordered map
66 // Originally was thinking we don't want ptrs here and want the user data
67 // to be a natural type so it can cleanly support std::vector. However as this
68 // evolved I am not sure this is the best decision and can be more costly for
69 // memory. Now that all the unit testing is in place it would be easier to
70 // refactor this back to the original packed ptr style if necessary.
71 template <typename gid_t, typename lid_t, typename user_t>
73  public:
74  // TODO: This free is an outstanding issue - follows original format and
75  // allows me to search the Kokkos::UnorderedMap by index and distinguish
76  // between empty slots and filled. But I am not quite understanding this
77  // and is there a way to search the filled slots without referring to the
78  // keys.
80  int owner; /* processor hosting global ID object */
81  int partition; /* Optional data */
82  int errcheck; /* Error checking(inconsistent updates) */
83  lid_t lid; /* lid value */
84  user_t userData; /* user data */
85  int free; /* flag whether node is free or used */
86 };
87 
88 // TODO: These message structures should become MPI datatypes(KDD)
89 // Currently these are implemented as they were in the original zoltan code.
90 template <typename gid_t, typename lid_t>
91 class Zoltan2_DD_Update_Msg { /* Only used by Zoltan_DD_Update() */
92  public:
93  char lid_flag; /* indicates if LID data are present */
94  char user_flag; /* indicates if USER data are present */
95  char partition_flag; /* indicates if optional partition data */
96  int owner; /* range [0, nproc-1] or -1 */
97  int partition;
98  gid_t adjData[1]; /* TODO: refactor - includes gid & lid & user */
99 };
100 
101 template <typename gid_t, typename lid_t>
102 class Zoltan2_DD_Find_Msg { /* Only used by Zoltan_DD_Find() */
103  public:
104  int proc; /* destination or location */
106  int index; /* to put things back in order afterward */
107  gid_t adjData[1]; /* TODO: refactor - includes gid and user */
108 };
109 
110 template <typename gid_t, typename lid_t>
111 class Zoltan2_DD_Remove_Msg { /* Only used by Zoltan_DD_Remove() */
112  public:
113  int owner; /* range [0, nproc-1] or -1 */
114  gid_t adjData[1]; /* TODO: refactor - includes gid */
115 };
116 
123 template <typename gid_t, typename lid_t, typename user_t>
125  public:
127  enum Update_Mode {
128  Replace = 0,
129  Add,
139  };
140 
143  Teuchos::RCP<const Teuchos::Comm<int> > comm_,
145  bool use_lid_,
146  int debug_level_)
147  : comm(comm_), use_lid(use_lid_),
148  debug_level(debug_level_)
149  {
150  }
151 
153  virtual ~Zoltan2_Directory() {
154  }
155 
157  int update(
158  size_t length, /* number of gids */
159  const gid_t * gid,
160  const lid_t * lid,
161  const user_t * user,
162  const int * partition,
163  Update_Mode update_mode);
166  int find(
167  size_t length, /* number of gids */
168  const gid_t * gid,
169  lid_t * lid,
170  user_t * user,
171  int * partition,
172  int * owner,
173  bool throw_if_missing = true);
178  int remove(
179  size_t length, /* number of gids */
180  const gid_t * gid);
183  int print() const;
184 
186  void stats() const;
187 
189  bool is_use_lid() const { return use_lid; }
190 
191  void get_locally_managed_gids(std::vector<gid_t> & local_gids) const {
192  // resize
193  local_gids.resize(node_map.size());
194 
195  // fill
196  size_t cnt = 0;
197  for(size_t n = 0; n < node_map.capacity(); ++n) {
198  if(node_map.value_at(n).free == 0) {
199  local_gids[cnt++] = node_map.key_at(n);
200  }
201  }
202 
203  if(cnt != node_map.size()) {
204  throw std::logic_error("Unexpected counts. Internal error with the"
205  " node_map behavior.");
206  }
207  }
208 
210  // This process follows the pattern of the original unique ids setup
211  // It assumes we have updated the directory with keys (as the gid_t) and
212  // also created empty user data. Each key is converted to a unique integer
213  // and written into the user data.
214  typedef long long mpi_t;
215  mpi_t nDDEntries = static_cast<mpi_t>(node_map.size());
216  mpi_t firstIdx;
217  MPI_Scan(&nDDEntries, &firstIdx, 1, MPI_LONG_LONG, MPI_SUM, getRawComm());
218  firstIdx -= nDDEntries; // do not include this rank's entries in prefix sum
219  size_t cnt = 0;
220  for(size_t n = 0; n < node_map.capacity(); ++n) {
221  if(node_map.value_at(n).free == 0) {
223  node_map.value_at(n);
224  node.userData = firstIdx + cnt;
225  cnt++;
226  }
227  }
228  }
229 
230  size_t node_map_size() const {
231  return node_map.size();
232  }
233 
234  protected:
235  // handled updating the local node information when the proc receives
236  // a new gid to store or updated data for a preexisting node
237  int update_local(gid_t* gid, lid_t* lid, user_t *user,
238  int partition, int owner);
239 
240  // collect data on the local proc which has been requested by the directory.
241  int find_local(gid_t* gid, lid_t* lid, user_t *user,
242  int *partition, int *owner, bool throw_if_missing = true) const;
243 
244  // remove the locally stored node for this gid
245  int remove_local(gid_t* gid);
246 
247  size_t find_msg_size; /* Total allocation for Zoltan2_DD_FindMsg */
248  size_t update_msg_size; /* Total allocation for Zoltan2_DD_Update_Msg */
249  size_t remove_msg_size; /* Total allocation for Zoltan2_DD_Remove_Msg */
250 
251  // originally the nodes are stored in a hash but in the new Kokkos mode
252  // they are stored using Kokkos::UnorderedMap
253  typedef Kokkos::UnorderedMap<gid_t,
256 
257  // this method exists so constructor and copy constructor don't duplicate
258  void allocate();
259 
260  // this method exists so operator= and copy constructor don't duplicate
262 
263  // TODO: Decide if this stays and how to incorporate with variable length
264  // data. See comments in Zoltan2_Directory_Impl.hpp
265  // size_t align_size_t(size_t a) const;
266 
267  // take a gid and hash to proc - determines which proc wil own the gid data
268  unsigned int hash_proc(const gid_t & gid) const;
269 
270  // stores the comm provided by the user
271  Teuchos::RCP<const Teuchos::Comm<int> > comm;
272 
273  bool use_lid; /* If false not using lid */
274  int debug_level; /* Determines actions to multiple updates */
275 
276  size_t max_id_size; /* Stores: max(sizeof(gid_t),sizeof(lid_t)) */
277  Update_Mode mode; /* Last mode sent using update */
278 
279  // abstract methods are implemented below by Zoltan2_Directory_Simple
280  // or Zoltan2_Directory_Vector. These methods contain all the places where
281  // the code had to be specialized for normal user type (int, long, etc) or
282  // std::vector user type of variable length. Possibly we could consider
283  // making this all work by templating but exactly how to do that cleanly
284  // I am not sure. The class inheritance approach may be easier to understand
285  // but it does mean the user has to pick the right class to use.
286  virtual bool is_Zoltan2_Directory_Vector() const = 0;
287  virtual void update_local_user(const user_t * pRaw, user_t & dst) = 0;
288  virtual void user_to_raw(const user_t & src, user_t * pRaw) const = 0;
289  virtual void raw_to_user(const user_t * pRaw, user_t & dst) const = 0;
290  virtual size_t size_of_value_type() const = 0;
291  virtual size_t get_update_msg_size(const user_t & data) const = 0;
292  virtual size_t get_update_msg_size(const user_t * pRaw) const = 0;
293  virtual size_t get_local_find_msg_size(gid_t *gid,
294  bool throw_if_missing = true) const = 0;
295  virtual size_t get_incoming_find_msg_size(
296  Zoltan2_DD_Find_Msg<gid_t,lid_t>* msg) const = 0;
297 
298  private:
299  MPI_Comm getRawComm() {
300  #ifdef HAVE_MPI
301  return Teuchos::getRawMpiComm(*comm);
302  #else
303  return MPI_COMM_WORLD;
304  #endif
305  }
306 
307  void rehash_node_map(size_t new_hash_size) {
308  node_map.rehash(new_hash_size);
309  }
310 };
311 
312 template <typename gid_t, typename lid_t, typename user_t>
313 class Zoltan2_Directory_Simple : public Zoltan2_Directory<gid_t, lid_t, user_t> {
314  public:
316 
318  Zoltan2_Directory_Simple(Teuchos::RCP<const Teuchos::Comm<int> > comm_, bool use_lid_,
319  int debug_level_) :
320  Zoltan2_Directory<gid_t, lid_t, user_t>(comm_, use_lid_,
321  debug_level_) {
322  // Note that allocate() must be called in the derived class, not the
323  // base class or inheritance of the methods will break
324  this->allocate();
325  }
326 
330  Zoltan2_Directory<gid_t, lid_t, user_t>(src.comm, src.use_lid,
331  src.debug_level) {
332  this->allocate();
333  this->copy(src);
334  }
335 
339  this->comm = src.comm;
340  this->use_lid = src.use_lid;
341  this->debug_level = src.debug_level;
342  this->allocate(); // operator= was setup in derived class so this inherits
343  this->copy(src);
344  return *this;
345  }
346 
347  protected:
348  // awkward to have this at all - so maybe to refactor out with future progress
349  virtual bool is_Zoltan2_Directory_Vector() const { return false; }
350 
351  // given raw data from the MPI stream we update user data based on mode
352  virtual void update_local_user(const user_t * pRaw, user_t & dst) {
353  switch(this->mode) {
355  dst = *pRaw;
356  break;
358  dst += *pRaw;
359  break;
361  throw std::logic_error("Aggregate doesn't mean anything for single "
362  "types. Must use Zoltan2_Directory_Vector class.");
364  throw std::logic_error("AggregateAdd doesn't mean anything for single "
365  "types. Must use Zoltan2_Directory_Vector class.");
366  }
367  }
368 
369  // convert user data to raw data - simple conversion for this class
370  virtual void user_to_raw(const user_t & src, user_t * pRaw) const {
371  *pRaw = src;
372  }
373 
374  // convert raw data to user data - simple conversion for this class
375  virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {
376  dst = *pRaw;
377  }
378 
379  // get size of the user type which is simply sizeof(user_t) for this class
380  virtual size_t size_of_value_type() const { return sizeof(user_t); }
381 
382  // for this class, update_msg_size is simple (not variable length)
383  virtual size_t get_update_msg_size(const user_t & data) const {
384  return this->update_msg_size;
385  }
386 
387  // for this class, update_msg_size is simple (not variable length)
388  virtual size_t get_update_msg_size(const user_t * pRaw) const {
389  return this->update_msg_size;
390  }
391 
392  // for this class, find_msg_size is simple (not variable length)
393  virtual size_t get_local_find_msg_size(gid_t *gid,
394  bool throw_if_missing = true) const {
395  return this->find_msg_size;
396  }
397 
398  // for this class, find_msg_size is simple (not variable length)
401  return this->find_msg_size;
402  }
403 };
404 
405 template <typename gid_t, typename lid_t, typename user_t>
406 class Zoltan2_Directory_Vector : public Zoltan2_Directory<gid_t, lid_t, user_t> {
407  public:
408  typedef typename user_t::value_type user_val_t;
409 
411  Zoltan2_Directory_Vector(Teuchos::RCP<const Teuchos::Comm<int> > comm_, bool use_lid_,
412  int debug_level_) :
413  Zoltan2_Directory<gid_t, lid_t, user_t>(comm_, use_lid_,
414  debug_level_) {
415  // Note that allocate() must be called in the derived class, not the
416  // base class or inheritance of the methods will break
417  this->allocate();
418  }
419 
423  Zoltan2_Directory<gid_t, lid_t, user_t>(src.comm, src.use_lid,
424  src.debug_level) {
425  this->allocate(); // operator= was setup in derived class so this inherits
426  this->copy(src);
427  }
428 
432  this->comm = src.comm;
433  this->use_lid = src.use_lid;
434  this->debug_level = src.debug_level;
435  this->allocate(); // operator= was setup in derived class so this inherits
436  this->copy(src);
437  return *this;
438  }
439 
440  protected:
441  // awkward to have this at all - so maybe to refactor out with future progress
442  virtual bool is_Zoltan2_Directory_Vector() const { return true; }
443 
444  // given raw data from the MPI stream we update user data based on mode
445  virtual void update_local_user(const user_t * pRaw, user_t & dst) {
446  // we're reading raw data of form: size_t, val, val, val ...
447  size_t * pLength = (size_t*)(pRaw);
448  size_t read_array_length = *pLength;
449  ++pLength; // move up to first element
450  user_val_t * pRead = (user_val_t*)(pLength);
451  switch(this->mode) {
453  // Note this is the raw_to_user method and we could just call it
454  // but Add and Aggregate don't have the equivalent so I've done it
455  // this way to keep the pattern.
456  dst.resize(read_array_length); // change to new
457  for(size_t i = 0; i < read_array_length; ++i) {
458  dst[i] = *pRead;
459  ++pRead;
460  }
461  }
462  break;
464  // ADD currently requires equal length vectors to add each element
465  if(dst.size() != static_cast<size_t>(read_array_length)) {
466  throw std::logic_error("The data lengths are not the same size");
467  }
468  // loop through and do the addition
469  for(size_t i = 0; i < dst.size(); ++i) {
470  dst[i] += *pRead;
471  ++pRead;
472  }
473  }
474  break;
476  // Add only unique elements
477  // Preserve ordering
478  // First scan the new incoming data
479  //
480  // For example we can have data of:
481  // [1,4,5,7]
482  // Then new incoming data is:
483  // [4,5,6,10]
484  // Then result would be:
485  // [1,4,5,6,7,10]
486  for(size_t i = 0; i < read_array_length; ++i) {
487  // handle the cases of dst no size or adding past last element
488  if(dst.size() == 0 || (*pRead) > dst[dst.size()-1]) {
489  dst.push_back(*pRead); // add first element or at end
490  }
491  else {
492  // otherwise we are going to insert unless it's not unique
493  for(auto itr = dst.begin(); itr != dst.end(); ++itr) {
494  if((*itr) == (*pRead)) { // do they match
496  Update_Mode::AggregateAdd) {
497  (*itr) += (*pRead); // do the AggregateAdd action using +=
498  }
499  break; // break because it's already in there - do nothing
500  }
501  else if((*itr) > (*pRead)) { // is scanned element larger?
502  dst.insert(itr, (*pRead)); // preserve ordering
503  break; // break because once we add it we are done
504  }
505  }
506  }
507  ++pRead; // get the next incoming array element (*pRead)
508  }
509  }
510  break;
512  // AggregateAdd is similar to Aggregate except that when two items
513  // match through the operator==, they are combined using operator+=
514  // instead of excluding the duplicate. This reliance on operator==
515  // and operator+= allows the user to define the behavior for the
516  // struct but needs design discussion. This example struct was taken
517  // from Zoltan2_GraphMetricsUtility.hpp which was the origina reason
518  // for adding this mode.
519  /*
520  struct part_info {
521  part_info() : sum_weights(0) {
522  }
523  const part_info & operator+=(const part_info & src) {
524  sum_weights += src.sum_weights;
525  return *this; // return old value
526  }
527  bool operator>(const part_info & src) {
528  return (target_part > src.target_part);
529  }
530  bool operator==(const part_info & src) {
531  return (target_part == src.target_part);
532  }
533  part_t target_part; // the part this part_info refers to
534  t_scalar_t sum_weights; // the sum of weights
535  };
536  */
537  // Then if we use AggregateAdd the following example shows how the
538  // struct with part_t 1 will have sum_weights combined:
539  //
540  // Proc 1 Proc 2 Result
541  // part_t 0 1 1 3 0 1 3
542  // sum_weights 1.0 1.0 2.0 2.0 1.0 3.0 2.0
543  //
544  // TODO: We could make this almost identical to above Aggregate and
545  // preserve ordering. Then the only difference is that Aggregate just
546  // does nothing when two elements are the same while AggregateAdd will
547  // combine them with += operator. Did not implement yet since
548  // Zoltan2_GraphMetricsUtility.hpp didn't have parts ordered and I
549  // wasn't sure yet if we'd want to make that a requirement.
550  for(size_t i = 0; i < read_array_length; ++i) {
551  bool bMatch = false;
552  for(auto itr = dst.begin(); itr != dst.end(); ++itr) {
553  if((*itr) == (*pRead)) { // determine if they go together using ==
554  (*itr) += (*pRead); // do the AggregateAdd action using +=
555  bMatch = true;
556  break;
557  }
558  }
559  if(!bMatch) {
560  dst.push_back(*pRead); // add first element or at end
561  }
562  ++pRead; // get the next incoming array element (*pRead)
563  }
564  }
565  break;
566 
567  }
568  }
569 
570  // write the std::vector as length, x1, x2, x3 ...
571  virtual void user_to_raw(const user_t & src, user_t * pRaw) const {
572  // we're writing raw data of form: size_t, val, val, val ...
573  size_t *pLength = (size_t*)(pRaw);
574  *pLength = src.size(); // first write the length
575  ++pLength; // move up to first element
576  user_val_t *pWrite = (user_val_t*)(pLength);
577  for(size_t n = 0; n < src.size(); ++n) {
578  *pWrite = src[n]; // now write each element
579  ++pWrite;
580  }
581  }
582 
583  // raw comes in as length, x1, x2, x3 ...
584  virtual void raw_to_user(const user_t * pRaw, user_t & dst) const {
585  // we're reading raw of form: size_t, val, val, val ...
586  size_t* pLength = (size_t*) pRaw;
587  dst.resize(static_cast<size_t>(*pLength)); // first read the length
588  ++pLength; // move up to first element
589  user_val_t* pRead = (user_val_t*) pLength;
590  for(size_t n = 0; n < dst.size(); ++n) {
591  dst[n] = *pRead; // now read each element
592  ++pRead;
593  }
594  }
595 
596  // for the std::vector directory, value type is the size of the std::vector
597  // template parameter, so for std::vector<int> we want sizeof(int)(
598  virtual size_t size_of_value_type() const {
599  return sizeof(typename user_t::value_type);
600  }
601 
602  // the update msg is the base size (includes vector length) plus the size
603  // of all the elements.
604  virtual size_t get_update_msg_size(const user_t & data) const {
605  return this->update_msg_size + data.size() * size_of_value_type();
606  }
607 
608  // the update msg is the base size (includes vector length) plus the size
609  // of all the elements. This is same idea as above method but here we are
610  // intepreting raw data (which comes in as length, x1, x2, x3...) so we
611  // read the size as the first element. That's all we need to determine the
612  // total update_msg_size.
613  virtual size_t get_update_msg_size(const user_t * pRaw) const {
614  // the first element is size_t (length of the vector)
615  size_t * pLength = (size_t*) (pRaw);
616  return this->update_msg_size +
617  (pRaw ? ((*pLength) * size_of_value_type()) : 0);
618  }
619 
620  // to get the local find msg size we need to verify the node exists and then
621  // read the std::vector size (which is added to base length find_msg_size.
622  virtual size_t get_local_find_msg_size(gid_t * gid,
623  bool throw_if_missing = true) const {
624  if(this->node_map.exists(*gid)) {
626  this->node_map.value_at(this->node_map.find(*gid));
627  return this->find_msg_size + node.userData.size() * sizeof(user_val_t);
628  }
629  else if(throw_if_missing) {
630  throw std::logic_error( "Could not find gid in map." );
631  }
632  else {
633  // not clear yet if we ever want to handle this case or always err out
634  // I'm using this right now for the unit testing to validate that the
635  // remove command actually works.
636  return this->find_msg_size; // will not have any data content
637  }
638  }
639 
640  // here we have a find msg coming in and we need to extract the vector length
641  // which is always at the same place in the message.
644  if(msg->proc == -1) {
645  // this happens if we called find for an element which was removed
646  // eventually we might just throw on find_local but for the testing,
647  // this is allowed, the data is left untouched, and the test validates
648  // that the results are as expected based on remove events
649  return this->find_msg_size; // no extra data for unfound node
650  }
651  // the first element of the user data is size_t (length of the vector)
652  size_t * pVectorLength =
653  (size_t*)(reinterpret_cast<char*>(msg->adjData) + this->max_id_size);
654  return this->find_msg_size + (*pVectorLength) * sizeof(user_val_t);
655  }
656 };
657 
658 } // end namespace Zoltan2
659 
660 #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.
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).
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 size_t size_of_value_type() const =0
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
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 bool is_Zoltan2_Directory_Vector() const =0
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
virtual size_t get_local_find_msg_size(gid_t *gid, bool throw_if_missing=true) const =0
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 size_t get_update_msg_size(const user_t &data) const =0
virtual void user_to_raw(const user_t &src, user_t *pRaw) 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 void raw_to_user(const user_t *pRaw, user_t &dst) const =0
virtual size_t get_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) 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_incoming_find_msg_size(Zoltan2_DD_Find_Msg< gid_t, lid_t > *msg) const =0
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...
virtual void user_to_raw(const user_t &src, user_t *pRaw) const =0
virtual void update_local_user(const user_t *pRaw, user_t &dst)=0
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