Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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"
24 #include "Zoltan2_InputTraits.hpp"
25 
26 namespace Zoltan2{
27 
28 
29 #define Z2_ABS(x) ((x) >= 0 ? (x) : -(x))
30 
35 
36 public:
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  }
144  coord_t * getlmins()const{
145  return this->lmins;
146  }
149  coord_t * getlmaxs()const{
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  }
251  bool isAlreadyNeighbor(part_t nIndex){
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 
449 private:
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 
474 class GridHash{
475 private:
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;
499 public:
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 
624  void insertToHash(){
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 /*
697 template <typename coord_t,typename part_t>
698 class coordinatePartBox{
699 public:
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 
740 template <typename Adapter, typename part_t>
741 class CoordinateCommGraph{
742 private:
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 
757 public:
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
~GridHash()
GridHash Class, Destructor.
GridHash Class, Hashing Class for part boxes.
std::vector< part_t > * getGridIndices()
function to get the indices of the buckets that the part is inserted to
coord_t * getlmaxs() const
function to get maximum values along all dimensions
coordinateModelPartBox(part_t pid, int dim_, scalar_t *lmi, scalar_t *lma)
Constructor deep copy of the maximum and minimum boundaries.
std::set< part_t > * getNeighbors()
function to get the indices of the neighboring parts.
part_t calculateNeighbors()
GridHash Class, For each box compares the adjacency against the boxes that are in the same buckets...
void getAdjArrays(ArrayRCP< part_t > &comXAdj_, ArrayRCP< part_t > &comAdj_)
GridHash Class, returns the adj arrays.
void updateMinMax(scalar_t newBoundary, int isMax, int dimInd)
function to update the boundary of the box.
coordinateModelPartBox(part_t pid, int dim_)
Constructor.
GridHash(const RCP< std::vector< Zoltan2::coordinateModelPartBox > > &pBoxes_, part_t ntasks_, int dim_)
GridHash Class, Constructor.
void insertToHash()
GridHash Class, For each box calculates the buckets which it should be inserted to.
void computeCentroid(coord_t *centroid) const
compute the centroid of the box
coordinateModelPartBox Class, represents the boundaries of the box which is a result of a geometric p...
SparseMatrixAdapter_t::part_t part_t
bool isNeighborWith(const coordinateModelPartBox &other) const
function to check if two boxes are neighbors.
void getMinMaxBoundaries()
GridHash Class, calculates the minimum of maximum box boundaries, and maxium of minimum box boundarie...
void setMinMaxHashIndices(coord_t *minMaxBoundaries, coord_t *sliceSizes, part_t numSlicePerDim)
function to obtain the min and max hash values along all dimensions.
void setpId(part_t pid)
function to set the part id
coordinateModelPartBox(const coordinateModelPartBox &other)
Copy Constructor deep copy of the maximum and minimum boundaries.
Traits for application input objects.
coord_t * getlmins() const
function to get minimum values along all dimensions
void addNeighbor(part_t nIndex)
function to add a new neighbor to the neighbor list.
bool isAlreadyNeighbor(part_t nIndex)
function to check if a given part is already in the neighbor list.
void writeGnuPlot(std::ofstream &file, std::ofstream &mm)
function for visualization.
bool boxesOverlap(int cdim, scalar_t *lower, scalar_t *upper) const
function to test whether this box overlaps a given box
bool pointInBox(int pointdim, scalar_t *point) const
function to test whether a point is in the box
part_t getpId() const
function to get the part id
void print()
function to print the boundaries.
int getDim() const
function to set the dimension
void fillAdjArrays()
GridHash Class, Function to fill adj arrays.