Zoltan2
Loading...
Searching...
No Matches
Zoltan2_CoordinatePartitioningGraph.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Zoltan2: A package of combinatorial algorithms for scientific computing
4//
5// Copyright 2012 NTESS and the Zoltan2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef _ZOLTAN2_COORDCOMMGRAPH_HPP_
11#define _ZOLTAN2_COORDCOMMGRAPH_HPP_
12
13
14#include <cmath>
15#include <limits>
16#include <iostream>
17#include <vector>
18#include <set>
19#include <fstream>
20#include "Teuchos_CommHelpers.hpp"
21#include "Teuchos_Comm.hpp"
22#include "Teuchos_ArrayViewDecl.hpp"
23#include "Teuchos_RCPDecl.hpp"
25
26namespace Zoltan2{
27
28
29#define Z2_ABS(x) ((x) >= 0 ? (x) : -(x))
30
35
36public:
37 typedef double coord_t;
39
43 pID(pid),
44 dim(dim_),
45 lmins(0), lmaxs(0),
46 maxScalar (std::numeric_limits<coord_t>::max()),
47 epsilon(std::numeric_limits<coord_t>::epsilon()),
48 minHashIndices(0),
49 maxHashIndices(0),
50 gridIndices(0), neighbors()
51 {
52 lmins = new coord_t [dim];
53 lmaxs = new coord_t [dim];
54
55 minHashIndices = new part_t [dim];
56 maxHashIndices = new part_t [dim];
57 gridIndices = new std::vector <part_t> ();
58 for (int i = 0; i < dim; ++i){
59 lmins[i] = -this->maxScalar;
60 lmaxs[i] = this->maxScalar;
61 }
62 }
66 template <typename scalar_t>
67 coordinateModelPartBox(part_t pid, int dim_, scalar_t *lmi, scalar_t *lma):
68 pID(pid),
69 dim(dim_),
70 lmins(0), lmaxs(0),
71 maxScalar (std::numeric_limits<coord_t>::max()),
72 epsilon(std::numeric_limits<coord_t>::epsilon()),
73 minHashIndices(0),
74 maxHashIndices(0),
75 gridIndices(0), neighbors()
76 {
77 lmins = new coord_t [dim];
78 lmaxs = new coord_t [dim];
79 minHashIndices = new part_t [dim];
80 maxHashIndices = new part_t [dim];
81 gridIndices = new std::vector <part_t> ();
82 for (int i = 0; i < dim; ++i){
83 lmins[i] = static_cast<coord_t>(lmi[i]);
84 lmaxs[i] = static_cast<coord_t>(lma[i]);
85 }
86 }
87
88
93 pID(other.getpId()),
94 dim(other.getDim()),
95 lmins(0), lmaxs(0),
96 maxScalar (std::numeric_limits<coord_t>::max()),
97 epsilon(std::numeric_limits<coord_t>::epsilon()),
98 minHashIndices(0),
99 maxHashIndices(0),
100 gridIndices(0), neighbors()
101 {
102
103 lmins = new coord_t [dim];
104 lmaxs = new coord_t [dim];
105 minHashIndices = new part_t [dim];
106 maxHashIndices = new part_t [dim];
107 gridIndices = new std::vector <part_t> ();
108 coord_t *othermins = other.getlmins();
109 coord_t *othermaxs = other.getlmaxs();
110 for (int i = 0; i < dim; ++i){
111 lmins[i] = othermins[i];
112 lmaxs[i] = othermaxs[i];
113 }
114 }
118 delete []this->lmins;
119 delete [] this->lmaxs;
120 delete []this->minHashIndices;
121 delete [] this->maxHashIndices;
122 delete gridIndices;
123 }
124
127 void setpId(part_t pid){
128 this->pID = pid;
129 }
132 part_t getpId() const{
133 return this->pID;
134 }
135
136
139 int getDim()const{
140 return this->dim;
141 }
145 return this->lmins;
146 }
150 return this->lmaxs;
151 }
154 void computeCentroid(coord_t *centroid)const {
155 for (int i = 0; i < this->dim; i++)
156 centroid[i] = 0.5 * (this->lmaxs[i] + this->lmins[i]);
157 }
158
162 std::vector <part_t> * getGridIndices () {
163 return this->gridIndices;
164 }
165
168 std::set<part_t> *getNeighbors() {
169 return &(this->neighbors);
170 }
171
174 template <typename scalar_t>
175 bool pointInBox(int pointdim, scalar_t *point) const {
176 if (pointdim != this->dim)
177 throw std::logic_error("dim of point must match dim of box");
178 for (int i = 0; i < pointdim; i++) {
179 if (static_cast<coord_t>(point[i]) < this->lmins[i]) return false;
180 if (static_cast<coord_t>(point[i]) > this->lmaxs[i]) return false;
181 }
182 return true;
183 }
184
187 template <typename scalar_t>
188 bool boxesOverlap(int cdim, scalar_t *lower, scalar_t *upper) const {
189 if (cdim != this->dim)
190 throw std::logic_error("dim of given box must match dim of box");
191
192 // Check for at least partial overlap
193 bool found = true;
194 for (int i = 0; i < cdim; i++) {
195 if (!((static_cast<coord_t>(lower[i]) >= this->lmins[i] &&
196 static_cast<coord_t>(lower[i]) <= this->lmaxs[i])
197 // lower i-coordinate in the box
198 || (static_cast<coord_t>(upper[i]) >= this->lmins[i] &&
199 static_cast<coord_t>(upper[i]) <= this->lmaxs[i])
200 // upper i-coordinate in the box
201 || (static_cast<coord_t>(lower[i]) < this->lmins[i] &&
202 static_cast<coord_t>(upper[i]) > this->lmaxs[i]))) {
203 // i-coordinates straddle the box
204 found = false;
205 break;
206 }
207 }
208 return found;
209 }
210
214 const coordinateModelPartBox &other) const{
215
216 coord_t *omins = other.getlmins();
217 coord_t *omaxs = other.getlmaxs();
218
219 int equality = 0;
220 for (int i = 0; i < dim; ++i){
221
222 if (omins[i] - this->lmaxs[i] > epsilon ||
223 this->lmins[i] - omaxs[i] > epsilon ) {
224 return false;
225 }
226 else if (Z2_ABS(omins[i] - this->lmaxs[i]) < epsilon ||
227 Z2_ABS(this->lmins[i] - omaxs[i]) < epsilon ){
228 if (++equality > 1){
229 return false;
230 }
231 }
232 }
233 if (equality == 1) {
234 return true;
235 }
236 else {
237 std::cout << "something is wrong: equality:"
238 << equality << std::endl;
239 return false;
240 }
241 }
242
243
246 void addNeighbor(part_t nIndex){
247 neighbors.insert(nIndex);
248 }
252
253 if (neighbors.end() != neighbors.find(nIndex)){
254 return true;
255 }
256 return false;
257
258 }
259
260
264 coord_t *minMaxBoundaries,
265 coord_t *sliceSizes,
266 part_t numSlicePerDim
267 ){
268 for (int j = 0; j < dim; ++j){
269 coord_t distance = (lmins[j] - minMaxBoundaries[j]);
270 part_t minInd = 0;
271 if (distance > epsilon && sliceSizes[j] > epsilon){
272 minInd = static_cast<part_t>(floor((lmins[j] - minMaxBoundaries[j])/ sliceSizes[j]));
273 }
274
275 if(minInd >= numSlicePerDim){
276 minInd = numSlicePerDim - 1;
277 }
278 part_t maxInd = 0;
279 distance = (lmaxs[j] - minMaxBoundaries[j]);
280 if (distance > epsilon && sliceSizes[j] > epsilon){
281 maxInd = static_cast<part_t>(ceil((lmaxs[j] - minMaxBoundaries[j])/ sliceSizes[j]));
282 }
283 if(maxInd >= numSlicePerDim){
284 maxInd = numSlicePerDim - 1;
285 }
286
287 //cout << "j:" << j << " lmins:" << lmins[j] << " lmaxs:" << lmaxs[j] << endl;
288 //cout << "j:" << j << " min:" << minInd << " max:" << maxInd << endl;
289 minHashIndices[j] = minInd;
290 maxHashIndices[j] = maxInd;
291 }
292 std::vector <part_t> *in = new std::vector <part_t> ();
293 in->push_back(0);
294 std::vector <part_t> *out = new std::vector <part_t> ();
295
296 for (int j = 0; j < dim; ++j){
297
298 part_t minInd = minHashIndices[j];
299 part_t maxInd = maxHashIndices[j];
300
301
302 part_t pScale = part_t(pow (float(numSlicePerDim), int(dim - j -1)));
303
304 part_t inSize = in->size();
305
306 for (part_t k = minInd; k <= maxInd; ++k){
307 for (part_t i = 0; i < inSize; ++i){
308 out->push_back((*in)[i] + k * pScale);
309 }
310 }
311 in->clear();
312 std::vector <part_t> *tmp = in;
313 in= out;
314 out= tmp;
315 }
316
317 std::vector <part_t> *tmp = in;
318 in = gridIndices;
319 gridIndices = tmp;
320
321
322 delete in;
323 delete out;
324 }
325
328 void print(){
329 for(int i = 0; i < this->dim; ++i){
330 std::cout << "\tbox:" << this->pID << " dim:" << i << " min:" << lmins[i] << " max:" << lmaxs[i] << std::endl;
331 }
332 }
333
336 template <typename scalar_t>
337 void updateMinMax (scalar_t newBoundary, int isMax, int dimInd){
338 if (isMax){
339 lmaxs[dimInd] = static_cast<coord_t>(newBoundary);
340 }
341 else {
342 lmins[dimInd] = static_cast<coord_t>(newBoundary);
343 }
344 }
345
348 void writeGnuPlot(std::ofstream &file,std::ofstream &mm){
349 int numCorners = (int(1)<<dim);
350 coord_t *corner1 = new coord_t [dim];
351 coord_t *corner2 = new coord_t [dim];
352
353 for (int i = 0; i < dim; ++i){
354 /*
355 if (-maxScalar == lmins[i]){
356 if (lmaxs[i] > 0){
357 lmins[i] = lmaxs[i] / 2;
358 }
359 else{
360 lmins[i] = lmaxs[i] * 2;
361 }
362 }
363 */
364 //std::cout << lmins[i] << " ";
365 mm << lmins[i] << " ";
366 }
367 //std::cout << std::endl;
368 mm << std::endl;
369 for (int i = 0; i < dim; ++i){
370
371 /*
372 if (maxScalar == lmaxs[i]){
373 if (lmins[i] < 0){
374 lmaxs[i] = lmins[i] / 2;
375 }
376 else{
377 lmaxs[i] = lmins[i] * 2;
378 }
379 }
380 */
381
382 //std::cout << lmaxs[i] << " ";
383 mm << lmaxs[i] << " ";
384 }
385 //std::cout << std::endl;
386 mm << std::endl;
387
388 for (int j = 0; j < numCorners; ++j){
389 std::vector <int> neighborCorners;
390 for (int i = 0; i < dim; ++i){
391 if(int(j & (int(1)<<i)) == 0){
392 corner1[i] = lmins[i];
393 }
394 else {
395 corner1[i] = lmaxs[i];
396 }
397 if (j % (int(1)<<(i + 1)) >= (int(1)<<i)){
398 int c1 = j - (int(1)<<i);
399
400 if (c1 > 0) {
401 neighborCorners.push_back(c1);
402 }
403 }
404 else {
405
406 int c1 = j + (int(1)<<i);
407 if (c1 < (int(1) << dim)) {
408 neighborCorners.push_back(c1);
409 }
410 }
411 }
412 //std::cout << "me:" << j << " nc:" << int (neighborCorners.size()) << std::endl;
413 for (int m = 0; m < int (neighborCorners.size()); ++m){
414
415 int n = neighborCorners[m];
416 //std::cout << "me:" << j << " n:" << n << std::endl;
417 for (int i = 0; i < dim; ++i){
418 if(int(n & (int(1)<<i)) == 0){
419 corner2[i] = lmins[i];
420 }
421 else {
422 corner2[i] = lmaxs[i];
423 }
424 }
425
426 std::string arrowline = "set arrow from ";
427 for (int i = 0; i < dim - 1; ++i){
428 arrowline +=
429 Teuchos::toString<coord_t>(corner1[i]) + ",";
430 }
431 arrowline +=
432 Teuchos::toString<coord_t>(corner1[dim -1]) + " to ";
433
434 for (int i = 0; i < dim - 1; ++i){
435 arrowline +=
436 Teuchos::toString<coord_t>(corner2[i]) + ",";
437 }
438 arrowline +=
439 Teuchos::toString<coord_t>(corner2[dim -1]) +
440 " nohead\n";
441
442 file << arrowline;
443 }
444 }
445 delete []corner1;
446 delete []corner2;
447 }
448
449private:
450 part_t pID; //part Id
451 int dim; //dimension of the box
452 coord_t *lmins; //minimum boundaries of the box along all dimensions.
453 coord_t *lmaxs; //maximum boundaries of the box along all dimensions.
454 coord_t maxScalar;
455 coord_t epsilon;
456
457 //to calculate the neighbors of the box and avoid the p^2 comparisons,
458 //we use hashing. A box can be put into multiple hash buckets.
459 //the following 2 variable holds the minimum and maximum of the
460 //hash values along all dimensions.
461 part_t *minHashIndices;
462 part_t *maxHashIndices;
463
464 //result hash bucket indices.
465 std::vector <part_t> *gridIndices;
466 //neighbors of the box.
467 std::set <part_t> neighbors;
468};
469
470
475private:
476
477 typedef typename Zoltan2::coordinateModelPartBox::coord_t coord_t;
478 typedef typename Zoltan2::coordinateModelPartBox::part_t part_t;
479
480 const RCP<std::vector<Zoltan2::coordinateModelPartBox> > pBoxes;
481
482 //minimum of the maximum box boundaries
483 coord_t *minMaxBoundaries;
484 //maximum of the minimum box boundaries
485 coord_t *maxMinBoundaries;
486 //the size of each slice along dimensions
487 coord_t *sliceSizes;
488 part_t nTasks;
489 int dim;
490 //the number of slices per dimension
491 part_t numSlicePerDim;
492 //the number of grids - buckets
493 part_t numGrids;
494 //hash vector
495 std::vector <std::vector <part_t> > grids;
496 //result communication graph.
497 ArrayRCP <part_t> comXAdj;
498 ArrayRCP <part_t> comAdj;
499public:
500
504 GridHash(const RCP<std::vector<Zoltan2::coordinateModelPartBox> > &pBoxes_,
505 part_t ntasks_, int dim_):
506 pBoxes(pBoxes_),
507 minMaxBoundaries(0),
508 maxMinBoundaries(0), sliceSizes(0),
509 nTasks(ntasks_),
510 dim(dim_),
511 numSlicePerDim(part_t(pow(double(ntasks_), 1.0 / dim))),
512 numGrids(0),
513 grids(),
514 comXAdj(), comAdj()
515 {
516
517 minMaxBoundaries = new coord_t[dim];
518 maxMinBoundaries = new coord_t[dim];
519 sliceSizes = new coord_t[dim];
520 //calculate the number of slices in each dimension.
521 numSlicePerDim /= 2;
522 if (numSlicePerDim == 0) numSlicePerDim = 1;
523
524 numGrids = part_t(pow(float(numSlicePerDim), int(dim)));
525
526 //allocate memory for buckets.
527 std::vector <std::vector <part_t> > grids_ (numGrids);
528 this->grids = grids_;
529 //get the boundaries of buckets.
530 this->getMinMaxBoundaries();
531 //insert boxes to buckets
532 this->insertToHash();
533 //calculate the neighbors for each bucket.
534 part_t nCount = this->calculateNeighbors();
535
536 //allocate memory for communication graph
537 ArrayRCP <part_t> tmpComXadj(ntasks_+1);
538 ArrayRCP <part_t> tmpComAdj(nCount);
539 comXAdj = tmpComXadj;
540 comAdj = tmpComAdj;
541 //fill communication graph
542 this->fillAdjArrays();
543 }
544
545
550 delete []minMaxBoundaries;
551 delete []maxMinBoundaries;
552 delete []sliceSizes;
553 }
554
559
560 part_t adjIndex = 0;
561
562 comXAdj[0] = 0;
563 for(part_t i = 0; i < this->nTasks; ++i){
564 std::set<part_t> *neigbors = (*pBoxes)[i].getNeighbors();
565
566 part_t s = neigbors->size();
567
568 comXAdj[i+1] = comXAdj[i] + s;
569 typedef typename std::set<part_t> mySet;
570 typedef typename mySet::iterator myIT;
571 myIT it;
572 for (it=neigbors->begin(); it!=neigbors->end(); ++it)
573
574 comAdj[adjIndex++] = *it;
575 //TODO not needed anymore.
576 neigbors->clear();
577 }
578 }
579
580
581
586 ArrayRCP <part_t> &comXAdj_,
587 ArrayRCP <part_t> &comAdj_){
588 comXAdj_ = this->comXAdj;
589 comAdj_ = this->comAdj;
590 }
591
596 part_t nCount = 0;
597 for(part_t i = 0; i < this->nTasks; ++i){
598 std::vector <part_t> *gridIndices =(*pBoxes)[i].getGridIndices();
599 part_t gridCount = gridIndices->size();
600
601 for (part_t j = 0; j < gridCount; ++j){
602 part_t grid = (*gridIndices)[j];
603 part_t boxCount = grids[grid].size();
604 for (part_t k = 0; k < boxCount; ++k){
605 part_t boxIndex = grids[grid][k];
606 if (boxIndex > i){
607 if((!(*pBoxes)[i].isAlreadyNeighbor(boxIndex))&& (*pBoxes)[i].isNeighborWith((*pBoxes)[boxIndex])){
608 //cout << "i:" << i << " n:" << boxIndex << " are neighbors."<< endl;
609 (*pBoxes)[i].addNeighbor(boxIndex);
610 (*pBoxes)[boxIndex].addNeighbor(i);
611 nCount += 2;
612 }
613 }
614 }
615 }
616 }
617
618 return nCount;
619 }
620
625
626 //cout << "ntasks:" << this->nTasks << endl;
627 for(part_t i = 0; i < this->nTasks; ++i){
628 (*pBoxes)[i].setMinMaxHashIndices(minMaxBoundaries, sliceSizes, numSlicePerDim);
629
630 std::vector <part_t> *gridIndices =(*pBoxes)[i].getGridIndices();
631
632 part_t gridCount = gridIndices->size();
633 //cout << "i:" << i << " gridsize:" << gridCount << endl;
634 for (part_t j = 0; j < gridCount; ++j){
635 part_t grid = (*gridIndices)[j];
636
637 //cout << "i:" << i << " is being inserted to:" << grid << endl;
638 (grids)[grid].push_back(i);
639 }
640 }
641
642
643/*
644 for(part_t i = 0; i < grids.size(); ++i){
645 cout << "grid:" << i << " gridsuze:" << (grids)[i].size() << " elements:";
646 for(part_t j = 0; j < (grids)[i].size(); ++j){
647 cout <<(grids)[i][j] << " ";
648 }
649 cout << endl;
650
651 }
652*/
653 }
654
659 coord_t *mins = (*pBoxes)[0].getlmins();
660 coord_t *maxs = (*pBoxes)[0].getlmaxs();
661
662 for (int j = 0; j < dim; ++j){
663 minMaxBoundaries[j] = maxs[j];
664 maxMinBoundaries[j] = mins[j];
665 }
666
667 for (part_t i = 1; i < nTasks; ++i){
668
669 mins = (*pBoxes)[i].getlmins();
670 maxs = (*pBoxes)[i].getlmaxs();
671
672 for (int j = 0; j < dim; ++j){
673
674 if (minMaxBoundaries[j] > maxs[j]){
675 minMaxBoundaries[j] = maxs[j];
676 }
677 if (maxMinBoundaries[j] < mins[j]){
678 maxMinBoundaries[j] = mins[j];
679 }
680 }
681 }
682
683
684 for (int j = 0; j < dim; ++j){
685 sliceSizes[j] = (maxMinBoundaries[j] - minMaxBoundaries[j]) / numSlicePerDim;
686 if (sliceSizes[j] < 0) sliceSizes[j] = 0;
687 /*
688 cout << "dim:" << j <<
689 " minMax:" << minMaxBoundaries[j] <<
690 " maxMin:" << maxMinBoundaries[j] <<
691 " sliceSizes:" << sliceSizes[j] << endl;
692 */
693 }
694 }
695};
696/*
697template <typename coord_t,typename part_t>
698class coordinatePartBox{
699public:
700 part_t pID;
701 int dim;
702 int numCorners;
703 coord_t **corners;
704 coord_t *lmins, *gmins;
705 coord_t *lmaxs, *gmaxs;
706 coord_t maxScalar;
707 std::vector <part_t> hash_indices;
708 coordinatePartBox(part_t pid, int dim_, coord_t *lMins, coord_t *gMins,
709 coord_t *lMaxs, coord_t *gMaxs):
710 pID(pid),
711 dim(dim_),
712 numCorners(int(pow(2, dim_))),
713 corners(0),
714 lmins(lMins), gmins(gMins), lmaxs(lMaxs), gmaxs(gMaxs),
715 maxScalar (std::numeric_limits<coord_t>::max()){
716 this->corners = new coord_t *[dim];
717 for (int i = 0; i < dim; ++i){
718 this->corners[i] = new coord_t[this->numCorners];
719 lmins[i] = this->maxScalar;
720 lmaxs[i] = -this->maxScalar;
721 }
722
723
724 for (int j = 0; j < this->numCorners; ++j){
725 for (int i = 0; i < dim; ++i){
726 std::cout << "j:" << j << " i:" << i << " 2^i:" << pow(2,i) << " and:" << int(j & int(pow(2,i))) << std::endl;
727 if(int(j & int(pow(2,i))) == 0){
728 corners[i][j] = gmins[i];
729 }
730 else {
731 corners[i][j] = gmaxs[i];
732 }
733
734 }
735 }
736 }
737
738};
739
740template <typename Adapter, typename part_t>
741class CoordinateCommGraph{
742private:
743
744 typedef typename Adapter::lno_t lno_t;
745 typedef typename Adapter::gno_t gno_t;
746 typedef typename Adapter::coord_t coord_t;
747
748 const Environment *env;
749 const Teuchos::Comm<int> *comm;
750 const Zoltan2::CoordinateModel<typename Adapter::base_adapter_t> *coords;
751 const Zoltan2::PartitioningSolution<Adapter> *soln;
752 std::vector<coordinatePartBox, part_t> cpb;
753 int coordDim;
754 part_t numParts;
755
756
757public:
758
759 CoordinateCommGraph(
760 const Environment *env_,
761 const Teuchos::Comm<int> *comm_,
762 const Zoltan2::CoordinateModel<typename Adapter::base_adapter_t> *coords_,
763 const Zoltan2::PartitioningSolution<Adapter> *soln_
764 ):
765 env(env_),
766 comm(comm_),
767 coords(coords_),
768 soln(soln_),
769 coordDim (coords_->getCoordinateDim()),
770 numParts (this->soln->getActualGlobalNumberOfParts())
771 {
772 this->create_part_boxes();
773 this->hash_part_boxes();
774 this->find_neighbors();
775 }
776
777 void create_part_boxes(){
778
779
780 size_t allocSize = numParts * coordDim;
781 coord_t *lmins = new coord_t [allocSize];
782 coord_t *gmins = new coord_t [allocSize];
783 coord_t *lmaxs = new coord_t [allocSize];
784 coord_t *gmaxs = new coord_t [allocSize];
785
786 for(part_t i = 0; i < numParts; ++i){
787 coordinatePartBox tmp(
788 i,
789 this->coordDim,
790 lmins + i * coordDim,
791 gmins + i * coordDim,
792 lmaxs + i * coordDim,
793 gmaxs + i * coordDim
794 );
795 cpb.push_back(tmp);
796 }
797
798 typedef StridedData<lno_t, coord_t> input_t;
799 Teuchos::ArrayView<const gno_t> gnos;
800 Teuchos::ArrayView<input_t> xyz;
801 Teuchos::ArrayView<input_t> wgts;
802 coords->getCoordinates(gnos, xyz, wgts);
803
804 //local and global num coordinates.
805 lno_t numLocalCoords = coords->getLocalNumCoordinates();
806
807 coord_t **pqJagged_coordinates = new coord_t *[coordDim];
808
809 for (int dim=0; dim < coordDim; dim++){
810 Teuchos::ArrayRCP<const coord_t> ar;
811 xyz[dim].getInputArray(ar);
812 //pqJagged coordinate values assignment
813 pqJagged_coordinates[dim] = (coord_t *)ar.getRawPtr();
814 }
815
816 part_t *sol_part = soln->getPartList();
817 for(lno_t i = 0; i < numLocalCoords; ++i){
818 part_t p = sol_part[i];
819 cpb[p].updateMinMax(pqJagged_coordinates, i);
820 }
821 delete []pqJagged_coordinates;
822
823
824 reduceAll<int, gno_t>(*comm, Teuchos::REDUCE_MIN,
825 dim * numParts, lmins, gmins
826 );
827 reduceAll<int, gno_t>(*comm, Teuchos::REDUCE_MAX,
828 dim * numParts, lmaxs, gmaxs
829 );
830 }
831
832 void hash_part_boxes (){
833 part_t pSingleDim = pow(double(numParts), double(1.0 / coordDim));
834 if (pSingleDim == 0) pSingleDim = 1;
835 std::vector < std::vector <part_t> > hash
836 (
837 part_t ( pow ( part_t (pSingleDim),
838 part_t(coordDim)
839 )
840 )
841 );
842
843 //calculate the corners of the dataset.
844 coord_t *allMins = new coord_t [coordDim];
845 coord_t *allMaxs = new coord_t [coordDim];
846 part_t *hash_scales= new coord_t [coordDim];
847
848 for (int j = 0; j < coordDim; ++j){
849 allMins[j] = cpb[0].gmins[j];
850 allMaxs[j] = cpb[0].gmaxs[j];
851 hash_scales[j] = part_t ( pow ( part_t (pSingleDim), part_t(coordDim - j - 1)));
852 }
853
854 for (part_t i = 1; i < numParts; ++i){
855 for (int j = 0; j < coordDim; ++j){
856 coord_t minC = cpb[i].gmins[i];
857 coord_t maxC = cpb[i].gmaxs[i];
858 if (minC < allMins[j]) allMins[j] = minC;
859 if (maxC > allMaxs[j]) allMaxs[j] = maxC;
860 }
861 }
862
863 //get size of each hash for each dimension
864 coord_t *hash_slices_size = new coord_t [coordDim];
865 for (int j = 0; j < coordDim; ++j){
866 hash_slices_size[j] = (allMaxs[j] - allMins[j]) / pSingleDim;
867
868 }
869
870 delete []allMaxs;
871 delete []allMins;
872
873
874
875 std::vector <part_t> *hashIndices = new std::vector <part_t>();
876 std::vector <part_t> *resultHashIndices = new std::vector <part_t>();
877 std::vector <part_t> *tmp_swap;
878 for (part_t i = 0; i < numParts; ++i){
879 hashIndices->clear();
880 resultHashIndices->clear();
881
882 hashIndices->push_back(0);
883
884 for (int j = 0; j < coordDim; ++j){
885
886 coord_t minC = cpb[i].gmins[i];
887 coord_t maxC = cpb[i].gmaxs[i];
888 part_t minHashIndex = part_t ((minC - allMins[j]) / hash_slices_size[j]);
889 part_t maxHashIndex = part_t ((maxC - allMins[j]) / hash_slices_size[j]);
890
891 part_t hashIndexSize = hashIndices->size();
892
893 for (part_t k = minHashIndex; k <= maxHashIndex; ++k ){
894
895 for (part_t i = 0; i < hashIndexSize; ++i){
896 resultHashIndices->push_back(hashIndices[i] + k * hash_scales[j]);
897 }
898 }
899 tmp_swap = hashIndices;
900 hashIndices = resultHashIndices;
901 resultHashIndices = tmp_swap;
902 }
903
904 part_t hashIndexSize = hashIndices->size();
905 for (part_t j = 0; j < hashIndexSize; ++j){
906 hash[(*hashIndices)[j]].push_back(i);
907 }
908 cpb[i].hash_indices = (*hashIndices);
909 }
910 delete hashIndices;
911 delete resultHashIndices;
912 }
913
914 void find_neighbors(){
915
916 }
917
918
919};
920
921*/
922} // namespace Zoltan2
923
924#endif
Traits for application input objects.
GridHash Class, Hashing Class for part boxes.
void fillAdjArrays()
GridHash Class, Function to fill adj arrays.
part_t calculateNeighbors()
GridHash Class, For each box compares the adjacency against the boxes that are in the same buckets.
~GridHash()
GridHash Class, Destructor.
GridHash(const RCP< std::vector< Zoltan2::coordinateModelPartBox > > &pBoxes_, part_t ntasks_, int dim_)
GridHash Class, Constructor.
void getMinMaxBoundaries()
GridHash Class, calculates the minimum of maximum box boundaries, and maxium of minimum box boundarie...
void insertToHash()
GridHash Class, For each box calculates the buckets which it should be inserted to.
void getAdjArrays(ArrayRCP< part_t > &comXAdj_, ArrayRCP< part_t > &comAdj_)
GridHash Class, returns the adj arrays.
coordinateModelPartBox Class, represents the boundaries of the box which is a result of a geometric p...
coordinateModelPartBox(part_t pid, int dim_, scalar_t *lmi, scalar_t *lma)
Constructor deep copy of the maximum and minimum boundaries.
void setMinMaxHashIndices(coord_t *minMaxBoundaries, coord_t *sliceSizes, part_t numSlicePerDim)
function to obtain the min and max hash values along all dimensions.
bool boxesOverlap(int cdim, scalar_t *lower, scalar_t *upper) const
function to test whether this box overlaps a given box
bool isNeighborWith(const coordinateModelPartBox &other) const
function to check if two boxes are neighbors.
bool isAlreadyNeighbor(part_t nIndex)
function to check if a given part is already in the neighbor list.
coord_t * getlmaxs() const
function to get maximum values along all dimensions
bool pointInBox(int pointdim, scalar_t *point) const
function to test whether a point is in the box
std::vector< part_t > * getGridIndices()
function to get the indices of the buckets that the part is inserted to
void computeCentroid(coord_t *centroid) const
compute the centroid of the box
void updateMinMax(scalar_t newBoundary, int isMax, int dimInd)
function to update the boundary of the box.
part_t getpId() const
function to get the part id
coordinateModelPartBox(part_t pid, int dim_)
Constructor.
void setpId(part_t pid)
function to set the part id
std::set< part_t > * getNeighbors()
function to get the indices of the neighboring parts.
void addNeighbor(part_t nIndex)
function to add a new neighbor to the neighbor list.
coordinateModelPartBox(const coordinateModelPartBox &other)
Copy Constructor deep copy of the maximum and minimum boundaries.
int getDim() const
function to set the dimension
void print()
function to print the boundaries.
void writeGnuPlot(std::ofstream &file, std::ofstream &mm)
function for visualization.
coord_t * getlmins() const
function to get minimum values along all dimensions
Created by mbenlioglu on Aug 31, 2020.
SparseMatrixAdapter_t::part_t part_t