DIY  3.0
data-parallel out-of-core C++ library
 All Classes Namespaces Functions Typedefs Groups Pages
link.hpp
1 #ifndef DIY_COVER_HPP
2 #define DIY_COVER_HPP
3 
4 #include <vector>
5 #include <map>
6 #include <algorithm>
7 
8 #include "types.hpp"
9 #include "serialization.hpp"
10 #include "assigner.hpp"
11 
12 namespace diy
13 {
14  // Local view of a distributed representation of a cover, a completely unstructured link
15  class Link
16  {
17  public:
18  virtual ~Link() {} // need to be able to delete derived classes
19 
20  int size() const { return neighbors_.size(); }
21  inline
22  int size_unique() const;
23  BlockID target(int i) const { return neighbors_[i]; }
24  BlockID& target(int i) { return neighbors_[i]; }
25  inline
26  int find(int gid) const;
27 
28  void add_neighbor(const BlockID& block) { neighbors_.push_back(block); }
29 
30  void fix(const Assigner& assigner) { for (unsigned i = 0; i < neighbors_.size(); ++i) { neighbors_[i].proc = assigner.rank(neighbors_[i].gid); } }
31 
32  void swap(Link& other) { neighbors_.swap(other.neighbors_); }
33 
34  virtual void save(BinaryBuffer& bb) const { diy::save(bb, neighbors_); }
35  virtual void load(BinaryBuffer& bb) { diy::load(bb, neighbors_); }
36 
37  virtual size_t id() const { return 0; }
38 
39  private:
40  std::vector<BlockID> neighbors_;
41  };
42 
43  template<class Bounds_>
44  class RegularLink;
45 
48 
49  // Selector between regular discrete and contious links given bounds type
50  template<class Bounds_>
52 
53  template<>
55  {
56  typedef RegularGridLink type;
57  static const size_t id = 1;
58  };
59 
60  template<>
62  {
64  static const size_t id = 2;
65  };
66 
67 
68  // for a regular decomposition, it makes sense to address the neighbors by direction
69  // and store local and neighbor bounds
70  template<class Bounds_>
71  class RegularLink: public Link
72  {
73  public:
74  typedef Bounds_ Bounds;
75 
76  typedef std::map<Direction, int> DirMap;
77  typedef std::vector<Direction> DirVec;
78 
79  public:
80  RegularLink(int dim, const Bounds& core, const Bounds& bounds):
81  dim_(dim), core_(core), bounds_(bounds) {}
82 
83  // dimension
84  int dimension() const { return dim_; }
85 
86  // direction
87  int direction(Direction dir) const; // convert direction to a neighbor (-1 if no neighbor)
88  Direction direction(int i) const { return dir_vec_[i]; }
89  void add_direction(Direction dir) { int c = dir_map_.size(); dir_map_[dir] = c; dir_vec_.push_back(dir); }
90 
91  // wrap
92  void add_wrap(Direction dir) { wrap_.push_back(dir); }
93  Direction wrap(int i) const { return wrap_[i]; }
94  Direction& wrap(int i) { return wrap_[i]; }
95 
96  // bounds
97  const Bounds& core() const { return core_; }
98  Bounds& core() { return core_; }
99  const Bounds& bounds() const { return bounds_; }
100  Bounds& bounds() { return bounds_; }
101  const Bounds& bounds(int i) const { return nbr_bounds_[i]; }
102  void add_bounds(const Bounds& bounds) { nbr_bounds_.push_back(bounds); }
103 
104  void swap(RegularLink& other) { Link::swap(other); dir_map_.swap(other.dir_map_); dir_vec_.swap(other.dir_vec_); nbr_bounds_.swap(other.nbr_bounds_); std::swap(dim_, other.dim_); wrap_.swap(other.wrap_); std::swap(core_, other.core_); std::swap(bounds_, other.bounds_); }
105 
106  void save(BinaryBuffer& bb) const
107  {
108  Link::save(bb);
109  diy::save(bb, dim_);
110  diy::save(bb, dir_map_);
111  diy::save(bb, dir_vec_);
112  diy::save(bb, core_);
113  diy::save(bb, bounds_);
114  diy::save(bb, nbr_bounds_);
115  diy::save(bb, wrap_);
116  }
117 
118  void load(BinaryBuffer& bb)
119  {
120  Link::load(bb);
121  diy::load(bb, dim_);
122  diy::load(bb, dir_map_);
123  diy::load(bb, dir_vec_);
124  diy::load(bb, core_);
125  diy::load(bb, bounds_);
126  diy::load(bb, nbr_bounds_);
127  diy::load(bb, wrap_);
128  }
129 
130  virtual size_t id() const { return RegularLinkSelector<Bounds>::id; }
131 
132  private:
133  int dim_;
134 
135  DirMap dir_map_;
136  DirVec dir_vec_;
137 
138  Bounds core_;
139  Bounds bounds_;
140  std::vector<Bounds> nbr_bounds_;
141  std::vector<Direction> wrap_;
142  };
143 
144  // Other cover candidates: KDTreeLink, AMRGridLink
145 
146  struct LinkFactory
147  {
148  public:
149  static Link* create(size_t id)
150  {
151  // not pretty, but will do for now
152  if (id == 0)
153  return new Link;
154  else if (id == 1)
155  return new RegularGridLink(0, DiscreteBounds(), DiscreteBounds());
156  else if (id == 2)
158  else
159  return 0;
160  }
161 
162  inline static void save(BinaryBuffer& bb, const Link* l);
163  inline static Link* load(BinaryBuffer& bb);
164  };
165 }
166 
167 
168 void
169 diy::LinkFactory::
170 save(BinaryBuffer& bb, const Link* l)
171 {
172  diy::save(bb, l->id());
173  l->save(bb);
174 }
175 
176 diy::Link*
177 diy::LinkFactory::
178 load(BinaryBuffer& bb)
179 {
180  size_t id;
181  diy::load(bb, id);
182  Link* l = create(id);
183  l->load(bb);
184  return l;
185 }
186 
187 int
188 diy::Link::
189 find(int gid) const
190 {
191  for (unsigned i = 0; i < (unsigned)size(); ++i)
192  {
193  if (target(i).gid == gid)
194  return i;
195  }
196  return -1;
197 }
198 int
199 diy::Link::
200 size_unique() const
201 {
202  std::vector<BlockID> tmp(neighbors_.begin(), neighbors_.end());
203  std::sort(tmp.begin(), tmp.end());
204  return std::unique(tmp.begin(), tmp.end()) - tmp.begin();
205 }
206 
207 template<class Bounds>
208 int
210 direction(Direction dir) const
211 {
212  DirMap::const_iterator it = dir_map_.find(dir);
213  if (it == dir_map_.end())
214  return -1;
215  else
216  return it->second;
217 }
218 
219 #endif
void load(BinaryBuffer &bb, T &x)
Loads x from bb by calling diy::Serialization<T>::load(bb,x).
Definition: serialization.hpp:106
Definition: types.hpp:10
void save(BinaryBuffer &bb, const T &x)
Saves x to bb by calling diy::Serialization<T>::save(bb,x).
Definition: serialization.hpp:102
virtual int rank(int gid) const =0
returns the process rank of the block with global id gid (need not be local)
Definition: assigner.hpp:11
Definition: types.hpp:16
A serialization buffer.
Definition: serialization.hpp:19
void sort(Master &master, const Assigner &assigner, std::vector< T > Block::*values, std::vector< T > Block::*samples, size_t num_samples, const Cmp &cmp, int k=2, bool samples_only=false)
sample sort values of each block, store the boundaries between blocks in samples
Definition: algorithms.hpp:25