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 using Neighbors = std::vector<BlockID>;
19
~Link()20 virtual ~Link() {} // need to be able to delete derived classes
21
size() const22 int size() const { return static_cast<int>(neighbors_.size()); }
23 inline
24 int size_unique() const;
target(int i) const25 BlockID target(int i) const { return neighbors_[static_cast<size_t>(i)]; }
target(int i)26 BlockID& target(int i) { return neighbors_[static_cast<size_t>(i)]; }
27 inline
28 int find(int gid) const;
29
add_neighbor(const BlockID & block)30 void add_neighbor(const BlockID& block) { neighbors_.push_back(block); }
31
fix(const Assigner & assigner)32 void fix(const Assigner& assigner) { for (unsigned i = 0; i < neighbors_.size(); ++i) { neighbors_[i].proc = assigner.rank(neighbors_[i].gid); } }
33
swap(Link & other)34 void swap(Link& other) { neighbors_.swap(other.neighbors_); }
35
36 const Neighbors&
neighbors() const37 neighbors() const { return neighbors_; }
38 Neighbors&
neighbors()39 neighbors() { return neighbors_; }
40
save(BinaryBuffer & bb) const41 virtual void save(BinaryBuffer& bb) const { diy::save(bb, neighbors_); }
load(BinaryBuffer & bb)42 virtual void load(BinaryBuffer& bb) { diy::load(bb, neighbors_); }
43
id() const44 virtual size_t id() const { return 0; }
45
46 private:
47 Neighbors neighbors_;
48 };
49
50 template<class Bounds_>
51 class RegularLink;
52
53 typedef RegularLink<DiscreteBounds> RegularGridLink;
54 typedef RegularLink<ContinuousBounds> RegularContinuousLink;
55
56 // Selector between regular discrete and contious links given bounds type
57 template<class Bounds_>
58 struct RegularLinkSelector;
59
60 template<>
61 struct RegularLinkSelector<DiscreteBounds>
62 {
63 typedef RegularGridLink type;
64 static const size_t id = 1;
65 };
66
67 template<>
68 struct RegularLinkSelector<ContinuousBounds>
69 {
70 typedef RegularContinuousLink type;
71 static const size_t id = 2;
72 };
73
74
75 // for a regular decomposition, it makes sense to address the neighbors by direction
76 // and store local and neighbor bounds
77 template<class Bounds_>
78 class RegularLink: public Link
79 {
80 public:
81 typedef Bounds_ Bounds;
82
83 typedef std::map<Direction, int> DirMap;
84 typedef std::vector<Direction> DirVec;
85
86 public:
RegularLink(int dim,const Bounds & core__,const Bounds & bounds__)87 RegularLink(int dim, const Bounds& core__, const Bounds& bounds__):
88 dim_(dim), core_(core__), bounds_(bounds__) {}
89
90 // dimension
dimension() const91 int dimension() const { return dim_; }
92
93 // direction
94 int direction(Direction dir) const; // convert direction to a neighbor (-1 if no neighbor)
direction(int i) const95 Direction direction(int i) const { return dir_vec_[i]; }
add_direction(Direction dir)96 void add_direction(Direction dir) { int c = dir_map_.size(); dir_map_[dir] = c; dir_vec_.push_back(dir); }
97
98 // wrap
add_wrap(Direction dir)99 void add_wrap(Direction dir) { wrap_.push_back(dir); }
wrap(int i) const100 Direction wrap(int i) const { return wrap_[i]; }
wrap(int i)101 Direction& wrap(int i) { return wrap_[i]; }
102
103 // bounds
core() const104 const Bounds& core() const { return core_; }
core()105 Bounds& core() { return core_; }
bounds() const106 const Bounds& bounds() const { return bounds_; }
bounds()107 Bounds& bounds() { return bounds_; }
bounds(int i) const108 const Bounds& bounds(int i) const { return nbr_bounds_[i]; }
add_bounds(const Bounds & bounds__)109 void add_bounds(const Bounds& bounds__) { nbr_bounds_.push_back(bounds__); }
110
swap(RegularLink & other)111 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_); }
112
save(BinaryBuffer & bb) const113 void save(BinaryBuffer& bb) const
114 {
115 Link::save(bb);
116 diy::save(bb, dim_);
117 diy::save(bb, dir_map_);
118 diy::save(bb, dir_vec_);
119 diy::save(bb, core_);
120 diy::save(bb, bounds_);
121 diy::save(bb, nbr_bounds_);
122 diy::save(bb, wrap_);
123 }
124
load(BinaryBuffer & bb)125 void load(BinaryBuffer& bb)
126 {
127 Link::load(bb);
128 diy::load(bb, dim_);
129 diy::load(bb, dir_map_);
130 diy::load(bb, dir_vec_);
131 diy::load(bb, core_);
132 diy::load(bb, bounds_);
133 diy::load(bb, nbr_bounds_);
134 diy::load(bb, wrap_);
135 }
136
id() const137 virtual size_t id() const { return RegularLinkSelector<Bounds>::id; }
138
139 private:
140 int dim_;
141
142 DirMap dir_map_;
143 DirVec dir_vec_;
144
145 Bounds core_;
146 Bounds bounds_;
147 std::vector<Bounds> nbr_bounds_;
148 std::vector<Direction> wrap_;
149 };
150
151 // Other cover candidates: KDTreeLink, AMRGridLink
152
153 struct LinkFactory
154 {
155 public:
creatediy::LinkFactory156 static Link* create(size_t id)
157 {
158 // not pretty, but will do for now
159 if (id == 0)
160 return new Link;
161 else if (id == 1)
162 return new RegularGridLink(0, DiscreteBounds(), DiscreteBounds());
163 else if (id == 2)
164 return new RegularContinuousLink(0, ContinuousBounds(), ContinuousBounds());
165 else
166 return 0;
167 }
168
169 inline static void save(BinaryBuffer& bb, const Link* l);
170 inline static Link* load(BinaryBuffer& bb);
171 };
172 }
173
174
175 void
176 diy::LinkFactory::
save(BinaryBuffer & bb,const Link * l)177 save(BinaryBuffer& bb, const Link* l)
178 {
179 diy::save(bb, l->id());
180 l->save(bb);
181 }
182
183 diy::Link*
184 diy::LinkFactory::
load(BinaryBuffer & bb)185 load(BinaryBuffer& bb)
186 {
187 size_t id;
188 diy::load(bb, id);
189 Link* l = create(id);
190 l->load(bb);
191 return l;
192 }
193
194 int
195 diy::Link::
find(int gid) const196 find(int gid) const
197 {
198 for (int i = 0; i < size(); ++i)
199 {
200 if (target(i).gid == gid)
201 return i;
202 }
203 return -1;
204 }
205 int
206 diy::Link::
size_unique() const207 size_unique() const
208 {
209 std::vector<BlockID> tmp(neighbors_.begin(), neighbors_.end());
210 std::sort(tmp.begin(), tmp.end());
211 return static_cast<int>(std::unique(tmp.begin(), tmp.end()) - tmp.begin());
212 }
213
214 template<class Bounds>
215 int
216 diy::RegularLink<Bounds>::
direction(Direction dir) const217 direction(Direction dir) const
218 {
219 DirMap::const_iterator it = dir_map_.find(dir);
220 if (it == dir_map_.end())
221 return -1;
222 else
223 return it->second;
224 }
225
226 #endif
227