Zoltan2
GeometricGenerator.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 #include <Teuchos_Comm.hpp>
00046 #include <Teuchos_ParameterList.hpp>
00047 #include <Teuchos_FilteredIterator.hpp>
00048 #include <Teuchos_ParameterEntry.hpp>
00049 #include <iostream>
00050 #include <ctime>
00051 #include <limits>
00052 #include <climits>
00053 #include <string>
00054 #include <cstdlib>
00055 #include <sstream>
00056 #include <fstream>
00057 #include <Tpetra_MultiVector_decl.hpp>
00058 #include <Zoltan2_XpetraMultiVectorAdapter.hpp>
00059 #include <Zoltan2_PartitioningSolution.hpp>
00060 #include <Teuchos_ArrayViewDecl.hpp>
00061 #include <Teuchos_RCP.hpp>
00062 #include <Tpetra_Distributor.hpp>
00063 #include <Zoltan2_PartitioningProblem.hpp>
00064 
00065 
00066 //#define HAVE_ZOLTAN2_ZOLTAN
00067 #ifdef HAVE_ZOLTAN2_ZOLTAN
00068 #include <zoltan.h>
00069 #endif
00070 
00071 #ifdef _MSC_VER
00072 #define NOMINMAX
00073 #include <windows.h>
00074 #endif
00075 
00076 using Teuchos::CommandLineProcessor;
00077 
00078 namespace GeometricGen{
00079 #define CATCH_EXCEPTIONS(pp) \
00080         catch (std::runtime_error &e) { \
00081             cout << "Runtime exception returned from " << pp << ": " \
00082             << e.what() << " FAIL" << endl; \
00083             return -1; \
00084         } \
00085         catch (std::logic_error &e) { \
00086             cout << "Logic exception returned from " << pp << ": " \
00087             << e.what() << " FAIL" << endl; \
00088             return -1; \
00089         } \
00090         catch (std::bad_alloc &e) { \
00091             cout << "Bad_alloc exception returned from " << pp << ": " \
00092             << e.what() << " FAIL" << endl; \
00093             return -1; \
00094         } \
00095         catch (std::exception &e) { \
00096             cout << "Unknown exception returned from " << pp << ": " \
00097             << e.what() << " FAIL" << endl; \
00098             return -1; \
00099         }
00100 
00101 
00102 
00103 
00104 #ifdef HAVE_ZOLTAN2_ZOLTAN
00105 
00106 
00107 template <typename tMVector_t>
00108 class DOTS{
00109 public:
00110   vector<vector<float> > weights;
00111   tMVector_t *coordinates;
00112 };
00113 
00114 template <typename tMVector_t>
00115 int getNumObj(void *data, int *ierr)
00116 {
00117   *ierr = 0;
00118   DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
00119   return dots_->coordinates->getLocalLength();
00120 }
00122 template <typename tMVector_t>
00123 void getCoords(void *data, int numGid, int numLid,
00124   int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
00125   int dim, double *coords_, int *ierr)
00126 {
00127   typedef typename tMVector_t::scalar_type scalar_t;
00128 
00129   // I know that Zoltan asks for coordinates in gid order.
00130   if (dim == 3){
00131     *ierr = 0;
00132     DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
00133     double *val = coords_;
00134     const scalar_t *x = dots_->coordinates->getData(0).getRawPtr();
00135     const scalar_t *y = dots_->coordinates->getData(1).getRawPtr();
00136     const scalar_t *z = dots_->coordinates->getData(2).getRawPtr();
00137     for (int i=0; i < numObj; i++){
00138       *val++ = static_cast<double>(x[i]);
00139       *val++ = static_cast<double>(y[i]);
00140       *val++ = static_cast<double>(z[i]);
00141     }
00142   }
00143   else {
00144     *ierr = 0;
00145     DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
00146     double *val = coords_;
00147     const scalar_t *x = dots_->coordinates->getData(0).getRawPtr();
00148     const scalar_t *y = dots_->coordinates->getData(1).getRawPtr();
00149     for (int i=0; i < numObj; i++){
00150       *val++ = static_cast<double>(x[i]);
00151       *val++ = static_cast<double>(y[i]);
00152     }
00153   }
00154 }
00155 
00156 template <typename tMVector_t>
00157 int getDim(void *data, int *ierr)
00158 {
00159   *ierr = 0;
00160   DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
00161   int dim =  dots_->coordinates->getNumVectors();
00162 
00163   return dim;
00164 }
00165 
00167 template <typename tMVector_t>
00168 void getObjList(void *data, int numGid, int numLid,
00169   ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
00170   int num_wgts, float *obj_wgts, int *ierr)
00171 {
00172   typedef typename tMVector_t::scalar_type scalar_t;
00173   typedef typename tMVector_t::global_ordinal_type gno_t;
00174 
00175   *ierr = 0;
00176   DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
00177 
00178   size_t localLen = dots_->coordinates->getLocalLength();
00179   const gno_t *ids =
00180                dots_->coordinates->getMap()->getNodeElementList().getRawPtr();
00181 
00182   if (sizeof(ZOLTAN_ID_TYPE) == sizeof(gno_t))
00183     memcpy(gids, ids, sizeof(ZOLTAN_ID_TYPE) * localLen);
00184   else
00185     for (size_t i=0; i < localLen; i++)
00186       gids[i] = static_cast<ZOLTAN_ID_TYPE>(ids[i]);
00187 
00188   if (num_wgts > 0){
00189     float *wgts = obj_wgts;
00190     for (size_t i=0; i < localLen; i++)
00191       for (int w=0; w < num_wgts; w++)
00192         *wgts++ = dots_->weights[w][i];
00193   }
00194 }
00195 #endif
00196 
00197 
00198 enum shape {SQUARE, RECTANGLE, CIRCLE, CUBE, RECTANGULAR_PRISM, SPHERE};
00199 const std::string shapes[] = {"SQUARE", "RECTANGLE", "CIRCLE", "CUBE", "RECTANGULAR_PRISM", "SPHERE"};
00200 #define SHAPE_COUNT 6
00201 
00202 enum distribution {normal, uniform};
00203 const std::string distribution[] = {"distribution", "uniform"};
00204 #define DISTRIBUTION_COUNT 2
00205 
00206 #define HOLE_ALLOC_STEP  10
00207 #define MAX_WEIGHT_DIM  10
00208 #define INVALID(STR) "Invalid argument at " + STR
00209 #define INVALIDSHAPE(STR, DIM) "Invalid shape name " + STR + " for " +  DIM + ".\nValid shapes are \"SQUARE\", \"RECTANGLE\", \"CIRCLE\" for 2D, and \"CUBE\", \"RECTANGULAR_PRISM\", \"SPHERE\" for 3D"
00210 
00211 #define INVALID_SHAPE_ARG(SHAPE, REQUIRED) "Invalid argument count for shape " + SHAPE + ". Requires " + REQUIRED + " argument(s)."
00212 #define MAX_ITER_ALLOWED 500
00213 
00214 const std::string weight_distribution_string = "WeightDistribution-";
00215 
00216 template <typename T>
00217 struct CoordinatePoint {
00218   T x;
00219   T y;
00220   T z;
00221   /*
00222   bool isInArea(int dim, T *minCoords, T *maxCoords){
00223     dim = min(3, dim);
00224     for (int i = 0; i < dim; ++i){
00225       bool maybe = true;
00226       switch(i){
00227       case 0:
00228         maybe = x < maxCoords[i] && x > maxCoords[i];
00229         break;
00230       case 1:
00231         maybe = y < maxCoords[i] && y > maxCoords[i];
00232         break;
00233       case 2:
00234         maybe = z < maxCoords[i] && z > maxCoords[i];
00235         break;
00236       }
00237       if (!maybe){
00238         return false;
00239       }
00240     }
00241     return true;
00242   }
00243    */
00244   CoordinatePoint(){
00245     x = 0;y=0;z=0;
00246   }
00247 };
00248 
00249 template <typename T>
00250 class Hole{
00251 public:
00252   CoordinatePoint<T> center;
00253   T edge1, edge2, edge3;
00254   Hole(CoordinatePoint<T> center_, T edge1_, T edge2_, T edge3_){
00255     this->center.x = center_.x;
00256     this->center.y = center_.y;
00257     this->center.z = center_.z;
00258     this->edge1 = edge1_;
00259     this->edge2 = edge2_;
00260     this->edge3 = edge3_;
00261   }
00262   virtual bool isInArea(CoordinatePoint<T> dot) = 0;
00263   virtual ~Hole(){}
00264 };
00265 
00266 template <typename T>
00267 class SquareHole:public Hole<T>{
00268 public:
00269   SquareHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
00270   virtual ~SquareHole(){}
00271   virtual bool isInArea(CoordinatePoint<T> dot){
00272     return fabs(dot.x - this->center.x) < this->edge1 / 2 && fabs(dot.y - this->center.y) < this->edge1 / 2;
00273   }
00274 };
00275 
00276 template <typename T>
00277 class RectangleHole:public Hole<T>{
00278 public:
00279   RectangleHole(CoordinatePoint<T> center_  , T edge_x_, T edge_y_): Hole<T>(center_, edge_x_,  edge_y_, 0){}
00280   virtual bool isInArea(CoordinatePoint<T> dot){
00281     return fabs(dot.x - this->center.x) < this->edge1 / 2 && fabs(dot.y - this->center.y) < this->edge2 / 2;
00282   }
00283   virtual ~RectangleHole(){}
00284 };
00285 
00286 template <typename T>
00287 class CircleHole:public Hole<T>{
00288 public:
00289   CircleHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
00290   virtual ~CircleHole(){}
00291   virtual bool isInArea(CoordinatePoint<T> dot){
00292     return (dot.x - this->center.x)*(dot.x - this->center.x) + (dot.y - this->center.y) * (dot.y - this->center.y) < this->edge1 * this->edge1;
00293   }
00294 };
00295 
00296 template <typename T>
00297 class CubeHole:public Hole<T>{
00298 public:
00299   CubeHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
00300   virtual ~CubeHole(){}
00301   virtual bool isInArea(CoordinatePoint<T> dot){
00302     return fabs(dot.x - this->center.x) < this->edge1 / 2 && fabs(dot.y - this->center.y) < this->edge1 / 2 && fabs(dot.z - this->center.z) < this->edge1 / 2;
00303   }
00304 };
00305 
00306 template <typename T>
00307 class RectangularPrismHole:public Hole<T>{
00308 public:
00309   RectangularPrismHole(CoordinatePoint<T> center_  , T edge_x_, T edge_y_, T edge_z_): Hole<T>(center_, edge_x_,  edge_y_, edge_z_){}
00310   virtual ~RectangularPrismHole(){}
00311   virtual bool isInArea(CoordinatePoint<T> dot){
00312     return fabs(dot.x - this->center.x) < this->edge1 / 2 && fabs(dot.y - this->center.y) < this->edge2 / 2 && fabs(dot.z - this->center.z) < this->edge3 / 2;
00313   }
00314 };
00315 
00316 template <typename T>
00317 class SphereHole:public Hole<T>{
00318 public:
00319   SphereHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
00320   virtual ~SphereHole(){}
00321   virtual bool isInArea(CoordinatePoint<T> dot){
00322     return  fabs((dot.x - this->center.x) * (dot.x - this->center.x) * (dot.x - this->center.x)) +
00323         fabs((dot.y - this->center.y) * (dot.y - this->center.y) * (dot.y - this->center.y)) +
00324         fabs((dot.z - this->center.z) * (dot.z - this->center.z) * (dot.z - this->center.z))
00325         <
00326         this->edge1 * this->edge1 * this->edge1;
00327   }
00328 };
00329 
00330 template <typename T, typename weighttype>
00331 class WeightDistribution{
00332 public:
00333   virtual weighttype getWeight(CoordinatePoint<T> P)=0;
00334   virtual weighttype get1DWeight(T x)=0;
00335   virtual weighttype get2DWeight(T x, T y)=0;
00336   virtual weighttype get3DWeight(T x, T y, T z)=0;
00337   WeightDistribution(){};
00338   virtual ~WeightDistribution(){};
00339 };
00340 
00359 template <typename T, typename weighttype>
00360 class SteppedEquation:public WeightDistribution<T, weighttype>{
00361   T a1,a2,a3;
00362   T b1,b2,b3;
00363   T c;
00364   T x1,y1,z1;
00365 
00366   T *steps;
00367   weighttype *values;
00368   int stepCount;
00369 public:
00370   SteppedEquation(T a1_, T a2_, T a3_, T b1_, T b2_, T b3_, T c_, T x1_, T y1_, T z1_, T *steps_, T *values_, int stepCount_):WeightDistribution<T,weighttype>(){
00371     this->a1 = a1_;
00372     this->a2 = a2_;
00373     this->a3 = a3_;
00374     this->b1 = b1_;
00375     this->b2 = b2_;
00376     this->b3 = b3_;
00377     this->c = c_;
00378     this->x1 = x1_;
00379     this->y1 = y1_;
00380     this->z1 = z1_;
00381 
00382 
00383     this->stepCount = stepCount_;
00384     if(this->stepCount > 0){
00385       this->steps = new T[this->stepCount];
00386       this->values = new T[this->stepCount + 1];
00387 
00388       for (int i = 0; i < this->stepCount; ++i){
00389         this->steps[i] = steps_[i];
00390         this->values[i] = values_[i];
00391       }
00392       this->values[this->stepCount] = values_[this->stepCount];
00393     }
00394 
00395   }
00396 
00397   virtual ~SteppedEquation(){
00398     if(this->stepCount > 0){
00399       delete [] this->steps;
00400       delete [] this->values;
00401     }
00402   }
00403 
00404 
00405   virtual weighttype get1DWeight(T x){
00406     T expressionRes = this->a1 * pow( (x - this->x1), b1) + c;
00407     if(this->stepCount > 0){
00408       for (int i = 0; i < this->stepCount; ++i){
00409         if (expressionRes < this->steps[i]) return this->values[i];
00410       }
00411       return this->values[this->stepCount];
00412     }
00413     else {
00414       return weighttype(expressionRes);
00415     }
00416   }
00417 
00418   virtual weighttype get2DWeight(T x, T y){
00419     T expressionRes = this->a1 * pow( (x - this->x1), b1) + this->a2 * pow( (y - this->y1), b2) + c;
00420     if(this->stepCount > 0){
00421       for (int i = 0; i < this->stepCount; ++i){
00422         if (expressionRes < this->steps[i]) return this->values[i];
00423       }
00424       return this->values[this->stepCount];
00425     }
00426     else {
00427       return weighttype(expressionRes);
00428     }
00429   }
00430 
00431   void print (T x, T y, T z){
00432     cout << this->a1 << "*" <<  "math.pow( (" << x  << "- " <<  this->x1 << " ), " << b1 <<")" << "+" <<  this->a2<< "*"<<  "math.pow( (" << y << "-" <<  this->y1 << "), " <<
00433         b2 << " ) + " << this->a3 << " * math.pow( (" << z << "-" <<  this->z1 << "), " << b3 << ")+ " << c << " == " <<
00434         this->a1 * pow( (x - this->x1), b1) + this->a2 * pow( (y - this->y1), b2) + this->a3 * pow( (z - this->z1), b3) + c << endl;
00435 
00436   }
00437 
00438   virtual weighttype get3DWeight(T x, T y, T z){
00439     T expressionRes = this->a1 * pow( (x - this->x1), b1) + this->a2 * pow( (y - this->y1), b2) + this->a3 * pow( (z - this->z1), b3) + this->c;
00440 
00441     //this->print(x,y,z);
00442     if(this->stepCount > 0){
00443       for (int i = 0; i < this->stepCount; ++i){
00444         if (expressionRes < this->steps[i]) {
00445           //cout << "0exp:" << expressionRes << " step:" << steps[i] << " value:" << values[i] << endl;
00446           return this->values[i];
00447         }
00448       }
00449 
00450       //cout << "1exp:" << expressionRes << " step:" << steps[stepCount] << " value:" << values[stepCount] << endl;
00451       return this->values[this->stepCount];
00452     }
00453     else {
00454       return weighttype(expressionRes);
00455     }
00456   }
00457 
00458   virtual weighttype getWeight(CoordinatePoint<T> p){
00459     T expressionRes = this->a1 * pow( (p.x - this->x1), b1) + this->a2 * pow( (p.y - this->y1), b2) + this->a3 * pow( (p.z - this->z1), b3);
00460     if(this->stepCount > 0){
00461       for (int i = 0; i < this->stepCount; ++i){
00462         if (expressionRes < this->steps[i]) return this->values[i];
00463       }
00464       return this->values[this->stepCount];
00465     }
00466     else {
00467       return weighttype(expressionRes);
00468     }
00469   }
00470 };
00471 
00472 template <typename T, typename lno_t, typename gno_t>
00473 class CoordinateDistribution{
00474 public:
00475   gno_t numPoints;
00476   int dimension;
00477   lno_t requested;
00478   gno_t assignedPrevious;
00479   int worldSize;
00480   virtual ~CoordinateDistribution(){}
00481 
00482   CoordinateDistribution(gno_t np_, int dim, int wSize) :
00483     numPoints(np_), dimension(dim), requested(0), assignedPrevious(0),
00484     worldSize(wSize){}
00485 
00486   virtual CoordinatePoint<T> getPoint(gno_t point_index, unsigned int &state) = 0;
00487   virtual T getXCenter() = 0;
00488   virtual T getXRadius() =0;
00489 
00490   void GetPoints(lno_t requestedPointcount, CoordinatePoint<T> *points /*preallocated sized numPoints*/,
00491       Hole<T> **holes, lno_t holeCount,
00492       float *sharedRatios_, int myRank){
00493 
00494     for (int i = 0; i < myRank; ++i){
00495       //cout << "me:" << myRank << " i:" << i << " s:" << sharedRatios_[i]<< endl;
00496       this->assignedPrevious += lno_t(sharedRatios_[i] * this->numPoints);
00497       if (i < this->numPoints % this->worldSize){
00498         this->assignedPrevious += 1;
00499       }
00500     }
00501 
00502     this->requested = requestedPointcount;
00503 
00504     unsigned int slice =  UINT_MAX/(this->worldSize);
00505     unsigned int stateBegin = myRank * slice;
00506 
00507 //#ifdef HAVE_ZOLTAN2_OMP
00508 //#pragma omp parallel for
00509 //#endif
00510 #ifdef HAVE_ZOLTAN2_OMP
00511 #pragma omp parallel
00512 #endif
00513     {
00514       int me = 0;
00515       int tsize = 1;
00516 #ifdef HAVE_ZOLTAN2_OMP
00517       me = omp_get_thread_num();
00518       tsize = omp_get_num_threads();
00519 #endif
00520       unsigned int state = stateBegin + me * slice/(tsize);
00521 
00522 #ifdef HAVE_ZOLTAN2_OMP
00523 #pragma omp for
00524 #endif
00525       for(lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
00526         lno_t iteration = 0;
00527         while(1){
00528           if(++iteration > MAX_ITER_ALLOWED) {
00529             throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
00530           }
00531           CoordinatePoint <T> p = this->getPoint( this->assignedPrevious + cnt, &state);
00532 
00533           bool isInHole = false;
00534           for(lno_t i = 0; i < holeCount; ++i){
00535             if(holes[i][0].isInArea(p)){
00536               isInHole = true;
00537               break;
00538             }
00539           }
00540           if(isInHole) continue;
00541           points[cnt].x = p.x;
00542 
00543           points[cnt].y = p.y;
00544           points[cnt].z = p.z;
00545           break;
00546         }
00547       }
00548     }
00549 //#pragma omp parallel
00550       /*
00551     {
00552 
00553       lno_t cnt = 0;
00554       lno_t iteration = 0;
00555       while (cnt < requestedPointcount){
00556         if(++iteration > MAX_ITER_ALLOWED) {
00557           throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
00558         }
00559         CoordinatePoint <T> p = this->getPoint();
00560 
00561         bool isInHole = false;
00562         for(lno_t i = 0; i < holeCount; ++i){
00563           if(holes[i][0].isInArea(p)){
00564             isInHole = true;
00565             break;
00566           }
00567         }
00568         if(isInHole) continue;
00569         iteration = 0;
00570         points[cnt].x = p.x;
00571         points[cnt].y = p.y;
00572         points[cnt].z = p.z;
00573         ++cnt;
00574       }
00575     }
00576     */
00577   }
00578 
00579   void GetPoints(lno_t requestedPointcount, T **coords/*preallocated sized numPoints*/, lno_t tindex,
00580       Hole<T> **holes, lno_t holeCount,
00581       float *sharedRatios_, int myRank){
00582 
00583     for (int i = 0; i < myRank; ++i){
00584       //cout << "me:" << myRank << " i:" << i << " s:" << sharedRatios_[i]<< endl;
00585       this->assignedPrevious += lno_t(sharedRatios_[i] * this->numPoints);
00586       if (gno_t(i) < this->numPoints % this->worldSize){
00587         this->assignedPrevious += 1;
00588       }
00589     }
00590 
00591     this->requested = requestedPointcount;
00592 
00593     unsigned int slice =  UINT_MAX/(this->worldSize);
00594     unsigned int stateBegin = myRank * slice;
00595 #ifdef HAVE_ZOLTAN2_OMP
00596 #pragma omp parallel
00597 #endif
00598     {
00599       int me = 0;
00600       int tsize = 1;
00601 #ifdef HAVE_ZOLTAN2_OMP
00602       me = omp_get_thread_num();
00603       tsize = omp_get_num_threads();
00604 #endif
00605       unsigned int state = stateBegin + me * (slice/(tsize));
00606       /*
00607 #pragma omp critical
00608       {
00609 
00610         cout << "myRank:" << me << " stateBeg:" << stateBegin << " tsize:" << tsize << " state:" << state <<  " slice: " << slice / tsize <<  endl;
00611       }
00612       */
00613 #ifdef HAVE_ZOLTAN2_OMP
00614 #pragma omp for
00615 #endif
00616       for(lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
00617         lno_t iteration = 0;
00618         while(1){
00619           if(++iteration > MAX_ITER_ALLOWED) {
00620             throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
00621           }
00622           CoordinatePoint <T> p = this->getPoint( this->assignedPrevious + cnt, state);
00623 
00624           bool isInHole = false;
00625           for(lno_t i = 0; i < holeCount; ++i){
00626             if(holes[i][0].isInArea(p)){
00627               isInHole = true;
00628               break;
00629             }
00630           }
00631           if(isInHole) continue;
00632           coords[0][cnt + tindex] = p.x;
00633           if(this->dimension > 1){
00634             coords[1][cnt + tindex] = p.y;
00635             if(this->dimension > 2){
00636               coords[2][cnt + tindex] = p.z;
00637             }
00638           }
00639           break;
00640         }
00641       }
00642     }
00643   }
00644 };
00645 
00646 template <typename T, typename lno_t, typename gno_t>
00647 class CoordinateNormalDistribution:public CoordinateDistribution<T,lno_t,gno_t>{
00648 public:
00649   CoordinatePoint<T> center;
00650   T standartDevx;
00651   T standartDevy;
00652   T standartDevz;
00653 
00654 
00655   virtual T getXCenter(){
00656     return center.x;
00657   }
00658   virtual T getXRadius(){
00659     return standartDevx;
00660   }
00661 
00662   CoordinateNormalDistribution(gno_t np_, int dim, CoordinatePoint<T> center_ ,
00663                                T sd_x, T sd_y, T sd_z, int wSize) :
00664     CoordinateDistribution<T,lno_t,gno_t>(np_,dim,wSize),
00665     standartDevx(sd_x), standartDevy(sd_y), standartDevz(sd_z)
00666   {
00667     this->center.x = center_.x;
00668     this->center.y = center_.y;
00669     this->center.z = center_.z;
00670   }
00671 
00672   virtual CoordinatePoint<T> getPoint(gno_t pindex, unsigned int &state){
00673 
00674     pindex = 0; // not used in normal distribution.
00675     CoordinatePoint <T> p;
00676 
00677     for(int i = 0; i < this->dimension; ++i){
00678       switch(i){
00679       case 0:
00680         p.x = normalDist(this->center.x, this->standartDevx, state);
00681         break;
00682       case 1:
00683         p.y = normalDist(this->center.y, this->standartDevy, state);
00684         break;
00685       case 2:
00686         p.z = normalDist(this->center.z, this->standartDevz, state);
00687         break;
00688       default:
00689         throw "unsupported dimension";
00690       }
00691     }
00692     return p;
00693   }
00694 
00695   virtual ~CoordinateNormalDistribution(){};
00696 private:
00697   T normalDist(T center_, T sd, unsigned int &state) {
00698     static bool derived=false;
00699     static T storedDerivation;
00700     T polarsqrt, normalsquared, normal1, normal2;
00701     if (!derived) {
00702       do {
00703         normal1=2.0*( T(rand_r(&state))/T(RAND_MAX) ) - 1.0;
00704         normal2=2.0*( T(rand_r(&state))/T(RAND_MAX) ) - 1.0;
00705         normalsquared=normal1*normal1+normal2*normal2;
00706       } while ( normalsquared>=1.0 || normalsquared == 0.0);
00707 
00708       polarsqrt=sqrt(-2.0*log(normalsquared)/normalsquared);
00709       storedDerivation=normal1*polarsqrt;
00710       derived=true;
00711       return normal2*polarsqrt*sd + center_;
00712     }
00713     else {
00714       derived=false;
00715       return storedDerivation*sd + center_;
00716     }
00717   }
00718 };
00719 
00720 template <typename T, typename lno_t, typename gno_t>
00721 class CoordinateUniformDistribution:public CoordinateDistribution<T,lno_t, gno_t>{
00722 public:
00723   T leftMostx;
00724   T rightMostx;
00725   T leftMosty;
00726   T rightMosty;
00727   T leftMostz;
00728   T rightMostz;
00729 
00730 
00731   virtual T getXCenter(){
00732     return (rightMostx - leftMostx)/2  + leftMostx;
00733   }
00734   virtual T getXRadius(){
00735     return (rightMostx - leftMostx)/2;
00736   }
00737 
00738 
00739   CoordinateUniformDistribution(gno_t np_, int dim, T l_x, T r_x, T l_y, T r_y,
00740                                 T l_z, T r_z, int wSize ) :
00741       CoordinateDistribution<T,lno_t,gno_t>(np_,dim,wSize),
00742       leftMostx(l_x), rightMostx(r_x), leftMosty(l_y), rightMosty(r_y),
00743       leftMostz(l_z), rightMostz(r_z){}
00744 
00745   virtual ~CoordinateUniformDistribution(){};
00746   virtual CoordinatePoint<T> getPoint(gno_t pindex, unsigned int &state){
00747 
00748 
00749     pindex = 0; //not used in uniform dist.
00750     CoordinatePoint <T> p;
00751     for(int i = 0; i < this->dimension; ++i){
00752       switch(i){
00753       case 0:
00754         p.x = uniformDist(this->leftMostx, this->rightMostx, state);
00755         break;
00756       case 1:
00757         p.y = uniformDist(this->leftMosty, this->rightMosty, state);
00758         break;
00759       case 2:
00760         p.z = uniformDist(this->leftMostz, this->rightMostz, state);
00761         break;
00762       default:
00763         throw "unsupported dimension";
00764       }
00765     }
00766     return p;
00767   }
00768 
00769 private:
00770 
00771   T uniformDist(T a, T b, unsigned int &state)
00772   {
00773     return (b-a)*(rand_r(&state) / double(RAND_MAX)) + a;
00774   }
00775 };
00776 
00777 template <typename T, typename lno_t, typename gno_t>
00778 class CoordinateGridDistribution:public CoordinateDistribution<T,lno_t,gno_t>{
00779 public:
00780   T leftMostx;
00781   T rightMostx;
00782   T leftMosty;
00783   T rightMosty;
00784   T leftMostz;
00785   T rightMostz;
00786   gno_t along_X, along_Y, along_Z;
00787   //T currentX, currentY, currentZ;
00788   T processCnt;
00789   int myRank;
00790   T xstep, ystep, zstep;
00791   gno_t xshift, yshift, zshift;
00792 
00793   virtual T getXCenter(){
00794     return (rightMostx - leftMostx)/2  + leftMostx;
00795   }
00796   virtual T getXRadius(){
00797     return (rightMostx - leftMostx)/2;
00798   }
00799 
00800 
00801   CoordinateGridDistribution(gno_t alongX, gno_t alongY, gno_t alongZ, int dim,
00802                              T l_x, T r_x, T l_y, T r_y, T l_z, T r_z ,
00803                              int myRank_, int wSize) :
00804       CoordinateDistribution<T,lno_t,gno_t>(alongX * alongY * alongZ,dim,wSize),
00805       leftMostx(l_x), rightMostx(r_x), leftMosty(l_y), rightMosty(r_y), leftMostz(l_z), rightMostz(r_z), myRank(myRank_){
00806     //currentX = leftMostx, currentY = leftMosty, currentZ = leftMostz;
00807     this->processCnt = 0;
00808     this->along_X = alongX; this->along_Y = alongY; this->along_Z = alongZ;
00809 
00810     if(this->along_X > 1)
00811       this->xstep = (rightMostx - leftMostx) / (alongX - 1);
00812     else
00813       this->xstep = 1;
00814     if(this->along_Y > 1)
00815       this->ystep = (rightMosty - leftMosty) / (alongY - 1);
00816     else
00817       this->ystep = 1;
00818     if(this->along_Z > 1)
00819       this->zstep = (rightMostz - leftMostz) / (alongZ - 1);
00820     else
00821       this->zstep = 1;
00822     xshift = 0; yshift = 0; zshift = 0;
00823   }
00824 
00825   virtual ~CoordinateGridDistribution(){};
00826   virtual CoordinatePoint<T> getPoint(gno_t pindex, unsigned int &state){
00827     //lno_t before = processCnt + this->assignedPrevious;
00828     //cout << "before:" << processCnt << " " << this->assignedPrevious << endl;
00829     //lno_t xshift = 0, yshift = 0, zshift = 0;
00830 
00831     //lno_t tmp = before % (this->along_X * this->along_Y);
00832     //xshift  = tmp % this->along_X;
00833     //yshift = tmp / this->along_X;
00834     //zshift = before / (this->along_X * this->along_Y);
00835 
00836     state = 0; //not used here
00837     this->zshift = pindex / (along_X * along_Y);
00838     this->yshift = (pindex % (along_X * along_Y)) / along_X;
00839     this->xshift = (pindex % (along_X * along_Y)) % along_X;
00840 
00841     //this->xshift = pindex / (along_Z * along_Y);
00842    // this->zshift = (pindex % (along_Z * along_Y)) / along_Y;
00843     //this->yshift = (pindex % (along_Z * along_Y)) % along_Y;
00844 
00845     CoordinatePoint <T> p;
00846     p.x = xshift * this->xstep + leftMostx;
00847     p.y = yshift * this->ystep + leftMosty;
00848     p.z = zshift * this->zstep + leftMostz;
00849 /*
00850     ++xshift;
00851     if(xshift == this->along_X){
00852       ++yshift;
00853       xshift = 0;
00854       if(yshift == this->along_Y){
00855         ++zshift;
00856         yshift = 0;
00857       }
00858     }
00859 */
00860     /*
00861     if(this->processCnt == 0){
00862       this->xshift = this->assignedPrevious / (along_Z * along_Y);
00863       //this->yshift = (this->assignedPrevious % (along_X * along_Y)) / along_X;
00864       this->zshift = (this->assignedPrevious % (along_Z * along_Y)) / along_Y;
00865       //this->xshift = (this->assignedPrevious % (along_X * along_Y)) % along_X;
00866       this->yshift = (this->assignedPrevious % (along_Z * along_Y)) % along_Y;
00867       ++this->processCnt;
00868     }
00869 
00870     CoordinatePoint <T> p;
00871     p.x = xshift * this->xstep + leftMostx;
00872     p.y = yshift * this->ystep + leftMosty;
00873     p.z = zshift * this->zstep + leftMostz;
00874 
00875     ++yshift;
00876     if(yshift == this->along_Y){
00877       ++zshift;
00878       yshift = 0;
00879       if(zshift == this->along_Z){
00880         ++xshift;
00881         zshift = 0;
00882       }
00883 
00884     }
00885     */
00886     /*
00887     if(this->requested - 1 > this->processCnt){
00888       this->processCnt++;
00889     } else {
00890       cout << "req:" << this->requested << " pr:" <<this->processCnt << endl;
00891       cout << "p:" << p.x << " " << p.y << " " << p.z <<  endl ;
00892       cout << "s:" << xshift << " " << yshift << " " << zshift <<  endl ;
00893       cout << "st:" << this->xstep << " " << this->ystep << " " << this->zstep <<  endl ;
00894     }
00895     */
00896     return p;
00897   }
00898 
00899 private:
00900 
00901 };
00902 
00903 template <typename scalar_t, typename lno_t, typename gno_t, typename node_t>
00904 class GeometricGenerator {
00905 private:
00906   Hole<scalar_t> **holes; //to represent if there is any hole in the input
00907   int holeCount;
00908   int coordinate_dimension;  //dimension of the geometry
00909   gno_t numGlobalCoords;  //global number of coordinates requested to be created.
00910   lno_t numLocalCoords;
00911   float *loadDistributions; //sized as the number of processors, the load of each processor.
00912   bool loadDistSet;
00913   bool distinctCoordSet;
00914   CoordinateDistribution<scalar_t, lno_t,gno_t> **coordinateDistributions;
00915   int distributionCount;
00916   //CoordinatePoint<scalar_t> *points;
00917   scalar_t **coords;
00918   scalar_t **wghts;
00919   WeightDistribution<scalar_t,scalar_t> **wd;
00920   int numWeightsPerCoord;
00921   int predistribution;
00922   RCP<const Teuchos::Comm<int> > comm;
00923   //RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmVector;
00924   //RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmwVector;
00925   int worldSize;
00926   int myRank;
00927   scalar_t minx;
00928   scalar_t maxx;
00929   scalar_t miny;
00930   scalar_t maxy;
00931   scalar_t minz;
00932   scalar_t maxz;
00933   std::string outfile;
00934   float perturbation_ratio;
00935 
00936   typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> tMVector_t;
00937   typedef Tpetra::Map<lno_t, gno_t, node_t> tMap_t;
00938 
00939 
00940   template <typename tt>
00941   tt getParamVal( const Teuchos::ParameterEntry& pe, const std::string &paramname){
00942     tt returnVal;
00943     try {
00944       returnVal = Teuchos::getValue<tt>(pe);
00945     }
00946     catch (...){
00947       throw INVALID(paramname);
00948     }
00949     return returnVal;
00950   }
00951 
00952   int countChar (std::string inStr, char cntChar){
00953     int cnt = 0;
00954     for (unsigned int i = 0; i < inStr.size(); ++i){
00955       if (inStr[i] == cntChar) {
00956         cnt++;
00957       }
00958     }
00959     return cnt;
00960   }
00961 
00962   template <typename tt>
00963   std::string toString(tt obj){
00964     std::stringstream ss (std::stringstream::in |std::stringstream::out);
00965     ss << obj;
00966     std::string tmp = "";
00967     ss >> tmp;
00968     return tmp;
00969   }
00970 
00971   template <typename tt>
00972   tt fromString(std::string obj){
00973     std::stringstream ss (std::stringstream::in | std::stringstream::out);
00974     ss << obj;
00975     tt tmp;
00976     ss >> tmp;
00977     if (ss.fail()){
00978       throw "Cannot convert string " + obj;
00979     }
00980     return tmp;
00981   }
00982 
00983 
00984   void splitString(std::string inStr, char splitChar, std::string *outSplittedStr){
00985     std::stringstream ss (std::stringstream::in | std::stringstream::out);
00986     ss << inStr;
00987     int cnt = 0;
00988     while (!ss.eof()){
00989       std::string tmp = "";
00990       std::getline(ss, tmp ,splitChar);
00991       outSplittedStr[cnt++] = tmp;
00992     }
00993   }
00994 
00995   /*
00996   void getDistinctCoordinateDescription(std::string distinctDescription){
00997 
00998     this->distinctCoordinates = new bool[this->dimension];
00999     if(distinctDescription != ""){
01000       int argCnt = this->countChar(distinctDescription, ',') + 1;
01001       if(argCnt != this->dimension) {
01002         throw "Invalid parameter count for distinct_coordinates. Size should be equal to dimension.";
01003       }
01004 
01005       std::string *splittedStr = new std::string[argCnt];
01006       splitString(holeDescription, ',', splittedStr);
01007 
01008       for(int i = 0; i < argCnt; ++i){
01009         if(splittedStr[i] == "T"){
01010           distinctCoordinates[i] = true;
01011         } else if(splittedStr[i] == "F"){
01012           distinctCoordinates[i] = false;
01013         } else {
01014           throw "Invalid parameter " + splittedStr[i] + " for distinct_coordinates.";
01015         }
01016       }
01017       delete []splittedStr;
01018     }
01019     else {
01020       for(int i = 0; i < this->dimension; ++i){
01021         distinctCoordinates[i] = false;
01022       }
01023     }
01024   }
01025    */
01026 
01027 
01028   void getCoordinateDistributions(std::string coordinate_distributions){
01029     if(coordinate_distributions == ""){
01030       throw "At least one distribution function must be provided to coordinate generator.";
01031     }
01032 
01033     int argCnt = this->countChar(coordinate_distributions, ',') + 1;
01034     std::string *splittedStr = new std::string[argCnt];
01035     splitString(coordinate_distributions, ',', splittedStr);
01036     coordinateDistributions = (CoordinateDistribution<scalar_t, lno_t,gno_t> **) malloc(sizeof (CoordinateDistribution<scalar_t, lno_t,gno_t> *) * 1);
01037     for(int i = 0; i < argCnt; ){
01038       coordinateDistributions = (CoordinateDistribution<scalar_t, lno_t,gno_t> **)realloc((void *)coordinateDistributions, (this->distributionCount + 1)* sizeof(CoordinateDistribution<scalar_t, lno_t,gno_t> *));
01039 
01040       std::string distName = splittedStr[i++];
01041       gno_t np_ = 0;
01042       if(distName == "NORMAL"){
01043         int reqArg = 5;
01044         if (this->coordinate_dimension == 3){
01045           reqArg = 7;
01046         }
01047         if(i + reqArg > argCnt) {
01048           std::string tmp = toString<int>(reqArg);
01049           throw INVALID_SHAPE_ARG(distName, tmp);
01050         }
01051         np_ = fromString<gno_t>(splittedStr[i++]);
01052         CoordinatePoint<scalar_t> pp;
01053 
01054         pp.x = fromString<scalar_t>(splittedStr[i++]);
01055         pp.y = fromString<scalar_t>(splittedStr[i++]);
01056         pp.z = 0;
01057         if(this->coordinate_dimension == 3){
01058           pp.z = fromString<scalar_t>(splittedStr[i++]);
01059         }
01060 
01061         scalar_t sd_x = fromString<scalar_t>(splittedStr[i++]);
01062         scalar_t sd_y = fromString<scalar_t>(splittedStr[i++]);
01063         scalar_t sd_z = 0;
01064         if(this->coordinate_dimension == 3){
01065           sd_z = fromString<scalar_t>(splittedStr[i++]);
01066         }
01067         this->coordinateDistributions[this->distributionCount++] = new CoordinateNormalDistribution<scalar_t, lno_t,gno_t>(np_, this->coordinate_dimension, pp , sd_x, sd_y, sd_z, this->worldSize );
01068 
01069       } else if(distName == "UNIFORM" ){
01070         int reqArg = 5;
01071         if (this->coordinate_dimension == 3){
01072           reqArg = 7;
01073         }
01074         if(i + reqArg > argCnt) {
01075           std::string tmp = toString<int>(reqArg);
01076           throw INVALID_SHAPE_ARG(distName, tmp);
01077         }
01078         np_ = fromString<gno_t>(splittedStr[i++]);
01079         scalar_t l_x = fromString<scalar_t>(splittedStr[i++]);
01080         scalar_t r_x = fromString<scalar_t>(splittedStr[i++]);
01081         scalar_t l_y = fromString<scalar_t>(splittedStr[i++]);
01082         scalar_t r_y = fromString<scalar_t>(splittedStr[i++]);
01083 
01084         scalar_t l_z = 0, r_z = 0;
01085 
01086         if(this->coordinate_dimension == 3){
01087           l_z = fromString<scalar_t>(splittedStr[i++]);
01088           r_z = fromString<scalar_t>(splittedStr[i++]);
01089         }
01090 
01091         this->coordinateDistributions[this->distributionCount++] = new CoordinateUniformDistribution<scalar_t, lno_t,gno_t>( np_,  this->coordinate_dimension, l_x, r_x, l_y, r_y, l_z, r_z, this->worldSize );
01092       } else if (distName == "GRID"){
01093         int reqArg = 6;
01094         if(this->coordinate_dimension == 3){
01095           reqArg = 9;
01096         }
01097         if(i + reqArg > argCnt) {
01098           std::string tmp = toString<int>(reqArg);
01099           throw INVALID_SHAPE_ARG(distName, tmp);
01100         }
01101 
01102         gno_t np_x = fromString<gno_t>(splittedStr[i++]);
01103         gno_t np_y = fromString<gno_t>(splittedStr[i++]);
01104         gno_t np_z = 1;
01105 
01106 
01107         if(this->coordinate_dimension == 3){
01108           np_z = fromString<gno_t>(splittedStr[i++]);
01109         }
01110 
01111         np_ = np_x * np_y * np_z;
01112         scalar_t l_x = fromString<scalar_t>(splittedStr[i++]);
01113         scalar_t r_x = fromString<scalar_t>(splittedStr[i++]);
01114         scalar_t l_y = fromString<scalar_t>(splittedStr[i++]);
01115         scalar_t r_y = fromString<scalar_t>(splittedStr[i++]);
01116 
01117         scalar_t l_z = 0, r_z = 0;
01118 
01119         if(this->coordinate_dimension == 3){
01120           l_z = fromString<scalar_t>(splittedStr[i++]);
01121           r_z = fromString<scalar_t>(splittedStr[i++]);
01122         }
01123 
01124         if(np_x < 1 || np_z < 1 || np_y < 1 ){
01125           throw "Provide at least 1 point along each dimension for grid test.";
01126         }
01127         //cout << "ly:" << l_y << " ry:" << r_y << endl;
01128         this->coordinateDistributions[this->distributionCount++] = new CoordinateGridDistribution<scalar_t, lno_t,gno_t>
01129         (np_x, np_y,np_z, this->coordinate_dimension, l_x, r_x,l_y, r_y, l_z, r_z , this->myRank, this->worldSize);
01130 
01131       }
01132       else {
01133         std::string tmp = toString<int>(this->coordinate_dimension);
01134         throw INVALIDSHAPE(distName, tmp);
01135       }
01136       this->numGlobalCoords += (gno_t) np_;
01137     }
01138     delete []splittedStr;
01139   }
01140 
01141   void getProcLoadDistributions(std::string proc_load_distributions){
01142 
01143     this->loadDistributions = new float[this->worldSize];
01144     if(proc_load_distributions == ""){
01145       float r = 1.0 / this->worldSize;
01146       for(int i = 0; i < this->worldSize; ++i){
01147         this->loadDistributions[i] = r;
01148       }
01149     } else{
01150 
01151 
01152       int argCnt = this->countChar(proc_load_distributions, ',') + 1;
01153       if(argCnt != this->worldSize) {
01154         throw "Invalid parameter count load distributions. Given " + toString<int>(argCnt) + " processor size is " + toString<int>(this->worldSize);
01155       }
01156       std::string *splittedStr = new std::string[argCnt];
01157       splitString(proc_load_distributions, ',', splittedStr);
01158       for(int i = 0; i < argCnt; ++i){
01159         this->loadDistributions[i] = fromString<float>(splittedStr[i]);
01160       }
01161       delete []splittedStr;
01162 
01163 
01164       float sum = 0;
01165       for(int i = 0; i < this->worldSize; ++i){
01166         sum += this->loadDistributions[i];
01167       }
01168       if (fabs(sum - 1.0) > 10*std::numeric_limits<float>::epsilon()){
01169         throw "Processor load ratios do not sum to 1.0.";
01170       }
01171     }
01172 
01173   }
01174 
01175   void getHoles(std::string holeDescription){
01176     if(holeDescription == ""){
01177       return;
01178     }
01179     this->holes =  (Hole<scalar_t> **) malloc(sizeof (Hole <scalar_t>*));
01180     int argCnt = this->countChar(holeDescription, ',') + 1;
01181     std::string *splittedStr = new std::string[argCnt];
01182     splitString(holeDescription, ',', splittedStr);
01183 
01184     for(int i = 0; i < argCnt; ){
01185       holes = (Hole<scalar_t> **)realloc((void *)holes, (this->holeCount + 1)* sizeof(Hole<scalar_t> *));
01186 
01187       std::string shapeName = splittedStr[i++];
01188       if(shapeName == "SQUARE" && this->coordinate_dimension == 2){
01189         if(i + 3 > argCnt) {
01190           throw INVALID_SHAPE_ARG(shapeName, "3");
01191         }
01192         CoordinatePoint<scalar_t> pp;
01193         pp.x = fromString<scalar_t>(splittedStr[i++]);
01194         pp.y = fromString<scalar_t>(splittedStr[i++]);
01195         scalar_t edge = fromString<scalar_t>(splittedStr[i++]);
01196         this->holes[this->holeCount++] = new SquareHole<scalar_t>(pp, edge);
01197       } else if(shapeName == "RECTANGLE" && this->coordinate_dimension == 2){
01198         if(i + 4 > argCnt) {
01199           throw INVALID_SHAPE_ARG(shapeName, "4");
01200         }
01201         CoordinatePoint<scalar_t> pp;
01202         pp.x = fromString<scalar_t>(splittedStr[i++]);
01203         pp.y = fromString<scalar_t>(splittedStr[i++]);
01204         scalar_t edgex = fromString<scalar_t>(splittedStr[i++]);
01205         scalar_t edgey = fromString<scalar_t>(splittedStr[i++]);
01206 
01207         this->holes[this->holeCount++] = new RectangleHole<scalar_t>(pp, edgex,edgey);
01208       } else if(shapeName == "CIRCLE" && this->coordinate_dimension == 2){
01209         if(i + 3 > argCnt) {
01210           throw INVALID_SHAPE_ARG(shapeName, "3");
01211         }
01212         CoordinatePoint<scalar_t> pp;
01213         pp.x = fromString<scalar_t>(splittedStr[i++]);
01214         pp.y = fromString<scalar_t>(splittedStr[i++]);
01215         scalar_t r = fromString<scalar_t>(splittedStr[i++]);
01216         this->holes[this->holeCount++] = new CircleHole<scalar_t>(pp, r);
01217       }  else if(shapeName == "CUBE" && this->coordinate_dimension == 3){
01218         if(i + 4 > argCnt) {
01219           throw INVALID_SHAPE_ARG(shapeName, "4");
01220         }
01221         CoordinatePoint<scalar_t> pp;
01222         pp.x = fromString<scalar_t>(splittedStr[i++]);
01223         pp.y = fromString<scalar_t>(splittedStr[i++]);
01224         pp.z = fromString<scalar_t>(splittedStr[i++]);
01225         scalar_t edge = fromString<scalar_t>(splittedStr[i++]);
01226         this->holes[this->holeCount++] = new CubeHole<scalar_t>(pp, edge);
01227       }  else if(shapeName == "RECTANGULAR_PRISM" && this->coordinate_dimension == 3){
01228         if(i + 6 > argCnt) {
01229           throw INVALID_SHAPE_ARG(shapeName, "6");
01230         }
01231         CoordinatePoint<scalar_t> pp;
01232         pp.x = fromString<scalar_t>(splittedStr[i++]);
01233         pp.y = fromString<scalar_t>(splittedStr[i++]);
01234         pp.z = fromString<scalar_t>(splittedStr[i++]);
01235         scalar_t edgex = fromString<scalar_t>(splittedStr[i++]);
01236         scalar_t edgey = fromString<scalar_t>(splittedStr[i++]);
01237         scalar_t edgez = fromString<scalar_t>(splittedStr[i++]);
01238         this->holes[this->holeCount++] = new RectangularPrismHole<scalar_t>(pp, edgex, edgey, edgez);
01239 
01240       }  else if(shapeName == "SPHERE" && this->coordinate_dimension == 3){
01241         if(i + 4 > argCnt) {
01242           throw INVALID_SHAPE_ARG(shapeName, "4");
01243         }
01244         CoordinatePoint<scalar_t> pp;
01245         pp.x = fromString<scalar_t>(splittedStr[i++]);
01246         pp.y = fromString<scalar_t>(splittedStr[i++]);
01247         pp.z = fromString<scalar_t>(splittedStr[i++]);
01248         scalar_t r = fromString<scalar_t>(splittedStr[i++]);
01249         this->holes[this->holeCount++] = new SphereHole<scalar_t>(pp, r);
01250       }  else {
01251         std::string tmp = toString<int>(this->coordinate_dimension);
01252         throw INVALIDSHAPE(shapeName, tmp);
01253       }
01254     }
01255     delete [] splittedStr;
01256   }
01257 
01258   void getWeightDistribution(std::string *weight_distribution_arr, int wdimension){
01259     int wcount = 0;
01260 
01261     this->wd = new WeightDistribution<scalar_t,scalar_t> *[wdimension];
01262     for(int ii = 0; ii < MAX_WEIGHT_DIM; ++ii){
01263       std::string weight_distribution = weight_distribution_arr[ii];
01264       if(weight_distribution == "") continue;
01265       if(wcount == wdimension) {
01266         throw "Weight Dimension is provided as " + toString<int>(wdimension) + ". More weight distribution is provided.";
01267       }
01268 
01269       int count = this->countChar(weight_distribution, ' ');
01270       std::string *splittedStr = new string[count + 1];
01271       this->splitString(weight_distribution, ' ', splittedStr);
01272       //cout << count << endl;
01273       scalar_t c=1;
01274       scalar_t a1=0,a2=0,a3=0;
01275       scalar_t x1=0,y1=0,z1=0;
01276       scalar_t b1=1,b2=1,b3=1;
01277       scalar_t *steps = NULL;
01278       scalar_t *values= NULL;
01279       int stepCount = 0;
01280       int valueCount = 1;
01281 
01282       for (int i = 1; i < count + 1; ++i){
01283         int assignmentCount = this->countChar(splittedStr[i], '=');
01284         if (assignmentCount != 1){
01285           throw "Error at the argument " + splittedStr[i];
01286         }
01287         std::string parameter_vs_val[2];
01288         this->splitString(splittedStr[i], '=', parameter_vs_val);
01289         std::string parameter = parameter_vs_val[0];
01290         std::string value = parameter_vs_val[1];
01291         //cout << "parameter:" << parameter << " value:" << value << endl;
01292 
01293         if (parameter == "a1"){
01294           a1 = this->fromString<scalar_t>(value);
01295         }
01296         else if (parameter == "a2"){
01297           if(this->coordinate_dimension > 1){
01298             a2 = this->fromString<scalar_t>(value);
01299           }
01300           else {
01301             throw  parameter+ " argument is not valid when dimension is " + toString<int>(this->coordinate_dimension);
01302           }
01303 
01304         }
01305         else if (parameter == "a3"){
01306           if(this->coordinate_dimension > 2){
01307             a3 = this->fromString<scalar_t>(value);
01308           }
01309           else {
01310             throw parameter+ " argument is not valid when dimension is " + toString<int>(this->coordinate_dimension);
01311           }
01312         }
01313         else if (parameter == "b1"){
01314           b1 = this->fromString<scalar_t>(value);
01315         }
01316         else if (parameter == "b2"){
01317           if(this->coordinate_dimension > 1){
01318             b2 = this->fromString<scalar_t>(value);
01319           }
01320           else {
01321             throw parameter+ " argument is not valid when dimension is " + toString<int>(this->coordinate_dimension);
01322           }
01323         }
01324         else if (parameter == "b3"){
01325 
01326           if(this->coordinate_dimension > 2){
01327             b3 = this->fromString<scalar_t>(value);
01328           }
01329           else {
01330             throw parameter+ " argument is not valid when dimension is " + toString<int>(this->coordinate_dimension);
01331           }
01332         }
01333         else if (parameter == "c"){
01334           c = this->fromString<scalar_t>(value);
01335         }
01336         else if (parameter == "x1"){
01337           x1 = this->fromString<scalar_t>(value);
01338         }
01339         else if (parameter == "y1"){
01340           if(this->coordinate_dimension > 1){
01341             y1 = this->fromString<scalar_t>(value);
01342           }
01343           else {
01344             throw parameter+ " argument is not valid when dimension is " + toString<int>(this->coordinate_dimension);
01345           }
01346         }
01347         else if (parameter == "z1"){
01348           if(this->coordinate_dimension > 2){
01349             z1 = this->fromString<scalar_t>(value);
01350           }
01351           else {
01352             throw parameter+ " argument is not valid when dimension is " + toString<int>(this->coordinate_dimension);
01353           }
01354         }
01355         else if (parameter == "steps"){
01356           stepCount = this->countChar(value, ',') + 1;
01357           std::string *stepstr = new std::string[stepCount];
01358           this->splitString(value, ',', stepstr);
01359           steps = new scalar_t[stepCount];
01360           for (int j = 0; j < stepCount; ++j){
01361             steps[j] = this->fromString<scalar_t>(stepstr[j]);
01362           }
01363           delete [] stepstr;
01364         }
01365         else if (parameter == "values"){
01366           valueCount = this->countChar(value, ',') + 1;
01367           std::string *stepstr = new std::string[valueCount];
01368           this->splitString(value, ',', stepstr);
01369           values = new scalar_t[valueCount];
01370           for (int j = 0; j < valueCount; ++j){
01371             values[j] = this->fromString<scalar_t>(stepstr[j]);
01372           }
01373           delete [] stepstr;
01374         }
01375         else {
01376           throw "Invalid parameter name at " + splittedStr[i];
01377         }
01378       }
01379 
01380       delete []splittedStr;
01381       if(stepCount + 1!= valueCount){
01382         throw "Step count: " + this->toString<int>(stepCount) + " must be 1 less than value count: " + this->toString<int>(valueCount);
01383       }
01384 
01385 
01386       this->wd[wcount++] =  new SteppedEquation<scalar_t,scalar_t>(a1, a2,  a3,  b1,  b2,  b3,  c,  x1,  y1,  z1, steps, values, stepCount);
01387 
01388       if(stepCount > 0){
01389         delete [] steps;
01390         delete [] values;
01391 
01392       }
01393     }
01394     if(wcount != this->numWeightsPerCoord){
01395       throw "Weight Dimension is provided as " + toString<int>(wdimension) + ". But " + toString<int>(wcount)+" weight distributions are provided.";
01396     }
01397   }
01398 
01399   void parseParams(const Teuchos::ParameterList & params){
01400     try {
01401       std::string holeDescription  = "";
01402       std::string proc_load_distributions = "";
01403       std::string distinctDescription = "";
01404       std::string coordinate_distributions = "";
01405       std::string numWeightsPerCoord_parameters[MAX_WEIGHT_DIM];
01406       for (int i = 0; i < MAX_WEIGHT_DIM; ++i){
01407         numWeightsPerCoord_parameters[i] = "";
01408       }
01409 
01410 
01411       for (Teuchos::ParameterList::ConstIterator pit = params.begin(); pit != params.end(); ++pit ){
01412         const std::string &paramName = params.name(pit);
01413 
01414         const Teuchos::ParameterEntry &pe = params.entry(pit);
01415 
01416         if(paramName.find("hole-") == 0){
01417           if(holeDescription == ""){
01418             holeDescription = getParamVal<std::string>(pe, paramName);
01419           }
01420           else {
01421             holeDescription +=","+getParamVal<std::string>(pe, paramName);
01422           }
01423         }
01424         else if(paramName.find("distribution-") == 0){
01425           if(coordinate_distributions == "")
01426             coordinate_distributions = getParamVal<std::string>(pe, paramName);
01427           else
01428             coordinate_distributions +=  ","+getParamVal<std::string>(pe, paramName);
01429           //cout << coordinate_distributions << endl;
01430           //TODO coordinate distribution description
01431         }
01432 
01433         else if (paramName.find(weight_distribution_string) == 0){
01434           std::string weight_dist_param = paramName.substr(weight_distribution_string.size());
01435           int dash_pos = weight_dist_param.find("-");
01436           std::string distribution_index_string = weight_dist_param.substr(0, dash_pos);
01437           int distribution_index = fromString<int>(distribution_index_string);
01438 
01439           if(distribution_index >= MAX_WEIGHT_DIM){
01440             throw "Given distribution index:" + distribution_index_string + " larger than maximum allowed number of weights:" + toString<int>(MAX_WEIGHT_DIM);
01441           }
01442           numWeightsPerCoord_parameters[distribution_index] +=  " " + weight_dist_param.substr(dash_pos + 1)+ "="+ getParamVal<std::string>(pe, paramName);
01443         }
01444         else if(paramName == "dim"){
01445           int dim = fromString<int>(getParamVal<std::string>(pe, paramName));
01446           if(dim < 2 && dim > 3){
01447             throw INVALID(paramName);
01448           } else {
01449             this->coordinate_dimension = dim;
01450           }
01451         }
01452         else if(paramName == "wdim"){
01453           int dim = fromString<int>(getParamVal<std::string>(pe, paramName));
01454           if(dim < 1 && dim > MAX_WEIGHT_DIM){
01455             throw INVALID(paramName);
01456           } else {
01457             this->numWeightsPerCoord = dim;
01458           }
01459         }
01460         else if(paramName == "predistribution"){
01461           int pre_distribution = fromString<int>(getParamVal<std::string>(pe, paramName));
01462           if(pre_distribution < 0 && pre_distribution > 3){
01463             throw INVALID(paramName);
01464           } else {
01465             this->predistribution = pre_distribution;
01466           }
01467         }
01468         else if(paramName == "perturbation_ratio"){
01469           float perturbation = fromString<float>(getParamVal<std::string>(pe, paramName));
01470           if(perturbation < 0 && perturbation > 1){
01471             throw INVALID(paramName);
01472           } else {
01473             this->perturbation_ratio = perturbation;
01474           }
01475         }
01476 
01477 
01478         else if(paramName == "proc_load_distributions"){
01479           proc_load_distributions = getParamVal<std::string>(pe, paramName);
01480           this->loadDistSet = true;
01481         }
01482 
01483         else if(paramName == "distinct_coordinates"){
01484           distinctDescription = getParamVal<std::string>(pe, paramName);
01485           if(distinctDescription == "T"){
01486             this->distinctCoordSet = true;
01487           } else if(distinctDescription == "F"){
01488             this->distinctCoordSet = true;
01489           } else {
01490             throw "Invalid parameter for distinct_coordinates: " + distinctDescription + ". Candidates: T or F." ;
01491           }
01492         }
01493 
01494         else if(paramName == "out_file"){
01495           this->outfile = getParamVal<std::string>(pe, paramName);
01496         }
01497 
01498         else {
01499           throw INVALID(paramName);
01500         }
01501       }
01502 
01503 
01504       if(this->coordinate_dimension == 0){
01505         throw "Dimension must be provided to coordinate generator.";
01506       }
01507       /*
01508       if(this->globalNumCoords == 0){
01509         throw "Number of coordinates must be provided to coordinate generator.";
01510       }
01511        */
01512       /*
01513       if(maxx <= minx ){
01514         throw "Error: maxx= "+ toString<scalar_t>(maxx)+ " and minx=" + toString<scalar_t>(minx);
01515       }
01516       if(maxy <= miny ){
01517         throw "Error: maxy= "+ toString<scalar_t>(maxy)+ " and miny=" + toString<scalar_t>(miny);
01518 
01519       }
01520       if(this->dimension == 3 && maxz <= minz ){
01521         throw "Error: maxz= "+ toString<scalar_t>(maxz)+ " and minz=" + toString<scalar_t>(minz);
01522       }
01523        */
01524       if (this->loadDistSet && this->distinctCoordSet){
01525         throw "distinct_coordinates and proc_load_distributions parameters cannot be satisfied together.";
01526       }
01527       this->getHoles(holeDescription);
01528       //this->getDistinctCoordinateDescription(distinctDescription);
01529       this->getProcLoadDistributions(proc_load_distributions);
01530       this->getCoordinateDistributions(coordinate_distributions);
01531       this->getWeightDistribution(numWeightsPerCoord_parameters, this->numWeightsPerCoord);
01532       /*
01533       if(this->numGlobalCoords <= 0){
01534         throw "Must have at least 1 point";
01535       }
01536        */
01537     }
01538     catch(std::string s){
01539       throw s;
01540     }
01541 
01542     catch(char * s){
01543       throw s;
01544     }
01545 
01546     catch(char const* s){
01547       throw s;
01548     }
01549 
01550   }
01551 public:
01552 
01553   ~GeometricGenerator(){
01554     if(this->holes){
01555       for (int i = 0; i < this->holeCount; ++i){
01556         delete this->holes[i];
01557       }
01558       free (this->holes);
01559     }
01560 
01561 
01562     delete []loadDistributions; //sized as the number of processors, the load of each processor.
01563     //delete []distinctCoordinates; // if processors have different or same range for coordinates to be created.
01564     if(coordinateDistributions){
01565 
01566       for (int i = 0; i < this->distributionCount; ++i){
01567         delete this->coordinateDistributions[i];
01568       }
01569       free (this->coordinateDistributions);
01570     }
01571     if (this->wd){
01572       for (int i = 0; i < this->numWeightsPerCoord; ++i){
01573         delete this->wd[i];
01574       }
01575       delete []this->wd;
01576     }
01577 
01578     if(this->numWeightsPerCoord){
01579       for(int i = 0; i < this->numWeightsPerCoord; ++i)
01580       delete [] this->wghts[i];
01581       delete []this->wghts;
01582     }
01583     if(this->coordinate_dimension){
01584       for(int i = 0; i < this->coordinate_dimension; ++i)
01585       delete [] this->coords[i];
01586       delete [] this->coords;
01587     }
01588     //delete []this->points;
01589   }
01590 
01591   void print_description(){
01592     cout <<"\nGeometric Generator Parameter File Format:" << endl;
01593     cout <<"- dim=Coordinate Dimension: 2 or 3" << endl;
01594     cout <<"- Available distributions:" << endl;
01595     cout <<"\tUNIFORM: -> distribution-1=UNIFORM,NUMCOORDINATES,XMIN,XMAX,YMIN,YMAX{,ZMIN,ZMAX}" << endl;
01596     cout <<"\tGRID: -> distribution-2=GRID,XLENGTH,YLENGTH{,ZLENGTH},XMIN,XMAX,YMIN,YMAX{,ZMIN,ZMAX}" << endl;
01597     cout <<"\tNORMAL: -> distribution-3=NORMAL,XCENTER,YCENTER{,ZCENTER},XSD,YSD,{,ZSD}" << endl;
01598     cout <<"- wdim=numWeightsPerCoord:  There should be as many weight function as number of weights per coord." << endl;
01599     cout <<"- Weight Equation: w = (a1 * (x - x1)^b1) + (a2 * (y - y1)^b2) + (a3 * (z - z1)^b3) + c" << endl;
01600     cout << "Parameter settings:" << endl;
01601     cout << "\tWeightDistribution-1-a1=a1 " << endl;
01602     cout << "\tWeightDistribution-1-a2=a2 " << endl;
01603     cout << "\tWeightDistribution-1-a3=a3 " << endl;
01604     cout << "\tWeightDistribution-1-b1=b1 " << endl;
01605     cout << "\tWeightDistribution-1-b2=b2 " << endl;
01606     cout << "\tWeightDistribution-1-b3=b3 " << endl;
01607     cout << "\tWeightDistribution-1-x1=x1 " << endl;
01608     cout << "\tWeightDistribution-1-y1=y1 " << endl;
01609     cout << "\tWeightDistribution-1-z1=z1 " << endl;
01610     cout << "\tWeightDistribution-1-c=c " << endl;
01611     cout << "\tIt is possible to set step function to the result of weight equation." << endl;
01612     cout << "\tWeightDistribution-1-steps=step1,step2,step3:increasing order" << endl;
01613     cout << "\tWeightDistribution-1-values=val1,val2,val3,val4." << endl;
01614     cout << "\t\tIf w < step1 -> w = val1" << endl;
01615     cout << "\t\tElse if w < step2 -> w = val2" << endl;
01616     cout << "\t\tElse if w < step3 -> w = val3" << endl;
01617     cout << "\t\tElse  -> w = val4" << endl;
01618     cout <<"- Holes:" << endl;
01619     cout << "\thole-1:SPHERE,XCENTER,YCENTER,ZCENTER,RADIUS (only for dim=3)" << endl;
01620     cout << "\thole-2:CUBE,XCENTER,YCENTER,ZCENTER,EDGE (only for dim=3)" << endl;
01621     cout << "\thole-3:RECTANGULAR_PRISM,XCENTER,YCENTER,ZCENTER,XEDGE,YEDGE,ZEDGE (only for dim=3)" << endl;
01622     cout << "\thole-4:SQUARE,XCENTER,YCENTER,EDGE (only for dim=2)" << endl;
01623     cout << "\thole-5:RECTANGLE,XCENTER,YCENTER,XEDGE,YEDGE (only for dim=2)" << endl;
01624     cout << "\thole-6:CIRCLE,XCENTER,YCENTER,RADIUS (only for dim=2)" << endl;
01625     cout << "- out_file:out_file_path : if provided output will be written to files." << endl;
01626     cout << "- proc_load_distributions:ratio_0, ratio_1, ratio_2....ratio_n. Loads of each processor, should be as many as MPI ranks and should sum up to 1." << endl;
01627     cout << "- predistribution:distribution_option. Predistribution of the coordinates to the processors. 0 for NONE, 1 RCB, 2 MJ, 3 BLOCK." << endl;
01628     cout << "- perturbation_ratio:the percent of the local data which will be perturbed in order to simulate the changes in the dynamic partitioning. Float value between 0 and 1." << endl;
01629   }
01630 
01631   GeometricGenerator(Teuchos::ParameterList &params, const RCP<const Teuchos::Comm<int> > & comm_){
01632     this->wd = NULL;
01633     this->comm = comm_;
01634     this->holes = NULL; //to represent if there is any hole in the input
01635     this->coordinate_dimension = 0;  //dimension of the geometry
01636     this->numWeightsPerCoord = 0;
01637     this->worldSize = comm_->getSize(); //comminication world object.
01638     this->numGlobalCoords = 0;  //global number of coordinates requested to be created.
01639     this->loadDistributions = NULL; //sized as the number of processors, the load of each processor.
01640     //this->distinctCoordinates = NULL; // if processors have different or same range for coordinates to be created.
01641     this->coordinateDistributions = NULL;
01642     this->holeCount = 0;
01643     this->distributionCount = 0;
01644     this->outfile = "";
01645     this->predistribution = 0;
01646     this->perturbation_ratio = 0;
01647     //this->points =  NULL;
01648 
01649     /*
01650     this->minx = 0;
01651     this->maxx = 0;
01652     this->miny = 0;
01653     this->maxy = 0;
01654     this->minz = 0;
01655     this->maxz = 0;
01656      */
01657     this->loadDistSet = false;
01658     this->distinctCoordSet = false;
01659     this->myRank = comm_->getRank();
01660 
01661     try {
01662       this->parseParams(params);
01663     }
01664     catch(std::string s){
01665       if(myRank == 0){
01666         print_description();
01667       }
01668       throw s;
01669     }
01670 
01671 
01672 
01673 
01674     lno_t myPointCount = 0;
01675     this->numGlobalCoords = 0;
01676 
01677     gno_t prefixSum = 0;
01678     for(int i = 0; i < this->distributionCount; ++i){
01679       for(int ii = 0; ii < this->worldSize; ++ii){
01680         lno_t increment  = lno_t (this->coordinateDistributions[i]->numPoints * this->loadDistributions[ii]);
01681         if (gno_t(ii) < this->coordinateDistributions[i]->numPoints % this->worldSize){
01682           increment += 1;
01683         }
01684         this->numGlobalCoords += increment;
01685         if(ii < myRank){
01686           prefixSum += increment;
01687         }
01688       }
01689       myPointCount += lno_t(this->coordinateDistributions[i]->numPoints * this->loadDistributions[myRank]);
01690       if (gno_t(myRank) < this->coordinateDistributions[i]->numPoints % this->worldSize){
01691         myPointCount += 1;
01692       }
01693     }
01694 
01695     this->coords = new scalar_t *[this->coordinate_dimension];
01696     for(int i = 0; i < this->coordinate_dimension; ++i){
01697       this->coords[i] = new scalar_t[myPointCount];
01698     }
01699 
01700     for (int ii = 0; ii < this->coordinate_dimension; ++ii){
01701 #ifdef HAVE_ZOLTAN2_OMP
01702 #pragma omp parallel for
01703 #endif
01704       for(lno_t i = 0; i < myPointCount; ++i){
01705         this->coords[ii][i] = 0;
01706       }
01707     }
01708 
01709     this->numLocalCoords = 0;
01710     srand ((myRank + 1) * this->numLocalCoords);
01711     for (int i = 0; i < distributionCount; ++i){
01712 
01713       lno_t requestedPointCount = lno_t(this->coordinateDistributions[i]->numPoints *  this->loadDistributions[myRank]);
01714       if (gno_t(myRank) < this->coordinateDistributions[i]->numPoints % this->worldSize){
01715         requestedPointCount += 1;
01716       }
01717       //cout << "req:" << requestedPointCount << endl;
01718       //this->coordinateDistributions[i]->GetPoints(requestedPointCount,this->points + this->numLocalCoords, this->holes, this->holeCount,  this->loadDistributions, myRank);
01719       this->coordinateDistributions[i]->GetPoints(requestedPointCount,this->coords, this->numLocalCoords, this->holes, this->holeCount,  this->loadDistributions, myRank);
01720       this->numLocalCoords += requestedPointCount;
01721     }
01722 
01723     /*
01724 
01725     if (this->myRank >= 0){
01726         for(lno_t i = 0; i < this->numLocalCoords; ++i){
01727 
01728           cout <<"me:" << this->myRank << " "<< this->coords[0][i];
01729           if(this->coordinate_dimension > 1){
01730             cout << " " << this->coords[1][i];
01731           }
01732           if(this->coordinate_dimension > 2){
01733             cout  << " " << this->coords[2][i];
01734           }
01735           cout << std::endl;
01736         }
01737     }
01738   */
01739 
01740 
01741 
01742     if (this->predistribution){
01743       redistribute();
01744     }
01745 
01746 
01747 
01748     int scale = 3;
01749     if (this->perturbation_ratio > 0){
01750       this->perturb_data(this->perturbation_ratio, scale);
01751     }
01752     /*
01753     if (this->myRank >= 0){
01754       cout << "after distribution" << endl;
01755         for(lno_t i = 0; i < this->numLocalCoords; ++i){
01756 
01757           cout <<"me:" << this->myRank << " " << this->coords[0][i];
01758           if(this->coordinate_dimension > 1){
01759             cout << " " << this->coords[1][i];
01760           }
01761           if(this->coordinate_dimension > 2){
01762             cout  << " " << this->coords[2][i];
01763           }
01764           cout << std::endl;
01765         }
01766     }
01767 
01768     */
01769 
01770 
01771     if (this->distinctCoordSet){
01772       //TODO: Partition and migration.
01773     }
01774 
01775     if(this->outfile != ""){
01776 
01777       std::ofstream myfile;
01778       myfile.open ((this->outfile + toString<int>(myRank)).c_str());
01779       for(lno_t i = 0; i < this->numLocalCoords; ++i){
01780 
01781         myfile << this->coords[0][i];
01782         if(this->coordinate_dimension > 1){
01783           myfile << " " << this->coords[1][i];
01784         }
01785         if(this->coordinate_dimension > 2){
01786           myfile << " " << this->coords[2][i];
01787         }
01788         myfile << std::endl;
01789       }
01790       myfile.close();
01791 
01792       if (this->myRank == 0){
01793         std::ofstream gnuplotfile("gnu.gnuplot");
01794         for(int i = 0; i < this->worldSize; ++i){
01795           string s = "splot";
01796           if (this->coordinate_dimension == 2){
01797             s = "plot";
01798           }
01799           if (i > 0){
01800             s = "replot";
01801           }
01802           gnuplotfile << s << " \"" << (this->outfile + toString<int>(i)) << "\"" << endl;
01803         }
01804         gnuplotfile  << "pause -1" << endl;
01805         gnuplotfile.close();
01806       }
01807     }
01808 
01809 
01810 
01811     /*
01812     Zoltan2::XpetraMultiVectorAdapter < Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> > xmv (RCP < Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> > (tmVector));
01813 
01814     RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmVector2;
01815     Zoltan2::PartitioningSolution< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> > solution;
01816     xmv.applyPartitioningSolution<Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >(this->tmVector, &tmVector2, solution);
01817      */
01818     if (this->numWeightsPerCoord > 0){
01819       this->wghts = new scalar_t *[this->numWeightsPerCoord];
01820       for(int i = 0; i < this->numWeightsPerCoord; ++i){
01821         this->wghts[i] = new scalar_t[this->numLocalCoords];
01822       }
01823     }
01824 
01825     for(int ii = 0; ii < this->numWeightsPerCoord; ++ii){
01826       switch(this->coordinate_dimension){
01827       case 1:
01828 #ifdef HAVE_ZOLTAN2_OMP
01829 #pragma omp parallel for
01830 #endif
01831         for (lno_t i = 0; i < this->numLocalCoords; ++i){
01832           this->wghts[ii][i] = this->wd[ii]->get1DWeight(this->coords[0][i]);
01833         }
01834         break;
01835       case 2:
01836 #ifdef HAVE_ZOLTAN2_OMP
01837 #pragma omp parallel for
01838 #endif
01839         for (lno_t i = 0; i < this->numLocalCoords; ++i){
01840           this->wghts[ii][i] = this->wd[ii]->get2DWeight(this->coords[0][i], this->coords[1][i]);
01841         }
01842         break;
01843       case 3:
01844 #ifdef HAVE_ZOLTAN2_OMP
01845 #pragma omp parallel for
01846 #endif
01847         for (lno_t i = 0; i < this->numLocalCoords; ++i){
01848           this->wghts[ii][i] = this->wd[ii]->get3DWeight(this->coords[0][i], this->coords[1][i], this->coords[2][i]);
01849         }
01850         break;
01851       }
01852     }
01853   }
01854 
01855   //############################################################//
01857   //############################################################//
01858   void perturb_data(float used_perturbation_ratio, int scale){
01859     scalar_t *maxCoords= new scalar_t [this->coordinate_dimension];
01860     scalar_t *minCoords= new scalar_t [this->coordinate_dimension];
01861     for (int dim = 0; dim < this->coordinate_dimension; ++dim){
01862       minCoords[dim] = maxCoords[dim] = this->coords[dim][0];
01863       for (lno_t i = 1; i < this->numLocalCoords; ++i){
01864         if (minCoords[dim] > this->coords[dim][i]){
01865           minCoords[dim] = this->coords[dim][i];
01866         }
01867 
01868         if (maxCoords[dim] < this->coords[dim][i]){
01869           maxCoords[dim] = this->coords[dim][i];
01870         }
01871       }
01872 
01873 
01874 
01875 
01876       scalar_t center = (maxCoords[dim] + minCoords[dim]) / 2;
01877 
01878       minCoords[dim] = center - (center - minCoords[dim]) * scale;
01879       maxCoords[dim] = (maxCoords[dim] - center) * scale + center;
01880 
01881     }
01882 
01883     gno_t numLocalToPerturb = gno_t(this->numLocalCoords*used_perturbation_ratio);
01884     //cout << "numLocalToPerturb :" << numLocalToPerturb  << endl;
01885     for (int dim = 0; dim < this->coordinate_dimension; ++dim){
01886       scalar_t range = maxCoords[dim] - minCoords[dim];
01887       for (gno_t i = 0; i < numLocalToPerturb; ++i){
01888         this->coords[dim][i] = (rand() / double (RAND_MAX)) * (range) +  minCoords[dim];
01889 
01890       }
01891     }
01892     delete []maxCoords;
01893     delete []minCoords;
01894   }
01895 
01896   //############################################################//
01898   //############################################################//
01899 
01900   //Returns the partitioning dimension as even as possible
01901   void getBestSurface (int remaining, int *dimProcs, int dim, int currentDim, int &bestSurface, int *bestDimProcs){
01902 
01903     if (currentDim < dim - 1){
01904       int ipx = 1;
01905       while(ipx <= remaining) {
01906         if(remaining % ipx == 0) {
01907           int nremain = remaining / ipx;
01908           dimProcs[currentDim] = ipx;
01909           getBestSurface (nremain, dimProcs, dim, currentDim + 1, bestSurface, bestDimProcs);
01910         }
01911         ipx++;
01912       }
01913     }
01914     else {
01915       dimProcs[currentDim] = remaining;
01916       int surface = 0;
01917       for (int i = 0; i < dim; ++i) surface += dimProcs[i];
01918       if (surface < bestSurface){
01919         bestSurface = surface;
01920         for (int i = 0; i < dim; ++i) bestDimProcs[i] = dimProcs[i];
01921       }
01922     }
01923 
01924   }
01925 
01926   //returns min and max coordinates along each dimension
01927   void getMinMaxCoords(scalar_t *globalMaxCoords, scalar_t *globalMinCoords){
01928     scalar_t *maxCoords= new scalar_t [this->coordinate_dimension];
01929     scalar_t *minCoords= new scalar_t [this->coordinate_dimension];
01930     for (int dim = 0; dim < this->coordinate_dimension; ++dim){
01931       minCoords[dim] = maxCoords[dim] = this->coords[dim][0];
01932       for (lno_t i = 1; i < this->numLocalCoords; ++i){
01933         if (minCoords[dim] > this->coords[dim][i]){
01934           minCoords[dim] = this->coords[dim][i];
01935         }
01936 
01937         if (maxCoords[dim] < this->coords[dim][i]){
01938           maxCoords[dim] = this->coords[dim][i];
01939         }
01940       }
01941     }
01942 
01943     reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MAX,
01944                             this->coordinate_dimension,
01945                             maxCoords,
01946                             globalMaxCoords);
01947 
01948 
01949     reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MIN,
01950                                 this->coordinate_dimension,
01951                                 minCoords,
01952                                 globalMinCoords);
01953 
01954     delete []maxCoords;
01955     delete []minCoords;
01956   }
01957 
01958 
01959   //performs a block partitioning.
01960   //then distributes the points of the overloaded parts to underloaded parts.
01961   void blockPartition(int *coordinate_grid_parts){
01962 
01963 #ifdef _MSC_VER
01964     typedef SSIZE_T ssize_t;
01965 #endif
01966 
01967     //############################################################//
01969     //############################################################//
01970 
01971     scalar_t *maxCoords= new scalar_t [this->coordinate_dimension];
01972     scalar_t *minCoords= new scalar_t [this->coordinate_dimension];
01973     //global min and max coordinates in each dimension.
01974     this->getMinMaxCoords(maxCoords, minCoords);
01975 
01976 
01977     //############################################################//
01979     //############################################################//
01980     int remaining = this->worldSize;
01981     int coord_dim = this->coordinate_dimension;
01982     int *dimProcs = new int[coord_dim];
01983     int *bestDimProcs = new int[coord_dim];
01984     int currentDim = 0;
01985 
01986     int bestSurface = 0;
01987     dimProcs[0] = remaining;
01988     for (int i = 1; i < coord_dim; ++i) dimProcs[i] = 1;
01989     for (int i = 0; i < coord_dim; ++i) bestSurface += dimProcs[i];
01990     for (int i = 0; i < coord_dim; ++i) bestDimProcs[i] = dimProcs[i];
01991     //divides the parts into dimensions as even as possible.
01992     getBestSurface ( remaining, dimProcs,  coord_dim,  currentDim, bestSurface, bestDimProcs);
01993 
01994 
01995     delete []dimProcs;
01996 
01997     //############################################################//
01999     //############################################################//
02000     int *shiftProcCount = new int[coord_dim];
02001     //how the consecutive parts along a dimension
02002     //differs in the index.
02003 
02004     int remainingProc = this->worldSize;
02005     for (int dim = 0; dim < coord_dim; ++dim){
02006       remainingProc = remainingProc /  bestDimProcs[dim];
02007       shiftProcCount[dim] = remainingProc;
02008     }
02009 
02010     scalar_t *dim_slices = new scalar_t[coord_dim];
02011     for (int dim = 0; dim < coord_dim; ++dim){
02012       scalar_t dim_range = maxCoords[dim] - minCoords[dim];
02013       scalar_t slice = dim_range / bestDimProcs[dim];
02014       dim_slices[dim] = slice;
02015     }
02016 
02017     //############################################################//
02019     //############################################################//
02020 
02021     gno_t *numPointsInParts = new gno_t[this->worldSize];
02022     gno_t *numGlobalPointsInParts = new gno_t[this->worldSize];
02023     gno_t *numPointsInPartsInclusiveUptoMyIndex = new gno_t[this->worldSize];
02024 
02025     gno_t *partBegins = new gno_t [this->worldSize];
02026     gno_t *partNext = new gno_t[this->numLocalCoords];
02027 
02028 
02029     for (lno_t i = 0; i < this->numLocalCoords; ++i){
02030       partNext[i] = -1;
02031     }
02032     for (int i = 0; i < this->worldSize; ++i) {
02033       partBegins[i] = 1;
02034     }
02035 
02036     for (int i = 0; i < this->worldSize; ++i)
02037       numPointsInParts[i] = 0;
02038 
02039     for (lno_t i = 0; i < this->numLocalCoords; ++i){
02040       int partIndex = 0;
02041       for (int dim = 0; dim < coord_dim; ++dim){
02042         int shift = int ((this->coords[dim][i] - minCoords[dim]) / dim_slices[dim]);
02043         if (shift >= bestDimProcs[dim]){
02044           shift = bestDimProcs[dim] - 1;
02045         }
02046         shift = shift * shiftProcCount[dim];
02047         partIndex += shift;
02048       }
02049       numPointsInParts[partIndex] += 1;
02050       coordinate_grid_parts[i] = partIndex;
02051 
02052       partNext[i] = partBegins[partIndex];
02053       partBegins[partIndex] = i;
02054 
02055     }
02056 
02057     //############################################################//
02059     //############################################################//
02060     reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
02061                                 this->worldSize,
02062                                 numPointsInParts,
02063                                 numGlobalPointsInParts);
02064 
02065 
02066       Teuchos::scan<int,gno_t>(
02067           *(this->comm), Teuchos::REDUCE_SUM,
02068           this->worldSize,
02069           numPointsInParts,
02070           numPointsInPartsInclusiveUptoMyIndex
02071       );
02072 
02073 
02074 
02075 
02076     /*
02077     gno_t totalSize = 0;
02078     for (int i = 0; i < this->worldSize; ++i){
02079       totalSize += numPointsInParts[i];
02080     }
02081     if (totalSize != this->numLocalCoords){
02082       cout << "me:" << this->myRank << " ts:" << totalSize << " nl:" << this->numLocalCoords << endl;
02083     }
02084     */
02085 
02086 
02087       //cout << "me:" << this->myRank << " ilk print" << endl;
02088 
02089     gno_t optimal_num = gno_t(this->numGlobalCoords/double(this->worldSize)+0.5);
02090 #ifdef printparts
02091     if (this->myRank == 0){
02092       gno_t totalSize = 0;
02093       for (int i = 0; i < this->worldSize; ++i){
02094         cout << "me:" << this->myRank << " NumPoints in part:" << i << " is: " << numGlobalPointsInParts[i] << endl;
02095         totalSize += numGlobalPointsInParts[i];
02096       }
02097       cout << "Total:" << totalSize << " ng:" << this->numGlobalCoords << endl;
02098       cout << "optimal_num:" << optimal_num << endl;
02099     }
02100 #endif
02101     ssize_t *extraInPart = new ssize_t [this->worldSize];
02102 
02103     ssize_t extraExchange = 0;
02104     for (int i = 0; i < this->worldSize; ++i){
02105       extraInPart[i] = numGlobalPointsInParts[i] - optimal_num;
02106       extraExchange += extraInPart[i];
02107     }
02108     if (extraExchange != 0){
02109       int addition = -1;
02110       if (extraExchange < 0) addition = 1;
02111       for (ssize_t i = 0; i < extraExchange; ++i){
02112         extraInPart[i % this->worldSize] += addition;
02113       }
02114     }
02115 
02116     //############################################################//
02118     //############################################################//
02119 
02120       int overloadedPartCount = 0;
02121       int *overloadedPartIndices = new int [this->worldSize];
02122 
02123 
02124       int underloadedPartCount = 0;
02125       int *underloadedPartIndices = new int [this->worldSize];
02126 
02127       for (int i = 0; i < this->worldSize; ++i){
02128         if(extraInPart[i] > 0){
02129           overloadedPartIndices[overloadedPartCount++] = i;
02130         }
02131         else if(extraInPart[i] < 0){
02132           underloadedPartIndices[underloadedPartCount++] = i;
02133         }
02134       }
02135 
02136       int underloadpartindex = underloadedPartCount - 1;
02137 
02138 
02139       int numPartsISendFrom = 0;
02140       int *mySendFromParts = new int[this->worldSize * 2];
02141       gno_t *mySendFromPartsCounts = new gno_t[this->worldSize * 2];
02142 
02143       int numPartsISendTo = 0;
02144       int *mySendParts = new int[this->worldSize * 2];
02145       gno_t *mySendCountsToParts = new gno_t[this->worldSize * 2];
02146 
02147 
02148     //############################################################//
02153     //############################################################//
02154       for (int i = overloadedPartCount - 1; i >= 0; --i){
02155         //get the overloaded part
02156         //the overload
02157         int overloadPart = overloadedPartIndices[i];
02158         gno_t overload = extraInPart[overloadPart];
02159         gno_t myload = numPointsInParts[overloadPart];
02160 
02161 
02162         //the inclusive load of the processors up to me
02163         gno_t inclusiveLoadUpToMe = numPointsInPartsInclusiveUptoMyIndex[overloadPart];
02164 
02165         //the exclusive load of the processors up to me
02166         gno_t exclusiveLoadUptoMe = inclusiveLoadUpToMe - myload;
02167 
02168 
02169         if (exclusiveLoadUptoMe >= overload){
02170           //this processor does not have to convert anything.
02171           //for this overloaded part.
02172           //set the extra for this processor to zero.
02173           overloadedPartIndices[i] = -1;
02174           extraInPart[overloadPart] = 0;
02175           //then consume underloaded parts.
02176           while (overload > 0){
02177             int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
02178             ssize_t underload = extraInPart[nextUnderLoadedPart];
02179             ssize_t left = overload + underload;
02180 
02181             if(left >= 0){
02182               extraInPart[nextUnderLoadedPart] = 0;
02183               underloadedPartIndices[underloadpartindex--] = -1;
02184             }
02185             else {
02186               extraInPart[nextUnderLoadedPart] = left;
02187             }
02188             overload = left;
02189           }
02190         }
02191         else if (exclusiveLoadUptoMe < overload){
02192           //if the previous processors load is not enough
02193           //then this processor should convert some of its elements.
02194           gno_t mySendCount = overload - exclusiveLoadUptoMe;
02195           //how much more needed.
02196           gno_t sendAfterMe = 0;
02197           //if my load is not enough
02198           //then the next processor will continue to convert.
02199           if (mySendCount > myload){
02200             sendAfterMe = mySendCount - myload;
02201             mySendCount = myload;
02202           }
02203 
02204 
02205           //this processors will convert from overloaded part
02206           //as many as mySendCount items.
02207           mySendFromParts[numPartsISendFrom] = overloadPart;
02208             mySendFromPartsCounts[numPartsISendFrom++] = mySendCount;
02209 
02210             //first consume underloaded parts for the previous processors.
02211           while (exclusiveLoadUptoMe > 0){
02212             int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
02213             ssize_t underload = extraInPart[nextUnderLoadedPart];
02214             ssize_t left = exclusiveLoadUptoMe + underload;
02215 
02216             if(left >= 0){
02217               extraInPart[nextUnderLoadedPart] = 0;
02218               underloadedPartIndices[underloadpartindex--] = -1;
02219             }
02220             else {
02221               extraInPart[nextUnderLoadedPart] = left;
02222             }
02223             exclusiveLoadUptoMe = left;
02224           }
02225 
02226           //consume underloaded parts for my load.
02227           while (mySendCount > 0){
02228             int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
02229             ssize_t underload = extraInPart[nextUnderLoadedPart];
02230             ssize_t left = mySendCount + underload;
02231 
02232             if(left >= 0){
02233               mySendParts[numPartsISendTo] = nextUnderLoadedPart;
02234               mySendCountsToParts[numPartsISendTo++] = -underload;
02235 
02236               extraInPart[nextUnderLoadedPart] = 0;
02237               underloadedPartIndices[underloadpartindex--] = -1;
02238             }
02239             else {
02240               extraInPart[nextUnderLoadedPart] = left;
02241 
02242               mySendParts[numPartsISendTo] = nextUnderLoadedPart;
02243               mySendCountsToParts[numPartsISendTo++] = mySendCount;
02244 
02245             }
02246             mySendCount = left;
02247           }
02248           //consume underloaded parts for the load of the processors after my index.
02249           while (sendAfterMe > 0){
02250             int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
02251             ssize_t underload = extraInPart[nextUnderLoadedPart];
02252             ssize_t left = sendAfterMe + underload;
02253 
02254             if(left >= 0){
02255               extraInPart[nextUnderLoadedPart] = 0;
02256               underloadedPartIndices[underloadpartindex--] = -1;
02257             }
02258             else {
02259               extraInPart[nextUnderLoadedPart] = left;
02260             }
02261             sendAfterMe = left;
02262           }
02263         }
02264       }
02265 
02266 
02267     //############################################################//
02269     //############################################################//
02270       for (int i = 0 ; i < numPartsISendFrom; ++i){
02271 
02272         //get the part from which the elements will be converted.
02273         int sendFromPart = mySendFromParts[i];
02274         ssize_t sendCount = mySendFromPartsCounts[i];
02275         while(sendCount > 0){
02276           int partToSendIndex = numPartsISendTo - 1;
02277           int partToSend = mySendParts[partToSendIndex];
02278 
02279           int sendCountToThisPart = mySendCountsToParts[partToSendIndex];
02280 
02281           //determine which part i should convert to
02282           //and how many to this part.
02283           if (sendCountToThisPart <= sendCount){
02284             mySendParts[partToSendIndex] = 0;
02285             mySendCountsToParts[partToSendIndex] = 0;
02286             --numPartsISendTo;
02287             sendCount -= sendCountToThisPart;
02288           }
02289           else {
02290             mySendCountsToParts[partToSendIndex] = sendCountToThisPart - sendCount;
02291             sendCountToThisPart = sendCount;
02292             sendCount = 0;
02293           }
02294 
02295 
02296             gno_t toChange = partBegins[sendFromPart];
02297           gno_t previous_begin = partBegins[partToSend];
02298 
02299           //do the conversion.
02300           for (int k = 0; k < sendCountToThisPart - 1; ++k){
02301             coordinate_grid_parts[toChange] = partToSend;
02302             toChange = partNext[toChange];
02303           }
02304           coordinate_grid_parts[toChange] = partToSend;
02305 
02306           gno_t newBegin = partNext[toChange];
02307           partNext[toChange] = previous_begin;
02308           partBegins[partToSend] = partBegins[sendFromPart];
02309           partBegins[sendFromPart] = newBegin;
02310         }
02311       }
02312 
02313       //if (this->myRank == 0) cout << "4" << endl;
02314 
02315 #ifdef printparts
02316 
02317 
02318       for (int i = 0; i < this->worldSize; ++i) numPointsInParts[i] = 0;
02319 
02320       for (int i = 0; i < this->numLocalCoords; ++i){
02321         numPointsInParts[coordinate_grid_parts[i]] += 1;
02322       }
02323 
02324     reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
02325                                 this->worldSize,
02326                                 numPointsInParts,
02327                                 numGlobalPointsInParts);
02328     if (this->myRank == 0){
02329       cout << "reassigning" << endl;
02330       gno_t totalSize = 0;
02331       for (int i = 0; i < this->worldSize; ++i){
02332         cout << "me:" << this->myRank << " NumPoints in part:" << i << " is: " << numGlobalPointsInParts[i] << endl;
02333         totalSize += numGlobalPointsInParts[i];
02334       }
02335       cout << "Total:" << totalSize << " ng:" << this->numGlobalCoords << endl;
02336     }
02337 #endif
02338     delete []mySendCountsToParts;
02339     delete []mySendParts;
02340     delete []mySendFromPartsCounts;
02341     delete []mySendFromParts;
02342     delete []underloadedPartIndices;
02343     delete []overloadedPartIndices;
02344     delete []extraInPart;
02345     delete []partNext;
02346     delete []partBegins;
02347     delete []numPointsInPartsInclusiveUptoMyIndex;
02348     delete []numPointsInParts;
02349     delete []numGlobalPointsInParts;
02350 
02351     delete []shiftProcCount;
02352     delete []bestDimProcs;
02353     delete []dim_slices;
02354       delete []minCoords;
02355       delete []maxCoords;
02356   }
02357 
02358   //given the part numbers for each local coordinate,
02359   //distributes the coordinates to the corresponding processors.
02360   void distribute_points(int *coordinate_grid_parts){
02361 
02362     Tpetra::Distributor distributor(comm);
02363     ArrayView<const int> pIds( coordinate_grid_parts, this->numLocalCoords);
02364     /*
02365     for (int i = 0 ; i < this->numLocalCoords; ++i){
02366       cout << "me:" << this->myRank << " to part:" << coordinate_grid_parts[i] << endl;
02367     }
02368     */
02369     gno_t numMyNewGnos = distributor.createFromSends(pIds);
02370 
02371     //cout << "distribution step 1 me:" << this->myRank << " numLocal:"  <<numMyNewGnos << " old:" <<  numLocalCoords << endl;
02372 
02373     this->numLocalCoords = numMyNewGnos;
02374 
02375 
02376     ArrayRCP<scalar_t> recvBuf2(distributor.getTotalReceiveLength());
02377 
02378     for (int i = 0; i < this->coordinate_dimension; ++i){
02379       ArrayView<scalar_t> s(this->coords[i], this->numLocalCoords);
02380         distributor.doPostsAndWaits<scalar_t>(s, 1, recvBuf2());
02381       delete [] this->coords[i];
02382       this->coords[i] = new scalar_t[this->numLocalCoords];
02383         for (lno_t j = 0; j < this->numLocalCoords; ++j){
02384           this->coords[i][j] = recvBuf2[j];
02385         }
02386 
02387     }
02388   }
02389 
02390   //calls MJ for p = numProcs
02391   int predistributeMJ(int *coordinate_grid_parts){
02392     int coord_dim = this->coordinate_dimension;
02393 
02394     lno_t numLocalPoints = this->numLocalCoords;
02395     gno_t numGlobalPoints = this->numGlobalCoords;
02396 
02397 
02398     //T **weight = NULL;
02399     //typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> tMVector_t;
02400     RCP<Tpetra::Map<lno_t, gno_t, node_t> > mp = rcp(
02401         new Tpetra::Map<lno_t, gno_t, node_t> (numGlobalPoints, numLocalPoints, 0, comm));
02402 
02403     Teuchos::Array<Teuchos::ArrayView<const scalar_t> > coordView(coord_dim);
02404 
02405 
02406 
02407     for (int i=0; i < coord_dim; i++){
02408       if(numLocalPoints > 0){
02409         Teuchos::ArrayView<const scalar_t> a(coords[i], numLocalPoints);
02410         coordView[i] = a;
02411       } else{
02412         Teuchos::ArrayView<const scalar_t> a;
02413         coordView[i] = a;
02414       }
02415     }
02416 
02417     RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmVector = RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >(
02418         new Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t>( mp, coordView.view(0, coord_dim), coord_dim));
02419 
02420 
02421     RCP<const tMVector_t> coordsConst = Teuchos::rcp_const_cast<const tMVector_t>(tmVector);
02422     vector<const scalar_t *> weights;
02423     vector <int> stride;
02424 
02425     typedef Zoltan2::XpetraMultiVectorAdapter<tMVector_t> inputAdapter_t;
02426     //inputAdapter_t ia(coordsConst);
02427     inputAdapter_t ia(coordsConst,weights, stride);
02428 
02429     Teuchos::RCP <Teuchos::ParameterList> params ;
02430     params =RCP <Teuchos::ParameterList> (new Teuchos::ParameterList, true);
02431 
02432 
02433     params->set("algorithm", "multijagged");
02434     params->set("num_global_parts", this->worldSize);
02435 
02436     //TODO we need to fix the setting parts.
02437     //Although MJ sets the parts with
02438     //currently the part setting is not correct when migration is done.
02439     params->set("migration_check_option", 2);
02440 
02441 
02442     Zoltan2::PartitioningProblem<inputAdapter_t> *problem;
02443 
02444 
02445     try {
02446 #ifdef HAVE_ZOLTAN2_MPI
02447       problem = new Zoltan2::PartitioningProblem<inputAdapter_t>(&ia, params.getRawPtr(),
02448           MPI_COMM_WORLD);
02449 #else
02450       problem = new Zoltan2::PartitioningProblem<inputAdapter_t>(&ia, params.getRawPtr());
02451 #endif
02452     }
02453     CATCH_EXCEPTIONS("PartitioningProblem()")
02454 
02455     try {
02456       problem->solve();
02457     }
02458     CATCH_EXCEPTIONS("solve()")
02459 
02460     const typename inputAdapter_t::part_t *partIds = problem->getSolution().getPartList();
02461 
02462     for (lno_t i = 0; i < this->numLocalCoords;++i){
02463       coordinate_grid_parts[i] = partIds[i];
02464       //cout << "me:" << this->myRank << " i:" << i << " goes to:" << partIds[i] << endl;
02465     }
02466     delete problem;
02467     return 0;
02468   }
02469 
02470 #ifdef HAVE_ZOLTAN2_ZOLTAN
02471   //calls RCP for p = numProcs
02472   int predistributeRCB(int *coordinate_grid_parts){
02473     int rank = this->myRank;
02474     int nprocs = this->worldSize;
02475     DOTS<tMVector_t> dots_;
02476 
02477     MEMORY_CHECK(rank==0 || rank==nprocs-1, "After initializing MPI");
02478 
02479 
02480     int nWeights = 0;
02481     int debugLevel=0;
02482     string memoryOn("memoryOn");
02483     string memoryOff("memoryOff");
02484     bool doMemory=false;
02485     int numGlobalParts = nprocs;
02486     int dummyTimer=0;
02487     bool remap=0;
02488 
02489     string balanceCount("balance_object_count");
02490     string balanceWeight("balance_object_weight");
02491     string mcnorm1("multicriteria_minimize_total_weight");
02492     string mcnorm2("multicriteria_balance_total_maximum");
02493     string mcnorm3("multicriteria_minimize_maximum_weight");
02494     string objective(balanceWeight);   // default
02495 
02496     // Process command line input
02497     CommandLineProcessor commandLine(false, true);
02498     //commandLine.setOption("size", &numGlobalCoords,
02499     //  "Approximate number of global coordinates.");
02500     int input_option = 0;
02501     commandLine.setOption("input_option", &input_option,
02502       "whether to use mesh creation, geometric generator, or file input");
02503     string inputFile = "";
02504 
02505     commandLine.setOption("input_file", &inputFile,
02506       "the input file for geometric generator or file input");
02507 
02508 
02509     commandLine.setOption("size", &numGlobalCoords,
02510       "Approximate number of global coordinates.");
02511     commandLine.setOption("numParts", &numGlobalParts,
02512       "Number of parts (default is one per proc).");
02513     commandLine.setOption("nWeights", &nWeights,
02514       "Number of weights per coordinate, zero implies uniform weights.");
02515     commandLine.setOption("debug", &debugLevel, "Zoltan1 debug level");
02516     commandLine.setOption("remap", "no-remap", &remap,
02517       "Zoltan1 REMAP parameter; disabled by default for scalability testing");
02518     commandLine.setOption("timers", &dummyTimer, "ignored");
02519     commandLine.setOption(memoryOn.c_str(), memoryOff.c_str(), &doMemory,
02520       "do memory profiling");
02521 
02522     string doc(balanceCount);
02523     doc.append(": ignore weights\n");
02524     doc.append(balanceWeight);
02525     doc.append(": balance on first weight\n");
02526     doc.append(mcnorm1);
02527     doc.append(": given multiple weights, balance their total.\n");
02528     doc.append(mcnorm3);
02529     doc.append(": given multiple weights, "
02530                "balance the maximum for each coordinate.\n");
02531     doc.append(mcnorm2);
02532     doc.append(": given multiple weights, balance the L2 norm of the weights.\n");
02533     commandLine.setOption("objective", &objective,  doc.c_str());
02534 
02535     CommandLineProcessor::EParseCommandLineReturn rc =
02536       commandLine.parse(0, NULL);
02537 
02538 
02539 
02540     if (rc != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
02541       if (rc == Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED) {
02542         if (rank==0) cout << "PASS" << endl;
02543         return 1;
02544       }
02545       else {
02546         if (rank==0) cout << "FAIL" << endl;
02547         return 0;
02548       }
02549     }
02550 
02551     //MEMORY_CHECK(doMemory && rank==0, "After processing parameters");
02552 
02553     // Create the data structure
02554 
02555     int coord_dim = this->coordinate_dimension;
02556 
02557 
02558     RCP<Tpetra::Map<lno_t, gno_t, node_t> > mp = rcp(
02559         new Tpetra::Map<lno_t, gno_t, node_t> (this->numGlobalCoords, this->numLocalCoords, 0, this->comm));
02560 
02561     Teuchos::Array<Teuchos::ArrayView<const scalar_t> > coordView(coord_dim);
02562     for (int i=0; i < coord_dim; i++){
02563       if(numLocalCoords > 0){
02564         Teuchos::ArrayView<const scalar_t> a(coords[i], numLocalCoords);
02565         coordView[i] = a;
02566       } else{
02567         Teuchos::ArrayView<const scalar_t> a;
02568         coordView[i] = a;
02569       }
02570     }
02571 
02572     tMVector_t *tmVector = new tMVector_t( mp, coordView.view(0, coord_dim), coord_dim);
02573 
02574     dots_.coordinates = tmVector;
02575     dots_.weights.resize(nWeights);
02576 
02577 
02578     MEMORY_CHECK(doMemory && rank==0, "After creating input");
02579 
02580     // Now call Zoltan to partition the problem.
02581 
02582     float ver;
02583     int aok = Zoltan_Initialize(0,NULL, &ver);
02584 
02585     if (aok != 0){
02586       printf("Zoltan_Initialize failed\n");
02587       exit(0);
02588     }
02589 
02590     struct Zoltan_Struct *zz;
02591     zz = Zoltan_Create(MPI_COMM_WORLD);
02592 
02593     Zoltan_Set_Param(zz, "LB_METHOD", "RCB");
02594     Zoltan_Set_Param(zz, "LB_APPROACH", "PARTITION");
02595     Zoltan_Set_Param(zz, "CHECK_GEOM", "0");
02596     Zoltan_Set_Param(zz, "NUM_GID_ENTRIES", "1");
02597     Zoltan_Set_Param(zz, "NUM_LID_ENTRIES", "0");
02598     Zoltan_Set_Param(zz, "RETURN_LISTS", "PART");
02599     std::ostringstream oss;
02600     oss << numGlobalParts;
02601     Zoltan_Set_Param(zz, "NUM_GLOBAL_PARTS", oss.str().c_str());
02602     oss.str("");
02603     oss << debugLevel;
02604     Zoltan_Set_Param(zz, "DEBUG_LEVEL", oss.str().c_str());
02605 
02606     if (remap)
02607       Zoltan_Set_Param(zz, "REMAP", "1");
02608     else
02609       Zoltan_Set_Param(zz, "REMAP", "0");
02610 
02611     if (objective != balanceCount){
02612       oss.str("");
02613       oss << nWeights;
02614       Zoltan_Set_Param(zz, "OBJ_WEIGHT_DIM", oss.str().c_str());
02615 
02616       if (objective == mcnorm1)
02617         Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "1");
02618       else if (objective == mcnorm2)
02619         Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "2");
02620       else if (objective == mcnorm3)
02621         Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "3");
02622     }
02623     else{
02624       Zoltan_Set_Param(zz, "OBJ_WEIGHT_DIM", "0");
02625     }
02626 
02627     Zoltan_Set_Num_Obj_Fn(zz, getNumObj<tMVector_t>, &dots_);
02628     Zoltan_Set_Obj_List_Fn(zz, getObjList<tMVector_t>, &dots_);
02629     Zoltan_Set_Num_Geom_Fn(zz,  getDim<tMVector_t>, &dots_);
02630     Zoltan_Set_Geom_Multi_Fn(zz, getCoords<tMVector_t>, &dots_);
02631 
02632     int changes, numGidEntries, numLidEntries, numImport, numExport;
02633     ZOLTAN_ID_PTR importGlobalGids, importLocalGids;
02634     ZOLTAN_ID_PTR exportGlobalGids, exportLocalGids;
02635     int *importProcs, *importToPart, *exportProcs, *exportToPart;
02636 
02637     MEMORY_CHECK(doMemory && rank==0, "Before Zoltan_LB_Partition");
02638 
02639 
02640     aok = Zoltan_LB_Partition(zz, &changes, &numGidEntries, &numLidEntries,
02641                               &numImport, &importGlobalGids, &importLocalGids,
02642                               &importProcs, &importToPart,
02643                               &numExport, &exportGlobalGids, &exportLocalGids,
02644                               &exportProcs, &exportToPart);
02645 
02646 
02647     MEMORY_CHECK(doMemory && rank==0, "After Zoltan_LB_Partition");
02648 
02649     for (lno_t i = 0; i < numLocalCoords; i++)
02650       coordinate_grid_parts[i] = exportToPart[i];
02651     Zoltan_Destroy(&zz);
02652     MEMORY_CHECK(doMemory && rank==0, "After Zoltan_Destroy");
02653 
02654     delete dots_.coordinates;
02655     return 0;
02656 }
02657 #endif
02658   void redistribute(){
02659     int *coordinate_grid_parts = new int[this->numLocalCoords];
02660     switch (this->predistribution){
02661     case 1:
02662 #ifdef HAVE_ZOLTAN2_ZOLTAN
02663       this->predistributeRCB(coordinate_grid_parts);
02664       break;
02665 #endif
02666     case 2:
02667 
02668       this->predistributeMJ(coordinate_grid_parts);
02669       break;
02670     case 3:
02671       //block
02672       blockPartition(coordinate_grid_parts);
02673       break;
02674     }
02675     this->distribute_points(coordinate_grid_parts);
02676 
02677     delete []coordinate_grid_parts;
02678 
02679 
02680   }
02681 
02682   //############################################################//
02684   //############################################################//
02685 
02686 
02687   int getNumWeights(){
02688     return this->numWeightsPerCoord;
02689   }
02690   int getCoordinateDimension(){
02691     return this->coordinate_dimension;
02692   }
02693   lno_t getNumLocalCoords(){
02694     return this->numLocalCoords;
02695   }
02696   gno_t getNumGlobalCoords(){
02697     return this->numGlobalCoords;
02698   }
02699 
02700   scalar_t **getLocalCoordinatesView(){
02701     return this->coords;
02702   }
02703 
02704   scalar_t **getLocalWeightsView(){
02705     return this->wghts;
02706   }
02707 
02708   void getLocalCoordinatesCopy( scalar_t ** c){
02709     for(int ii = 0; ii < this->coordinate_dimension; ++ii){
02710 #ifdef HAVE_ZOLTAN2_OMP
02711 #pragma omp parallel for
02712 #endif
02713       for (lno_t i = 0; i < this->numLocalCoords; ++i){
02714         c[ii][i] = this->coords[ii][i];
02715       }
02716     }
02717   }
02718 
02719   void getLocalWeightsCopy(scalar_t **w){
02720     for(int ii = 0; ii < this->numWeightsPerCoord; ++ii){
02721 #ifdef HAVE_ZOLTAN2_OMP
02722 #pragma omp parallel for
02723 #endif
02724       for (lno_t i = 0; i < this->numLocalCoords; ++i){
02725         w[ii][i] = this->wghts[ii][i];
02726       }
02727     }
02728   }
02729 };
02730 }