DIY 3.0 data-parallel out-of-core C++ library

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Examples

- File List

All Classes Namespaces Functions Typedefs Groups Pages
decomposition.hpp
1 #ifndef DIY_DECOMPOSITION_HPP
2 #define DIY_DECOMPOSITION_HPP
3
4 #include <vector>
5 #include <algorithm>
6 #include <iostream>
7 #include <cmath>
8 #include <sstream>
9 #include <stdexcept>
10
11 #include "link.hpp"
12 #include "assigner.hpp"
13 #include "master.hpp"
14
15 namespace diy
16 {
17 namespace detail
18 {
19 template<class Bounds_, class Enable = void>
20 struct BoundsHelper;
21
22 // discrete bounds
23 template<class Bounds>
24 struct BoundsHelper<Bounds, typename std::enable_if<std::is_integral<typename Bounds::Coordinate>::value>::type>
25 {
26 using Coordinate = typename Bounds::Coordinate;
27
28 static Coordinate from(int i, int n, Coordinate min, Coordinate max, bool) { return min + (max - min + 1)/n * i; }
29 static Coordinate to (int i, int n, Coordinate min, Coordinate max, bool shared_face)
30 {
31 if (i == n - 1)
32 return max;
33 else
34 return from(i+1, n, min, max, shared_face) - (shared_face ? 0 : 1);
35 }
36
37 static int lower(Coordinate x, int n, Coordinate min, Coordinate max, bool shared)
38 {
39 Coordinate width = (max - min + 1)/n;
40 Coordinate res = (x - min)/width;
41 if (res >= n) res = n - 1;
42
43 if (shared && x == from(res, n, min, max, shared))
44 --res;
45 return res;
46 }
47 static int upper(Coordinate x, int n, Coordinate min, Coordinate max, bool shared)
48 {
49 Coordinate width = (max - min + 1)/n;
50 Coordinate res = (x - min)/width + 1;
51 if (shared && x == from(res, n, min, max, shared))
52 ++res;
53 return res;
54 }
55 };
56
57 // continuous bounds
58 template<class Bounds>
59 struct BoundsHelper<Bounds, typename std::enable_if<std::is_floating_point<typename Bounds::Coordinate>::value>::type>
60 {
61 using Coordinate = typename Bounds::Coordinate;
62
63 static Coordinate from(int i, int n, Coordinate min, Coordinate max, bool) { return min + (max - min)/n * i; }
64 static Coordinate to (int i, int n, Coordinate min, Coordinate max, bool) { return min + (max - min)/n * (i+1); }
65
66 static int lower(Coordinate x, int n, Coordinate min, Coordinate max, bool) { Coordinate width = (max - min)/n; Coordinate res = std::floor((x - min)/width); if (min + res*width == x) return (res - 1); else return res; }
67 static int upper(Coordinate x, int n, Coordinate min, Coordinate max, bool) { Coordinate width = (max - min)/n; Coordinate res = std::ceil ((x - min)/width); if (min + res*width == x) return (res + 1); else return res; }
68 };
69 }
70
74 template<class Bounds_>
75 struct RegularDecomposer
76 {
77 typedef Bounds_ Bounds;
78 typedef typename BoundsValue<Bounds>::type Coordinate;
79 typedef typename RegularLinkSelector<Bounds>::type Link;
80
81 using Creator = std::function<void(int, Bounds, Bounds, Bounds, Link)>;
82 using Updater = std::function<void(int, int, Bounds, Bounds, Bounds, Link)>;
83
84 typedef std::vector<bool> BoolVector;
85 typedef std::vector<Coordinate> CoordinateVector;
86 typedef std::vector<int> DivisionsVector;
87
96 RegularDecomposer(int dim_,
97 const Bounds& domain_,
98 int nblocks_,
99 BoolVector share_face_ = BoolVector(),
100 BoolVector wrap_ = BoolVector(),
101 CoordinateVector ghosts_ = CoordinateVector(),
102 DivisionsVector divisions_ = DivisionsVector()):
103 dim(dim_), domain(domain_), nblocks(nblocks_),
104 share_face(share_face_),
105 wrap(wrap_), ghosts(ghosts_), divisions(divisions_)
106 {
107 if ((int) share_face.size() < dim) share_face.resize(dim);
108 if ((int) wrap.size() < dim) wrap.resize(dim);
109 if ((int) ghosts.size() < dim) ghosts.resize(dim);
110 if ((int) divisions.size() < dim) divisions.resize(dim);
111
112 fill_divisions(divisions);
113 }
114
115 // Calls create(int gid, const Bounds& bounds, const Link& link)
116 void decompose(int rank, const Assigner& assigner, const Creator& create);
117
118 void decompose(int rank, const Assigner& assigner, Master& master, const Updater& update);
119
120 void decompose(int rank, const Assigner& assigner, Master& master);
121
122 // find lowest gid that owns a particular point
123 template<class Point>
124 int lowest_gid(const Point& p) const;
125
126 void gid_to_coords(int gid, DivisionsVector& coords) const { gid_to_coords(gid, coords, divisions); }
127 int coords_to_gid(const DivisionsVector& coords) const { return coords_to_gid(coords, divisions); }
128 void fill_divisions(std::vector<int>& divisions) const;
129
130 void fill_bounds(Bounds& bounds, const DivisionsVector& coords, bool add_ghosts = false) const;
131 void fill_bounds(Bounds& bounds, int gid, bool add_ghosts = false) const;
132
133 static bool all(const std::vector<int>& v, int x);
134 static void gid_to_coords(int gid, DivisionsVector& coords, const DivisionsVector& divisions);
135 static int coords_to_gid(const DivisionsVector& coords, const DivisionsVector& divisions);
136
137 static void factor(std::vector<unsigned>& factors, int n);
138
139 // Point to GIDs functions
140 template<class Point>
141 void point_to_gids(std::vector<int>& gids, const Point& p) const;
142
144 template<class Point>
145 int point_to_gid(const Point& p) const;
146
147 template<class Point>
148 int num_gids(const Point& p) const;
149
150 template<class Point>
151 void top_bottom(int& top, int& bottom, const Point& p, int axis) const;
152
153
154 int dim;
155 Bounds domain;
156 int nblocks;
157 BoolVector share_face;
158 BoolVector wrap;
159 CoordinateVector ghosts;
160 DivisionsVector divisions;
161
162 };
163
180 template<class Bounds>
181 void decompose(int dim,
182 int rank,
183 const Bounds& domain,
184 const Assigner& assigner,
185 const typename RegularDecomposer<Bounds>::Creator& create,
186 typename RegularDecomposer<Bounds>::BoolVector share_face = typename RegularDecomposer<Bounds>::BoolVector(),
187 typename RegularDecomposer<Bounds>::BoolVector wrap = typename RegularDecomposer<Bounds>::BoolVector(),
188 typename RegularDecomposer<Bounds>::CoordinateVector ghosts = typename RegularDecomposer<Bounds>::CoordinateVector(),
189 typename RegularDecomposer<Bounds>::DivisionsVector divs = typename RegularDecomposer<Bounds>::DivisionsVector())
190 {
191 RegularDecomposer<Bounds>(dim, domain, assigner.nblocks(), share_face, wrap, ghosts, divs).decompose(rank, assigner, create);
192 }
193
210 template<class Bounds>
211 void decompose(int dim,
212 int rank,
213 const Bounds& domain,
214 const Assigner& assigner,
215 Master& master,
216 typename RegularDecomposer<Bounds>::BoolVector share_face = typename RegularDecomposer<Bounds>::BoolVector(),
217 typename RegularDecomposer<Bounds>::BoolVector wrap = typename RegularDecomposer<Bounds>::BoolVector(),
218 typename RegularDecomposer<Bounds>::CoordinateVector ghosts = typename RegularDecomposer<Bounds>::CoordinateVector(),
219 typename RegularDecomposer<Bounds>::DivisionsVector divs = typename RegularDecomposer<Bounds>::DivisionsVector())
220 {
221 RegularDecomposer<Bounds>(dim, domain, assigner.nblocks(), share_face, wrap, ghosts, divs).decompose(rank, assigner, master);
222 }
223
233 inline
234 void decompose(int rank,
235 const Assigner& assigner,
236 Master& master)
237 {
238 std::vector<int> local_gids;
239 assigner.local_gids(rank, local_gids);
240
241 for (size_t i = 0; i < local_gids.size(); ++i)
242 master.add(local_gids[i], master.create(), new diy::Link);
243 }
244
254 template<class Bounds>
255 void decompose(int dim,
256 int rank,
257 const Bounds& domain,
258 const Assigner& assigner,
259 Master& master,
260 const typename RegularDecomposer<Bounds>::Updater& update,
261 typename RegularDecomposer<Bounds>::BoolVector share_face =
262 typename RegularDecomposer<Bounds>::BoolVector(),
263 typename RegularDecomposer<Bounds>::BoolVector wrap =
264 typename RegularDecomposer<Bounds>::BoolVector(),
265 typename RegularDecomposer<Bounds>::CoordinateVector ghosts =
266 typename RegularDecomposer<Bounds>::CoordinateVector(),
267 typename RegularDecomposer<Bounds>::DivisionsVector divs =
268 typename RegularDecomposer<Bounds>::DivisionsVector())
269 {
270 RegularDecomposer<Bounds>(dim, domain, assigner.nblocks(), share_face, wrap, ghosts, divs).
271 decompose(rank, assigner, master, update);
272 }
273
276 }
277
278 // decomposes domain and adds blocks to the master
279 template<class Bounds>
280 void
281 diy::RegularDecomposer<Bounds>::
282 decompose(int rank, const Assigner& assigner, Master& master)
283 {
284 decompose(rank, assigner, [&master](int gid, const Bounds& core, const Bounds& bounds, const Bounds& domain, const Link& link)
285 {
286 void* b = master.create();
287 Link* l = new Link(link);
288 master.add(gid, b, l);
289 });
290 }
291
292 template<class Bounds>
293 void
294 diy::RegularDecomposer<Bounds>::
295 decompose(int rank, const Assigner& assigner, const Creator& create)
296 {
297 std::vector<int> gids;
298 assigner.local_gids(rank, gids);
299 for (int i = 0; i < (int)gids.size(); ++i)
300 {
301 int gid = gids[i];
302
303 DivisionsVector coords;
304 gid_to_coords(gid, coords);
305
306 Bounds core, bounds;
307 fill_bounds(core, coords);
308 fill_bounds(bounds, coords, true);
309
310 // Fill link with all the neighbors
311 Link link(dim, core, bounds);
312 std::vector<int> offsets(dim, -1);
313 offsets[0] = -2;
314 while (!all(offsets, 1))
315 {
316 // next offset
317 int i;
318 for (i = 0; i < dim; ++i)
319 if (offsets[i] == 1)
320 offsets[i] = -1;
321 else
322 break;
323 ++offsets[i];
324
325 if (all(offsets, 0)) continue; // skip ourselves
326
327 DivisionsVector nhbr_coords(dim);
328 Direction dir, wrap_dir;
329 bool inbounds = true;
330 for (int i = 0; i < dim; ++i)
331 {
332 nhbr_coords[i] = coords[i] + offsets[i];
333
334 // wrap
335 if (nhbr_coords[i] < 0)
336 {
337 if (wrap[i])
338 {
339 nhbr_coords[i] = divisions[i] - 1;
340 wrap_dir[i] = -1;
341 }
342 else
343 inbounds = false;
344 }
345
346 if (nhbr_coords[i] >= divisions[i])
347 {
348 if (wrap[i])
349 {
350 nhbr_coords[i] = 0;
351 wrap_dir[i] = 1;
352 }
353 else
354 inbounds = false;
355 }
356
357 // NB: this needs to match the addressing scheme in dir_t (in constants.h)
358 if (offsets[i] == -1 || offsets[i] == 1)
359 dir[i] = offsets[i];
360 }
361 if (!inbounds) continue;
362
363 int nhbr_gid = coords_to_gid(nhbr_coords);
364 BlockID bid; bid.gid = nhbr_gid; bid.proc = assigner.rank(nhbr_gid);
365 link.add_neighbor(bid);
366
367 Bounds nhbr_bounds;
368 fill_bounds(nhbr_bounds, nhbr_coords);
369 link.add_bounds(nhbr_bounds);
370
371 link.add_direction(dir);
372 link.add_wrap(wrap_dir);
373 }
374
375 create(gid, core, bounds, domain, link);
376 }
377 }
378
379 // decomposes domain but does not add blocks to master, assumes they were added already
380 template<class Bounds>
381 void
382 diy::RegularDecomposer<Bounds>::
383 decompose(int rank, const Assigner& assigner, Master& master, const Updater& update)
384 {
385 decompose(rank, assigner, [&master,&update](int gid, const Bounds& core, const Bounds& bounds, const Bounds& domain, const Link& link)
386 {
387 int lid = master.lid(gid);
388 Link* l = new Link(link);
389 master.replace_link(lid, l);
390 update(gid, lid, core, bounds, domain, *l);
391 });
392 }
393
394 template<class Bounds>
395 bool
396 diy::RegularDecomposer<Bounds>::
397 all(const std::vector<int>& v, int x)
398 {
399 for (unsigned i = 0; i < v.size(); ++i)
400 if (v[i] != x)
401 return false;
402 return true;
403 }
404
405 template<class Bounds>
406 void
407 diy::RegularDecomposer<Bounds>::
408 gid_to_coords(int gid, DivisionsVector& coords, const DivisionsVector& divisions)
409 {
410 int dim = divisions.size();
411 for (int i = 0; i < dim; ++i)
412 {
413 coords.push_back(gid % divisions[i]);
414 gid /= divisions[i];
415 }
416 }
417
418 template<class Bounds>
419 int
420 diy::RegularDecomposer<Bounds>::
421 coords_to_gid(const DivisionsVector& coords, const DivisionsVector& divisions)
422 {
423 int gid = 0;
424 for (int i = coords.size() - 1; i >= 0; --i)
425 {
426 gid *= divisions[i];
427 gid += coords[i];
428 }
429 return gid;
430 }
431
434 template<class Bounds>
435 void
436 diy::RegularDecomposer<Bounds>::
437 fill_bounds(Bounds& bounds,
438 const DivisionsVector& coords,
439 bool add_ghosts)
440 const
441 {
442 for (int i = 0; i < dim; ++i)
443 {
444 bounds.min[i] = detail::BoundsHelper<Bounds>::from(coords[i], divisions[i], domain.min[i], domain.max[i], share_face[i]);
445 bounds.max[i] = detail::BoundsHelper<Bounds>::to (coords[i], divisions[i], domain.min[i], domain.max[i], share_face[i]);
446 }
447
448 for (int i = dim; i < DIY_MAX_DIM; ++i) // set the unused dimension to 0
449 {
450 bounds.min[i] = 0;
451 bounds.max[i] = 0;
452 }
453
454 if (!add_ghosts)
455 return;
456
457 for (int i = 0; i < dim; ++i)
458 {
459 if (wrap[i])
460 {
461 bounds.min[i] -= ghosts[i];
462 bounds.max[i] += ghosts[i];
463 } else
464 {
465 bounds.min[i] = std::max(domain.min[i], bounds.min[i] - ghosts[i]);
466 bounds.max[i] = std::min(domain.max[i], bounds.max[i] + ghosts[i]);
467 }
468 }
469 }
470
473 template<class Bounds>
474 void
475 diy::RegularDecomposer<Bounds>::
476 fill_bounds(Bounds& bounds,
477 int gid,
478 bool add_ghosts)
479 const
480 {
481 DivisionsVector coords;
482 gid_to_coords(gid, coords);
483 if (add_ghosts)
484 fill_bounds(bounds, coords, true);
485 else
486 fill_bounds(bounds, coords);
487 }
488
489 namespace diy { namespace detail {
490 // current state of division in one dimension used in fill_divisions below
491 template<class Coordinate>
492 struct Div
493 {
494 int dim; // 0, 1, 2, etc. e.g. for x, y, z etc.
495 int nb; // number of blocks so far in this dimension
496 Coordinate b_size; // block size so far in this dimension
497
498 // sort on descending block size unless tied, in which case
499 // sort on ascending num blocks in current dim unless tied, in which case
500 // sort on ascending dimension
501 bool operator<(Div rhs) const
502 {
503 // sort on second value of the pair unless tied, in which case sort on first
504 if (b_size == rhs.b_size)
505 {
506 if (nb == rhs.nb)
507 return(dim < rhs.dim);
508 return(nb < rhs.nb);
509 }
510 return(b_size > rhs.b_size);
511 }
512 };
513 } }
514
515 template<class Bounds>
516 void
517 diy::RegularDecomposer<Bounds>::
518 fill_divisions(std::vector<int>& divisions) const
519 {
520 // prod = number of blocks unconstrained by user; c = number of unconstrained dimensions
521 int prod = 1; int c = 0;
522 for (int i = 0; i < dim; ++i)
523 if (divisions[i] != 0)
524 {
525 prod *= divisions[i];
526 ++c;
527 }
528
529 if (nblocks % prod != 0)
530 throw std::runtime_error("Total number of blocks cannot be factored into provided divs");
531
532 if (c == (int) divisions.size()) // nothing to do; user provided all divs
533 return;
534
535 // factor number of blocks left in unconstrained dimensions
536 // factorization is sorted from smallest to largest factors
537 std::vector<unsigned> factors;
538 factor(factors, nblocks/prod);
539
540 using detail::Div;
541 std::vector< Div<Coordinate> > missing_divs; // pairs consisting of (dim, #divs)
542
543 // init missing_divs
544 for (int i = 0; i < dim; i++)
545 {
546 if (divisions[i] == 0)
547 {
548 Div<Coordinate> div;
549 div.dim = i;
550 div.nb = 1;
551 div.b_size = domain.max[i] - domain.min[i];
552 missing_divs.push_back(div);
553 }
554 }
555
556 // iterate over factorization of number of blocks (factors are sorted smallest to largest)
557 // NB: using int instead of size_t because must be negative in order to break out of loop
558 for (int i = factors.size() - 1; i >= 0; --i)
559 {
560 // fill in missing divs by dividing dimension w/ largest block size
561 // except when this would be illegal (resulting in bounds.max < bounds.min;
562 // only a problem for discrete bounds
563
564 // sort on decreasing block size
565 std::sort(missing_divs.begin(), missing_divs.end());
566
567 // split the dimension with the largest block size (first element in vector)
568 Coordinate min =
569 detail::BoundsHelper<Bounds>::from(0,
570 missing_divs[0].nb * factors[i],
571 domain.min[missing_divs[0].dim],
572 domain.max[missing_divs[0].dim],
573 share_face[missing_divs[0].dim]);
574 Coordinate max =
575 detail::BoundsHelper<Bounds>::to(0,
576 missing_divs[0].nb * factors[i],
577 domain.min[missing_divs[0].dim],
578 domain.max[missing_divs[0].dim],
579 share_face[missing_divs[0].dim]);
580 if (max >= min)
581 {
582 missing_divs[0].nb *= factors[i];
583 missing_divs[0].b_size = max - min;
584 }
585 else
586 {
587 std::ostringstream oss;
588 oss << "Unable to decompose domain into " << nblocks << " blocks: " << min << " " << max;
589 throw std::runtime_error(oss.str());
590 }
591 }
592
593 // assign the divisions
594 for (size_t i = 0; i < missing_divs.size(); i++)
595 divisions[missing_divs[i].dim] = missing_divs[i].nb;
596 }
597
598 template<class Bounds>
599 void
600 diy::RegularDecomposer<Bounds>::
601 factor(std::vector<unsigned>& factors, int n)
602 {
603 while (n != 1)
604 for (int i = 2; i <= n; ++i)
605 {
606 if (n % i == 0)
607 {
608 factors.push_back(i);
609 n /= i;
610 break;
611 }
612 }
613 }
614
615 // Point to GIDs
616 // TODO: deal with wrap correctly
617 // TODO: add an optional ghosts argument to ignore ghosts (if we want to find the true owners, or something like that)
618 template<class Bounds>
619 template<class Point>
620 void
621 diy::RegularDecomposer<Bounds>::
622 point_to_gids(std::vector<int>& gids, const Point& p) const
623 {
624 std::vector< std::pair<int, int> > ranges(dim);
625 for (int i = 0; i < dim; ++i)
626 top_bottom(ranges[i].second, ranges[i].first, p, i);
627
628 // look up gids for all combinations
629 DivisionsVector coords(dim), location(dim);
630 while(location.back() < ranges.back().second - ranges.back().first)
631 {
632 for (int i = 0; i < dim; ++i)
633 coords[i] = ranges[i].first + location[i];
634 gids.push_back(coords_to_gid(coords, divisions));
635
636 location[0]++;
637 unsigned i = 0;
638 while (i < dim-1 && location[i] == ranges[i].second - ranges[i].first)
639 {
640 location[i] = 0;
641 ++i;
642 location[i]++;
643 }
644 }
645 }
646
647 template<class Bounds>
648 template<class Point>
649 int
650 diy::RegularDecomposer<Bounds>::
651 point_to_gid(const Point& p) const
652 {
653 int gid = 0;
654 for (int axis = dim - 1; axis >= 0; --axis)
655 {
656 int bottom = detail::BoundsHelper<Bounds>::lower(p[axis], divisions[axis], domain.min[axis], domain.max[axis], share_face[axis]);
657 bottom = std::max(0, bottom);
658
659 // coupled with coords_to_gid
660 gid *= divisions[axis];
661 gid += bottom;
662 }
663
664 return gid;
665 }
666
667 template<class Bounds>
668 template<class Point>
669 int
670 diy::RegularDecomposer<Bounds>::
671 num_gids(const Point& p) const
672 {
673 int res = 1;
674 for (int i = 0; i < dim; ++i)
675 {
676 int top, bottom;
677 top_bottom(top, bottom, p, i);
678 res *= top - bottom;
679 }
680 return res;
681 }
682
683 template<class Bounds>
684 template<class Point>
685 void
686 diy::RegularDecomposer<Bounds>::
687 top_bottom(int& top, int& bottom, const Point& p, int axis) const
688 {
689 Coordinate l = p[axis] - ghosts[axis];
690 Coordinate r = p[axis] + ghosts[axis];
691
692 top = detail::BoundsHelper<Bounds>::upper(r, divisions[axis], domain.min[axis], domain.max[axis], share_face[axis]);
693 bottom = detail::BoundsHelper<Bounds>::lower(l, divisions[axis], domain.min[axis], domain.max[axis], share_face[axis]);
694
695 if (!wrap[axis])
696 {
697 bottom = std::max(0, bottom);
698 top = std::min(divisions[axis], top);
699 }
700 }
701
702 // find lowest gid that owns a particular point
703 template<class Bounds>
704 template<class Point>
705 int
706 diy::RegularDecomposer<Bounds>::
707 lowest_gid(const Point& p) const
708 {
709 // TODO: optimize - no need to compute all gids
710 std::vector<int> gids;
711 point_to_gids(gids, p);
712 std::sort(gids.begin(), gids.end());
713 return gids[0];
714 }
715
716 #endif
diy::RegularDecomposer::point_to_gid
int point_to_gid(const Point &p) const
returns gid of a block that contains the point; ignores ghosts
Definition: decomposition.hpp:651
diy::Assigner::nblocks
int nblocks() const
returns the total number of global blocks
Definition: assigner.hpp:26
diy::RegularDecomposer
Decomposes a regular (discrete or continuous) domain into even blocks; creates Links with Bounds alon...
Definition: decomposition.hpp:75
diy::RegularLinkSelector
Definition: link.hpp:51
diy::decompose
void decompose(int dim, int rank, const Bounds &domain, const Assigner &assigner, Master &master, const typename RegularDecomposer< Bounds >::Updater &update, typename RegularDecomposer< Bounds >::BoolVector share_face=typename RegularDecomposer< Bounds >::BoolVector(), typename RegularDecomposer< Bounds >::BoolVector wrap=typename RegularDecomposer< Bounds >::BoolVector(), typename RegularDecomposer< Bounds >::CoordinateVector ghosts=typename RegularDecomposer< Bounds >::CoordinateVector(), typename RegularDecomposer< Bounds >::DivisionsVector divs=typename RegularDecomposer< Bounds >::DivisionsVector())
Add a decomposition (modify links) of an existing set of blocks that were added to the master previou...
Definition: decomposition.hpp:255
diy::Assigner
Definition: assigner.hpp:11
diy::decompose
void decompose(int dim, int rank, const Bounds &domain, const Assigner &assigner, const typename RegularDecomposer< Bounds >::Creator &create, typename RegularDecomposer< Bounds >::BoolVector share_face=typename RegularDecomposer< Bounds >::BoolVector(), typename RegularDecomposer< Bounds >::BoolVector wrap=typename RegularDecomposer< Bounds >::BoolVector(), typename RegularDecomposer< Bounds >::CoordinateVector ghosts=typename RegularDecomposer< Bounds >::CoordinateVector(), typename RegularDecomposer< Bounds >::DivisionsVector divs=typename RegularDecomposer< Bounds >::DivisionsVector())
Decomposes the domain into a prescribed pattern of blocks.
Definition: decomposition.hpp:181
diy::Master::add
int add(int gid, void *b, Link *l)
add a block
Definition: master.hpp:658
diy::Master
Definition: master.hpp:35
diy::Link
Definition: link.hpp:15
diy::Point
Definition: point.hpp:15
diy::Bounds
Definition: types.hpp:16
diy::Assigner::local_gids
virtual void local_gids(int rank, std::vector< int > &gids) const =0
gets the local gids for a given process rank
diy::RegularDecomposer::RegularDecomposer
RegularDecomposer(int dim_, const Bounds &domain_, int nblocks_, BoolVector share_face_=BoolVector(), BoolVector wrap_=BoolVector(), CoordinateVector ghosts_=CoordinateVector(), DivisionsVector divisions_=DivisionsVector())
Definition: decomposition.hpp:96
diy::RegularDecomposer::fill_bounds
void fill_bounds(Bounds &bounds, const DivisionsVector &coords, bool add_ghosts=false) const
Gets the bounds, with or without ghosts, for a block specified by its block coordinates.
Definition: decomposition.hpp:437
diy::sort
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