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