Zoltan2
Zoltan2_CoordinatePartitioningGraph.hpp
Go to the documentation of this file.
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