|
Zoltan2
|
00001 // @HEADER 00002 // 00003 // *********************************************************************** 00004 // 00005 // Zoltan2: A package of combinatorial algorithms for scientific computing 00006 // Copyright 2012 Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Karen Devine (kddevin@sandia.gov) 00039 // Erik Boman (egboman@sandia.gov) 00040 // Siva Rajamanickam (srajama@sandia.gov) 00041 // 00042 // *********************************************************************** 00043 // 00044 // @HEADER 00045 #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 ¶mname){ 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 ¶mName = 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 ¶ms, 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 }
1.7.6.1