|
Zoltan2
|
00001 // @HEADER 00002 // 00003 // *********************************************************************** 00004 // 00005 // Zoltan2: A package of combinatorial algorithms for scientific computing 00006 // Copyright 2012 Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Karen Devine (kddevin@sandia.gov) 00039 // Erik Boman (egboman@sandia.gov) 00040 // Siva Rajamanickam (srajama@sandia.gov) 00041 // 00042 // *********************************************************************** 00043 // 00044 // @HEADER 00045 00046 #ifndef _ZOLTAN2_COORDCOMMGRAPH_HPP_ 00047 #define _ZOLTAN2_COORDCOMMGRAPH_HPP_ 00048 00049 00050 #include <cmath> 00051 #include <limits> 00052 #include <iostream> 00053 #include <vector> 00054 #include <set> 00055 #include <fstream> 00056 #include "Teuchos_CommHelpers.hpp" 00057 #include "Teuchos_Comm.hpp" 00058 #include "Teuchos_ArrayViewDecl.hpp" 00059 #include "Teuchos_RCPDecl.hpp" 00060 00061 namespace Zoltan2{ 00062 00063 00064 #define Z2_ABS(x) ((x) >= 0 ? (x) : -(x)) 00065 00069 template <typename scalar_t,typename part_t> 00070 class coordinateModelPartBox{ 00071 00072 part_t pID; //part Id 00073 int dim; //dimension of the box 00074 scalar_t *lmins; //minimum boundaries of the box along all dimensions. 00075 scalar_t *lmaxs; //maximum boundaries of the box along all dimensions. 00076 scalar_t maxScalar; 00077 scalar_t _EPSILON; 00078 00079 //to calculate the neighbors of the box and avoid the p^2 comparisons, 00080 //we use hashing. A box can be put into multiple hash buckets. 00081 //the following 2 variable holds the minimum and maximum of the 00082 //hash values along all dimensions. 00083 part_t *minHashIndices; 00084 part_t *maxHashIndices; 00085 00086 //result hash bucket indices. 00087 std::vector <part_t> *gridIndices; 00088 //neighbors of the box. 00089 std::set <part_t> neighbors; 00090 public: 00093 coordinateModelPartBox(part_t pid, int dim_): 00094 pID(pid), 00095 dim(dim_), 00096 lmins(0), lmaxs(0), 00097 maxScalar (std::numeric_limits<scalar_t>::max()), 00098 _EPSILON(std::numeric_limits<scalar_t>::epsilon()), 00099 minHashIndices(0), 00100 maxHashIndices(0), 00101 gridIndices(0), neighbors() 00102 { 00103 lmins = new scalar_t [dim]; 00104 lmaxs = new scalar_t [dim]; 00105 00106 minHashIndices = new part_t [dim]; 00107 maxHashIndices = new part_t [dim]; 00108 gridIndices = new std::vector <part_t> (); 00109 for (int i = 0; i < dim; ++i){ 00110 lmins[i] = -this->maxScalar; 00111 lmaxs[i] = this->maxScalar; 00112 } 00113 } 00117 coordinateModelPartBox(part_t pid, int dim_, scalar_t *lmi, scalar_t *lma): 00118 pID(pid), 00119 dim(dim_), 00120 lmins(0), lmaxs(0), 00121 maxScalar (std::numeric_limits<scalar_t>::max()), 00122 _EPSILON(std::numeric_limits<scalar_t>::epsilon()), 00123 minHashIndices(0), 00124 maxHashIndices(0), 00125 gridIndices(0), neighbors() 00126 { 00127 lmins = new scalar_t [dim]; 00128 lmaxs = new scalar_t [dim]; 00129 minHashIndices = new part_t [dim]; 00130 maxHashIndices = new part_t [dim]; 00131 gridIndices = new std::vector <part_t> (); 00132 for (int i = 0; i < dim; ++i){ 00133 lmins[i] = lmi[i]; 00134 lmaxs[i] = lma[i]; 00135 } 00136 } 00137 00138 00142 coordinateModelPartBox(const coordinateModelPartBox <scalar_t, part_t> &other): 00143 pID(0), 00144 dim(other.getDim()), 00145 lmins(0), lmaxs(0), 00146 maxScalar (std::numeric_limits<scalar_t>::max()), 00147 _EPSILON(std::numeric_limits<scalar_t>::epsilon()), 00148 minHashIndices(0), 00149 maxHashIndices(0), 00150 gridIndices(0), neighbors() 00151 { 00152 00153 lmins = new scalar_t [dim]; 00154 lmaxs = new scalar_t [dim]; 00155 minHashIndices = new part_t [dim]; 00156 maxHashIndices = new part_t [dim]; 00157 gridIndices = new std::vector <part_t> (); 00158 scalar_t *othermins = other.getlmins(); 00159 scalar_t *othermaxs = other.getlmaxs(); 00160 for (int i = 0; i < dim; ++i){ 00161 lmins[i] = othermins[i]; 00162 lmaxs[i] = othermaxs[i]; 00163 } 00164 } 00167 ~coordinateModelPartBox(){ 00168 delete []this->lmins; 00169 delete [] this->lmaxs; 00170 delete []this->minHashIndices; 00171 delete [] this->maxHashIndices; 00172 delete gridIndices; 00173 } 00174 00177 void setpId(part_t pid){ 00178 this->pID = pid; 00179 } 00182 part_t getpId() const{ 00183 return this->pID; 00184 } 00185 00186 00189 int getDim()const{ 00190 return this->dim; 00191 } 00194 scalar_t * getlmins()const{ 00195 return this->lmins; 00196 } 00199 scalar_t * getlmaxs()const{ 00200 return this->lmaxs; 00201 } 00204 void computeCentroid(scalar_t *centroid)const { 00205 for (int i = 0; i < this->dim; i++) 00206 centroid[i] = 0.5 * (this->lmaxs[i] + this->lmins[i]); 00207 } 00208 00212 std::vector <part_t> * getGridIndices (){ 00213 return this->gridIndices; 00214 } 00215 00218 std::set<part_t> *getNeighbors(){ 00219 return &(this->neighbors); 00220 } 00221 00224 bool pointInBox(int pointdim, scalar_t *point) { 00225 if (pointdim != this->dim) 00226 throw std::logic_error("dim of point must match dim of box"); 00227 for (int i = 0; i < pointdim; i++) { 00228 if (point[i] < this->lmins[i]) return false; 00229 if (point[i] > this->lmaxs[i]) return false; 00230 } 00231 return true; 00232 } 00233 00236 bool isNeighborWith(const coordinateModelPartBox <scalar_t, part_t> &other){ 00237 00238 00239 scalar_t *omins = other.getlmins(); 00240 scalar_t *omaxs = other.getlmaxs(); 00241 00242 int equality = 0; 00243 for (int i = 0; i < dim; ++i){ 00244 00245 if (omins[i] - this->lmaxs[i] > _EPSILON || this->lmins[i] - omaxs[i] > _EPSILON ){ 00246 return false; 00247 } 00248 else if (Z2_ABS(omins[i] - this->lmaxs[i]) < _EPSILON || Z2_ABS(this->lmins[i] - omaxs[i]) < _EPSILON ){ 00249 if (++equality > 1){ 00250 return false; 00251 } 00252 } 00253 } 00254 if (equality == 1) { 00255 return true; 00256 } 00257 else { 00258 std::cout << "something is wrong: equality:" << equality << std::endl; 00259 return false; 00260 } 00261 } 00262 00263 00266 void addNeighbor(part_t nIndex){ 00267 neighbors.insert(nIndex); 00268 } 00271 bool isAlreadyNeighbor(part_t nIndex){ 00272 00273 if (neighbors.end() != neighbors.find(nIndex)){ 00274 return true; 00275 } 00276 return false; 00277 00278 } 00279 00280 00283 void setMinMaxHashIndices ( 00284 scalar_t *minMaxBoundaries, 00285 scalar_t *sliceSizes, 00286 part_t numSlicePerDim 00287 ){ 00288 for (int j = 0; j < dim; ++j){ 00289 scalar_t distance = (lmins[j] - minMaxBoundaries[j]); 00290 part_t minInd = 0; 00291 if (distance > _EPSILON && sliceSizes[j] > _EPSILON){ 00292 minInd = static_cast<part_t>(floor((lmins[j] - minMaxBoundaries[j])/ sliceSizes[j])); 00293 } 00294 00295 if(minInd >= numSlicePerDim){ 00296 minInd = numSlicePerDim - 1; 00297 } 00298 part_t maxInd = 0; 00299 distance = (lmaxs[j] - minMaxBoundaries[j]); 00300 if (distance > _EPSILON && sliceSizes[j] > _EPSILON){ 00301 maxInd = static_cast<part_t>(ceil((lmaxs[j] - minMaxBoundaries[j])/ sliceSizes[j])); 00302 } 00303 if(maxInd >= numSlicePerDim){ 00304 maxInd = numSlicePerDim - 1; 00305 } 00306 00307 //cout << "j:" << j << " lmins:" << lmins[j] << " lmaxs:" << lmaxs[j] << endl; 00308 //cout << "j:" << j << " min:" << minInd << " max:" << maxInd << endl; 00309 minHashIndices[j] = minInd; 00310 maxHashIndices[j] = maxInd; 00311 } 00312 std::vector <part_t> *in = new std::vector <part_t> (); 00313 in->push_back(0); 00314 std::vector <part_t> *out = new std::vector <part_t> (); 00315 00316 for (int j = 0; j < dim; ++j){ 00317 00318 part_t minInd = minHashIndices[j]; 00319 part_t maxInd = maxHashIndices[j]; 00320 00321 00322 part_t pScale = part_t(pow (float(numSlicePerDim), int(dim - j -1))); 00323 00324 part_t inSize = in->size(); 00325 00326 for (part_t k = minInd; k <= maxInd; ++k){ 00327 for (part_t i = 0; i < inSize; ++i){ 00328 out->push_back((*in)[i] + k * pScale); 00329 } 00330 } 00331 in->clear(); 00332 std::vector <part_t> *tmp = in; 00333 in= out; 00334 out= tmp; 00335 } 00336 00337 std::vector <part_t> *tmp = in; 00338 in = gridIndices; 00339 gridIndices = tmp; 00340 00341 00342 delete in; 00343 delete out; 00344 } 00345 00348 void print(){ 00349 for(int i = 0; i < this->dim; ++i){ 00350 std::cout << "\tbox:" << this->pID << " dim:" << i << " min:" << lmins[i] << " max:" << lmaxs[i] << std::endl; 00351 } 00352 } 00353 00356 void updateMinMax (scalar_t newBoundary, int isMax, int dimInd){ 00357 if (isMax){ 00358 lmaxs[dimInd] = newBoundary; 00359 } 00360 else { 00361 lmins[dimInd] = newBoundary; 00362 } 00363 } 00364 00365 template <typename tt> 00366 std::string toString(tt obj){ 00367 std::stringstream ss (std::stringstream::in |std::stringstream::out); 00368 ss << obj; 00369 std::string tmp = ""; 00370 ss >> tmp; 00371 return tmp; 00372 } 00373 00374 00377 void writeGnuPlot(std::ofstream &file,std::ofstream &mm){ 00378 int numCorners = (int(1)<<dim); 00379 scalar_t *corner1 = new scalar_t [dim]; 00380 scalar_t *corner2 = new scalar_t [dim]; 00381 00382 for (int i = 0; i < dim; ++i){ 00383 /* 00384 if (-maxScalar == lmins[i]){ 00385 if (lmaxs[i] > 0){ 00386 lmins[i] = lmaxs[i] / 2; 00387 } 00388 else{ 00389 lmins[i] = lmaxs[i] * 2; 00390 } 00391 } 00392 */ 00393 //std::cout << lmins[i] << " "; 00394 mm << lmins[i] << " "; 00395 } 00396 //std::cout << std::endl; 00397 mm << std::endl; 00398 for (int i = 0; i < dim; ++i){ 00399 00400 /* 00401 if (maxScalar == lmaxs[i]){ 00402 if (lmins[i] < 0){ 00403 lmaxs[i] = lmins[i] / 2; 00404 } 00405 else{ 00406 lmaxs[i] = lmins[i] * 2; 00407 } 00408 } 00409 */ 00410 00411 //std::cout << lmaxs[i] << " "; 00412 mm << lmaxs[i] << " "; 00413 } 00414 //std::cout << std::endl; 00415 mm << std::endl; 00416 00417 for (int j = 0; j < numCorners; ++j){ 00418 std::vector <int> neighborCorners; 00419 for (int i = 0; i < dim; ++i){ 00420 if(int(j & (int(1)<<i)) == 0){ 00421 corner1[i] = lmins[i]; 00422 } 00423 else { 00424 corner1[i] = lmaxs[i]; 00425 } 00426 if (j % (int(1)<<(i + 1)) >= (int(1)<<i)){ 00427 int c1 = j - (int(1)<<i); 00428 00429 if (c1 > 0) { 00430 neighborCorners.push_back(c1); 00431 } 00432 } 00433 else { 00434 00435 int c1 = j + (int(1)<<i); 00436 if (c1 < (int(1) << dim)) { 00437 neighborCorners.push_back(c1); 00438 } 00439 } 00440 } 00441 //std::cout << "me:" << j << " nc:" << int (neighborCorners.size()) << std::endl; 00442 for (int m = 0; m < int (neighborCorners.size()); ++m){ 00443 00444 int n = neighborCorners[m]; 00445 //std::cout << "me:" << j << " n:" << n << std::endl; 00446 for (int i = 0; i < dim; ++i){ 00447 if(int(n & (int(1)<<i)) == 0){ 00448 corner2[i] = lmins[i]; 00449 } 00450 else { 00451 corner2[i] = lmaxs[i]; 00452 } 00453 } 00454 00455 std::string arrowline = "set arrow from "; 00456 for (int i = 0; i < dim - 1; ++i){ 00457 arrowline += toString<scalar_t>(corner1[i]) + ","; 00458 } 00459 arrowline += toString<scalar_t>(corner1[dim -1]) + " to "; 00460 00461 for (int i = 0; i < dim - 1; ++i){ 00462 arrowline += toString<scalar_t>(corner2[i]) + ","; 00463 } 00464 arrowline += toString<scalar_t>(corner2[dim -1]) + " nohead\n"; 00465 00466 file << arrowline; 00467 } 00468 } 00469 delete []corner1; 00470 delete []corner2; 00471 } 00472 00473 00474 }; 00475 00476 00480 template <typename scalar_t, typename part_t> 00481 class GridHash{ 00482 private: 00483 00484 RCP < std::vector <Zoltan2::coordinateModelPartBox <scalar_t, part_t> > > pBoxes; 00485 00486 //minimum of the maximum box boundaries 00487 scalar_t *minMaxBoundaries; 00488 //maximum of the minimum box boundaries 00489 scalar_t *maxMinBoundaries; 00490 //the size of each slice along dimensions 00491 scalar_t *sliceSizes; 00492 part_t nTasks; 00493 int dim; 00494 //the number of slices per dimension 00495 part_t numSlicePerDim; 00496 //the number of grids - buckets 00497 part_t numGrids; 00498 //hash vector 00499 std::vector <std::vector <part_t> > grids; 00500 //result communication graph. 00501 ArrayRCP <part_t> comXAdj; 00502 ArrayRCP <part_t> comAdj; 00503 public: 00504 00508 GridHash(RCP < std::vector <Zoltan2::coordinateModelPartBox <scalar_t, part_t> > > pBoxes_, 00509 part_t ntasks_, int dim_): 00510 pBoxes(pBoxes_), 00511 minMaxBoundaries(0), 00512 maxMinBoundaries(0), sliceSizes(0), 00513 nTasks(ntasks_), 00514 dim(dim_), 00515 numSlicePerDim(part_t(pow(double(ntasks_), 1.0 / dim))), 00516 numGrids(0), 00517 grids(), 00518 comXAdj(), comAdj() 00519 { 00520 00521 minMaxBoundaries = new scalar_t[dim]; 00522 maxMinBoundaries = new scalar_t[dim]; 00523 sliceSizes = new scalar_t[dim]; 00524 //calculate the number of slices in each dimension. 00525 numSlicePerDim /= 2; 00526 if (numSlicePerDim == 0) numSlicePerDim = 1; 00527 00528 numGrids = part_t(pow(float(numSlicePerDim), int(dim))); 00529 00530 //allocate memory for buckets. 00531 std::vector <std::vector <part_t> > grids_ (numGrids); 00532 this->grids = grids_; 00533 //get the boundaries of buckets. 00534 this->getMinMaxBoundaries(); 00535 //insert boxes to buckets 00536 this->insertToHash(); 00537 //calculate the neighbors for each bucket. 00538 part_t nCount = this->calculateNeighbors(); 00539 00540 //allocate memory for communication graph 00541 ArrayRCP <part_t> tmpComXadj(ntasks_); 00542 ArrayRCP <part_t> tmpComAdj(nCount); 00543 comXAdj = tmpComXadj; 00544 comAdj = tmpComAdj; 00545 //fill communication graph 00546 this->fillAdjArrays(); 00547 } 00548 00549 00553 ~GridHash(){ 00554 delete []minMaxBoundaries; 00555 delete []maxMinBoundaries; 00556 delete []sliceSizes; 00557 } 00558 00562 void fillAdjArrays(){ 00563 00564 part_t adjIndex = 0; 00565 00566 for(part_t i = 0; i < this->nTasks; ++i){ 00567 std::set<part_t> *neigbors = (*pBoxes)[i].getNeighbors(); 00568 00569 part_t s = neigbors->size(); 00570 00571 comXAdj[i] = s; 00572 if (i > 0){ 00573 comXAdj[i] += comXAdj[i - 1]; 00574 } 00575 typedef typename std::set<part_t> mySet; 00576 typedef typename mySet::iterator myIT; 00577 myIT it; 00578 for (it=neigbors->begin(); it!=neigbors->end(); ++it) 00579 00580 comAdj[adjIndex++] = *it; 00581 //TODO not needed anymore. 00582 neigbors->clear(); 00583 } 00584 } 00585 00586 00587 00591 void getAdjArrays( 00592 ArrayRCP <part_t> &comXAdj_, 00593 ArrayRCP <part_t> &comAdj_){ 00594 comXAdj_ = this->comXAdj; 00595 comAdj_ = this->comAdj; 00596 } 00597 00601 part_t calculateNeighbors(){ 00602 part_t nCount = 0; 00603 for(part_t i = 0; i < this->nTasks; ++i){ 00604 std::vector <part_t> *gridIndices =(*pBoxes)[i].getGridIndices(); 00605 part_t gridCount = gridIndices->size(); 00606 00607 for (part_t j = 0; j < gridCount; ++j){ 00608 part_t grid = (*gridIndices)[j]; 00609 part_t boxCount = grids[grid].size(); 00610 for (part_t k = 0; k < boxCount; ++k){ 00611 part_t boxIndex = grids[grid][k]; 00612 if (boxIndex > i){ 00613 if((!(*pBoxes)[i].isAlreadyNeighbor(boxIndex))&& (*pBoxes)[i].isNeighborWith((*pBoxes)[boxIndex])){ 00614 //cout << "i:" << i << " n:" << boxIndex << " are neighbors."<< endl; 00615 (*pBoxes)[i].addNeighbor(boxIndex); 00616 (*pBoxes)[boxIndex].addNeighbor(i); 00617 nCount += 2; 00618 } 00619 } 00620 } 00621 } 00622 } 00623 00624 return nCount; 00625 } 00626 00630 void insertToHash(){ 00631 00632 //cout << "ntasks:" << this->nTasks << endl; 00633 for(part_t i = 0; i < this->nTasks; ++i){ 00634 (*pBoxes)[i].setMinMaxHashIndices(minMaxBoundaries, sliceSizes, numSlicePerDim); 00635 00636 std::vector <part_t> *gridIndices =(*pBoxes)[i].getGridIndices(); 00637 00638 part_t gridCount = gridIndices->size(); 00639 //cout << "i:" << i << " gridsize:" << gridCount << endl; 00640 for (part_t j = 0; j < gridCount; ++j){ 00641 part_t grid = (*gridIndices)[j]; 00642 00643 //cout << "i:" << i << " is being inserted to:" << grid << endl; 00644 (grids)[grid].push_back(i); 00645 } 00646 } 00647 00648 00649 /* 00650 for(part_t i = 0; i < grids.size(); ++i){ 00651 cout << "grid:" << i << " gridsuze:" << (grids)[i].size() << " elements:"; 00652 for(part_t j = 0; j < (grids)[i].size(); ++j){ 00653 cout <<(grids)[i][j] << " "; 00654 } 00655 cout << endl; 00656 00657 } 00658 */ 00659 } 00660 00664 void getMinMaxBoundaries(){ 00665 scalar_t *mins = (*pBoxes)[0].getlmins(); 00666 scalar_t *maxs = (*pBoxes)[0].getlmaxs(); 00667 00668 for (int j = 0; j < dim; ++j){ 00669 minMaxBoundaries[j] = maxs[j]; 00670 maxMinBoundaries[j] = mins[j]; 00671 } 00672 00673 for (part_t i = 1; i < nTasks; ++i){ 00674 00675 mins = (*pBoxes)[i].getlmins(); 00676 maxs = (*pBoxes)[i].getlmaxs(); 00677 00678 for (int j = 0; j < dim; ++j){ 00679 00680 if (minMaxBoundaries[j] > maxs[j]){ 00681 minMaxBoundaries[j] = maxs[j]; 00682 } 00683 if (maxMinBoundaries[j] < mins[j]){ 00684 maxMinBoundaries[j] = mins[j]; 00685 } 00686 } 00687 } 00688 00689 00690 for (int j = 0; j < dim; ++j){ 00691 sliceSizes[j] = (maxMinBoundaries[j] - minMaxBoundaries[j]) / numSlicePerDim; 00692 if (sliceSizes[j] < 0) sliceSizes[j] = 0; 00693 /* 00694 cout << "dim:" << j << 00695 " minMax:" << minMaxBoundaries[j] << 00696 " maxMin:" << maxMinBoundaries[j] << 00697 " sliceSizes:" << sliceSizes[j] << endl; 00698 */ 00699 } 00700 } 00701 }; 00702 /* 00703 template <typename scalar_t,typename part_t> 00704 class coordinatePartBox{ 00705 public: 00706 part_t pID; 00707 int dim; 00708 int numCorners; 00709 scalar_t **corners; 00710 scalar_t *lmins, *gmins; 00711 scalar_t *lmaxs, *gmaxs; 00712 scalar_t maxScalar; 00713 std::vector <part_t> hash_indices; 00714 coordinatePartBox(part_t pid, int dim_, scalar_t *lMins, scalar_t *gMins, 00715 scalar_t *lMaxs, scalar_t *gMaxs): 00716 pID(pid), 00717 dim(dim_), 00718 numCorners(int(pow(2, dim_))), 00719 corners(0), 00720 lmins(lMins), gmins(gMins), lmaxs(lMaxs), gmaxs(gMaxs), 00721 maxScalar (std::numeric_limits<scalar_t>::max()){ 00722 this->corners = new scalar_t *[dim]; 00723 for (int i = 0; i < dim; ++i){ 00724 this->corners[i] = new scalar_t[this->numCorners]; 00725 lmins[i] = this->maxScalar; 00726 lmaxs[i] = -this->maxScalar; 00727 } 00728 00729 00730 for (int j = 0; j < this->numCorners; ++j){ 00731 for (int i = 0; i < dim; ++i){ 00732 std::cout << "j:" << j << " i:" << i << " 2^i:" << pow(2,i) << " and:" << int(j & int(pow(2,i))) << std::endl; 00733 if(int(j & int(pow(2,i))) == 0){ 00734 corners[i][j] = gmins[i]; 00735 } 00736 else { 00737 corners[i][j] = gmaxs[i]; 00738 } 00739 00740 } 00741 } 00742 } 00743 00744 }; 00745 00746 template <typename Adapter, typename part_t> 00747 class CoordinateCommGraph{ 00748 private: 00749 00750 typedef typename Adapter::lno_t lno_t; 00751 typedef typename Adapter::gno_t gno_t; 00752 typedef typename Adapter::scalar_t scalar_t; 00753 00754 const Environment *env; 00755 const Teuchos::Comm<int> *comm; 00756 const Zoltan2::CoordinateModel<typename Adapter::base_adapter_t> *coords; 00757 const Zoltan2::PartitioningSolution<Adapter> *soln; 00758 std::vector<coordinatePartBox, part_t> cpb; 00759 int coordDim; 00760 part_t numParts; 00761 00762 00763 public: 00764 00765 CoordinateCommGraph( 00766 const Environment *env_, 00767 const Teuchos::Comm<int> *comm_, 00768 const Zoltan2::CoordinateModel<typename Adapter::base_adapter_t> *coords_, 00769 const Zoltan2::PartitioningSolution<Adapter> *soln_ 00770 ): 00771 env(env_), 00772 comm(comm_), 00773 coords(coords_), 00774 soln(soln_), 00775 coordDim (coords_->getCoordinateDim()), 00776 numParts (this->soln->getActualGlobalNumberOfParts()) 00777 { 00778 this->create_part_boxes(); 00779 this->hash_part_boxes(); 00780 this->find_neighbors(); 00781 } 00782 00783 void create_part_boxes(){ 00784 00785 00786 size_t allocSize = numParts * coordDim; 00787 scalar_t *lmins = new scalar_t [allocSize]; 00788 scalar_t *gmins = new scalar_t [allocSize]; 00789 scalar_t *lmaxs = new scalar_t [allocSize]; 00790 scalar_t *gmaxs = new scalar_t [allocSize]; 00791 00792 for(part_t i = 0; i < numParts; ++i){ 00793 coordinatePartBox tmp( 00794 i, 00795 this->coordDim, 00796 lmins + i * coordDim, 00797 gmins + i * coordDim, 00798 lmaxs + i * coordDim, 00799 gmaxs + i * coordDim 00800 ); 00801 cpb.push_back(tmp); 00802 } 00803 00804 typedef StridedData<lno_t, scalar_t> input_t; 00805 Teuchos::ArrayView<const gno_t> gnos; 00806 Teuchos::ArrayView<input_t> xyz; 00807 Teuchos::ArrayView<input_t> wgts; 00808 coords->getCoordinates(gnos, xyz, wgts); 00809 00810 //local and global num coordinates. 00811 lno_t numLocalCoords = coords->getLocalNumCoordinates(); 00812 00813 scalar_t **pqJagged_coordinates = new scalar_t *[coordDim]; 00814 00815 for (int dim=0; dim < coordDim; dim++){ 00816 Teuchos::ArrayRCP<const scalar_t> ar; 00817 xyz[dim].getInputArray(ar); 00818 //pqJagged coordinate values assignment 00819 pqJagged_coordinates[dim] = (scalar_t *)ar.getRawPtr(); 00820 } 00821 00822 part_t *sol_part = soln->getPartList(); 00823 for(lno_t i = 0; i < numLocalCoords; ++i){ 00824 part_t p = sol_part[i]; 00825 cpb[p].updateMinMax(pqJagged_coordinates, i); 00826 } 00827 delete []pqJagged_coordinates; 00828 00829 00830 reduceAll<int, gno_t>(*comm, Teuchos::REDUCE_MIN, 00831 dim * numParts, lmins, gmins 00832 ); 00833 reduceAll<int, gno_t>(*comm, Teuchos::REDUCE_MAX, 00834 dim * numParts, lmaxs, gmaxs 00835 ); 00836 } 00837 00838 void hash_part_boxes (){ 00839 part_t pSingleDim = pow(double(numParts), double(1.0 / coordDim)); 00840 if (pSingleDim == 0) pSingleDim = 1; 00841 std::vector < std::vector <part_t> > hash 00842 ( 00843 part_t ( pow ( part_t (pSingleDim), 00844 part_t(coordDim) 00845 ) 00846 ) 00847 ); 00848 00849 //calculate the corners of the dataset. 00850 scalar_t *allMins = new scalar_t [coordDim]; 00851 scalar_t *allMaxs = new scalar_t [coordDim]; 00852 part_t *hash_scales= new scalar_t [coordDim]; 00853 00854 for (int j = 0; j < coordDim; ++j){ 00855 allMins[j] = cpb[0].gmins[j]; 00856 allMaxs[j] = cpb[0].gmaxs[j]; 00857 hash_scales[j] = part_t ( pow ( part_t (pSingleDim), part_t(coordDim - j - 1))); 00858 } 00859 00860 for (part_t i = 1; i < numParts; ++i){ 00861 for (int j = 0; j < coordDim; ++j){ 00862 scalar_t minC = cpb[i].gmins[i]; 00863 scalar_t maxC = cpb[i].gmaxs[i]; 00864 if (minC < allMins[j]) allMins[j] = minC; 00865 if (maxC > allMaxs[j]) allMaxs[j] = maxC; 00866 } 00867 } 00868 00869 //get size of each hash for each dimension 00870 scalar_t *hash_slices_size = new scalar_t [coordDim]; 00871 for (int j = 0; j < coordDim; ++j){ 00872 hash_slices_size[j] = (allMaxs[j] - allMins[j]) / pSingleDim; 00873 00874 } 00875 00876 delete []allMaxs; 00877 delete []allMins; 00878 00879 00880 00881 std::vector <part_t> *hashIndices = new std::vector <part_t>(); 00882 std::vector <part_t> *resultHashIndices = new std::vector <part_t>(); 00883 std::vector <part_t> *tmp_swap; 00884 for (part_t i = 0; i < numParts; ++i){ 00885 hashIndices->clear(); 00886 resultHashIndices->clear(); 00887 00888 hashIndices->push_back(0); 00889 00890 for (int j = 0; j < coordDim; ++j){ 00891 00892 scalar_t minC = cpb[i].gmins[i]; 00893 scalar_t maxC = cpb[i].gmaxs[i]; 00894 part_t minHashIndex = part_t ((minC - allMins[j]) / hash_slices_size[j]); 00895 part_t maxHashIndex = part_t ((maxC - allMins[j]) / hash_slices_size[j]); 00896 00897 part_t hashIndexSize = hashIndices->size(); 00898 00899 for (part_t k = minHashIndex; k <= maxHashIndex; ++k ){ 00900 00901 for (part_t i = 0; i < hashIndexSize; ++i){ 00902 resultHashIndices->push_back(hashIndices[i] + k * hash_scales[j]); 00903 } 00904 } 00905 tmp_swap = hashIndices; 00906 hashIndices = resultHashIndices; 00907 resultHashIndices = tmp_swap; 00908 } 00909 00910 part_t hashIndexSize = hashIndices->size(); 00911 for (part_t j = 0; j < hashIndexSize; ++j){ 00912 hash[(*hashIndices)[j]].push_back(i); 00913 } 00914 cpb[i].hash_indices = (*hashIndices); 00915 } 00916 delete hashIndices; 00917 delete resultHashIndices; 00918 } 00919 00920 void find_neighbors(){ 00921 00922 } 00923 00924 00925 }; 00926 00927 */ 00928 } // namespace Zoltan2 00929 00930 #endif
1.7.6.1