Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
GeometricGenerator.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef GEOMETRICGENERATOR
11 #define GEOMETRICGENERATOR
12 
13 #include <Teuchos_Comm.hpp>
14 #include <Teuchos_ParameterList.hpp>
15 #include <Teuchos_FilteredIterator.hpp>
16 #include <Teuchos_ParameterEntry.hpp>
17 #include <iostream>
18 #include <ctime>
19 #include <limits>
20 #include <climits>
21 #include <string>
22 #include <cstdlib>
23 #include <sstream>
24 #include <fstream>
25 #include <Tpetra_MultiVector_decl.hpp>
28 #include <Teuchos_ArrayViewDecl.hpp>
29 #include <Teuchos_RCP.hpp>
30 #include <Tpetra_Distributor.hpp>
32 
33 
34 #include <zoltan.h>
35 
36 #ifdef _MSC_VER
37 #define NOMINMAX
38 #include <windows.h>
39 #endif
40 
41 using Teuchos::CommandLineProcessor;
42 using Teuchos::ArrayView;
43 using std::string;
44 using Teuchos::ArrayRCP;
45 
46 namespace GeometricGen{
47 #define CATCH_EXCEPTIONS(pp) \
48  catch (std::runtime_error &e) { \
49  std::cout << "Runtime exception returned from " << pp << ": " \
50  << e.what() << " FAIL" << std::endl; \
51  return -1; \
52  } \
53  catch (std::logic_error &e) { \
54  std::cout << "Logic exception returned from " << pp << ": " \
55  << e.what() << " FAIL" << std::endl; \
56  return -1; \
57  } \
58  catch (std::bad_alloc &e) { \
59  std::cout << "Bad_alloc exception returned from " << pp << ": " \
60  << e.what() << " FAIL" << std::endl; \
61  return -1; \
62  } \
63  catch (std::exception &e) { \
64  std::cout << "Unknown exception returned from " << pp << ": " \
65  << e.what() << " FAIL" << std::endl; \
66  return -1; \
67  }
68 
69 
70 
71 
72 template <typename tMVector_t>
73 class DOTS{
74 public:
75  std::vector<std::vector<float> > weights;
77 };
78 
79 template <typename tMVector_t>
80 int getNumObj(void *data, int *ierr)
81 {
82  *ierr = 0;
83  DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
84  return dots_->coordinates->getLocalLength();
85 }
87 template <typename tMVector_t>
88 void getCoords(void *data, int numGid, int numLid,
89  int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
90  int dim, double *coords_, int *ierr)
91 {
92  typedef typename tMVector_t::scalar_type scalar_t;
93 
94  // I know that Zoltan asks for coordinates in gid order.
95  if (dim == 3){
96  *ierr = 0;
97  DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
98  double *val = coords_;
99  const scalar_t *x = dots_->coordinates->getData(0).getRawPtr();
100  const scalar_t *y = dots_->coordinates->getData(1).getRawPtr();
101  const scalar_t *z = dots_->coordinates->getData(2).getRawPtr();
102  for (int i=0; i < numObj; i++){
103  *val++ = static_cast<double>(x[i]);
104  *val++ = static_cast<double>(y[i]);
105  *val++ = static_cast<double>(z[i]);
106  }
107  }
108  else {
109  *ierr = 0;
110  DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
111  double *val = coords_;
112  const scalar_t *x = dots_->coordinates->getData(0).getRawPtr();
113  const scalar_t *y = dots_->coordinates->getData(1).getRawPtr();
114  for (int i=0; i < numObj; i++){
115  *val++ = static_cast<double>(x[i]);
116  *val++ = static_cast<double>(y[i]);
117  }
118  }
119 }
120 
121 template <typename tMVector_t>
122 int getDim(void *data, int *ierr)
123 {
124  *ierr = 0;
125  DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
126  int dim = dots_->coordinates->getNumVectors();
127 
128  return dim;
129 }
130 
132 template <typename tMVector_t>
133 void getObjList(void *data, int numGid, int numLid,
134  ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
135  int num_wgts, float *obj_wgts, int *ierr)
136 {
137  typedef typename tMVector_t::global_ordinal_type gno_t;
138 
139  *ierr = 0;
140  DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
141 
142  size_t localLen = dots_->coordinates->getLocalLength();
143  const gno_t *ids =
144  dots_->coordinates->getMap()->getLocalElementList().getRawPtr();
145 
146  if (sizeof(ZOLTAN_ID_TYPE) == sizeof(gno_t))
147  memcpy(gids, ids, sizeof(ZOLTAN_ID_TYPE) * localLen);
148  else
149  for (size_t i=0; i < localLen; i++)
150  gids[i] = static_cast<ZOLTAN_ID_TYPE>(ids[i]);
151 
152  if (num_wgts > 0){
153  float *wgts = obj_wgts;
154  for (size_t i=0; i < localLen; i++)
155  for (int w=0; w < num_wgts; w++)
156  *wgts++ = dots_->weights[w][i];
157  }
158 }
159 
160 
162 const std::string shapes[] = {"SQUARE", "RECTANGLE", "CIRCLE", "CUBE", "RECTANGULAR_PRISM", "SPHERE"};
163 #define SHAPE_COUNT 6
164 
166 const std::string distribution[] = {"distribution", "uniform"};
167 #define DISTRIBUTION_COUNT 2
168 
169 #define HOLE_ALLOC_STEP 10
170 #define MAX_WEIGHT_DIM 10
171 #define INVALID(STR) "Invalid argument at " + STR
172 #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"
173 
174 #define INVALID_SHAPE_ARG(SHAPE, REQUIRED) "Invalid argument count for shape " + SHAPE + ". Requires " + REQUIRED + " argument(s)."
175 #define MAX_ITER_ALLOWED 500
176 
177 const std::string weight_distribution_string = "WeightDistribution-";
178 
179 template <typename T>
181  T x;
182  T y;
183  T z;
184  /*
185  bool isInArea(int dim, T *minCoords, T *maxCoords){
186  dim = min(3, dim);
187  for (int i = 0; i < dim; ++i){
188  bool maybe = true;
189  switch(i){
190  case 0:
191  maybe = x < maxCoords[i] && x > maxCoords[i];
192  break;
193  case 1:
194  maybe = y < maxCoords[i] && y > maxCoords[i];
195  break;
196  case 2:
197  maybe = z < maxCoords[i] && z > maxCoords[i];
198  break;
199  }
200  if (!maybe){
201  return false;
202  }
203  }
204  return true;
205  }
206  */
208  x = 0;y=0;z=0;
209  }
210 };
211 
212 template <typename T>
213 class Hole{
214 public:
217  Hole(CoordinatePoint<T> center_, T edge1_, T edge2_, T edge3_){
218  this->center.x = center_.x;
219  this->center.y = center_.y;
220  this->center.z = center_.z;
221  this->edge1 = edge1_;
222  this->edge2 = edge2_;
223  this->edge3 = edge3_;
224  }
225  virtual bool isInArea(CoordinatePoint<T> dot) = 0;
226  virtual ~Hole(){}
227 };
228 
229 template <typename T>
230 class SquareHole:public Hole<T>{
231 public:
232  SquareHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
233  virtual ~SquareHole(){}
234  virtual bool isInArea(CoordinatePoint<T> dot){
235  return fabs(dot.x - this->center.x) < this->edge1 / 2 && fabs(dot.y - this->center.y) < this->edge1 / 2;
236  }
237 };
238 
239 template <typename T>
240 class RectangleHole:public Hole<T>{
241 public:
242  RectangleHole(CoordinatePoint<T> center_ , T edge_x_, T edge_y_): Hole<T>(center_, edge_x_, edge_y_, 0){}
243  virtual bool isInArea(CoordinatePoint<T> dot){
244  return fabs(dot.x - this->center.x) < this->edge1 / 2 && fabs(dot.y - this->center.y) < this->edge2 / 2;
245  }
246  virtual ~RectangleHole(){}
247 };
248 
249 template <typename T>
250 class CircleHole:public Hole<T>{
251 public:
252  CircleHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
253  virtual ~CircleHole(){}
254  virtual bool isInArea(CoordinatePoint<T> dot){
255  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;
256  }
257 };
258 
259 template <typename T>
260 class CubeHole:public Hole<T>{
261 public:
262  CubeHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
263  virtual ~CubeHole(){}
264  virtual bool isInArea(CoordinatePoint<T> dot){
265  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;
266  }
267 };
268 
269 template <typename T>
270 class RectangularPrismHole:public Hole<T>{
271 public:
272  RectangularPrismHole(CoordinatePoint<T> center_ , T edge_x_, T edge_y_, T edge_z_): Hole<T>(center_, edge_x_, edge_y_, edge_z_){}
274  virtual bool isInArea(CoordinatePoint<T> dot){
275  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;
276  }
277 };
278 
279 template <typename T>
280 class SphereHole:public Hole<T>{
281 public:
282  SphereHole(CoordinatePoint<T> center_ , T edge_): Hole<T>(center_, edge_, 0 , 0){}
283  virtual ~SphereHole(){}
284  virtual bool isInArea(CoordinatePoint<T> dot){
285  return fabs((dot.x - this->center.x) * (dot.x - this->center.x) * (dot.x - this->center.x)) +
286  fabs((dot.y - this->center.y) * (dot.y - this->center.y) * (dot.y - this->center.y)) +
287  fabs((dot.z - this->center.z) * (dot.z - this->center.z) * (dot.z - this->center.z))
288  <
289  this->edge1 * this->edge1 * this->edge1;
290  }
291 };
292 
293 template <typename T, typename weighttype>
295 public:
296  virtual weighttype getWeight(CoordinatePoint<T> P)=0;
297  virtual weighttype get1DWeight(T x)=0;
298  virtual weighttype get2DWeight(T x, T y)=0;
299  virtual weighttype get3DWeight(T x, T y, T z)=0;
301  virtual ~WeightDistribution(){};
302 };
303 
322 template <typename T, typename weighttype>
323 class SteppedEquation:public WeightDistribution<T, weighttype>{
324  T a1,a2,a3;
325  T b1,b2,b3;
326  T c;
327  T x1,y1,z1;
328 
329  T *steps;
330  weighttype *values;
331  int stepCount;
332 public:
333  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>(){
334  this->a1 = a1_;
335  this->a2 = a2_;
336  this->a3 = a3_;
337  this->b1 = b1_;
338  this->b2 = b2_;
339  this->b3 = b3_;
340  this->c = c_;
341  this->x1 = x1_;
342  this->y1 = y1_;
343  this->z1 = z1_;
344 
345 
346  this->stepCount = stepCount_;
347  if(this->stepCount > 0){
348  this->steps = new T[this->stepCount];
349  this->values = new T[this->stepCount + 1];
350 
351  for (int i = 0; i < this->stepCount; ++i){
352  this->steps[i] = steps_[i];
353  this->values[i] = values_[i];
354  }
355  this->values[this->stepCount] = values_[this->stepCount];
356  }
357 
358  }
359 
360  virtual ~SteppedEquation(){
361  if(this->stepCount > 0){
362  delete [] this->steps;
363  delete [] this->values;
364  }
365  }
366 
367 
368  virtual weighttype get1DWeight(T x){
369  T expressionRes = this->a1 * pow( (x - this->x1), b1) + c;
370  if(this->stepCount > 0){
371  for (int i = 0; i < this->stepCount; ++i){
372  if (expressionRes < this->steps[i]) return this->values[i];
373  }
374  return this->values[this->stepCount];
375  }
376  else {
377  return weighttype(expressionRes);
378  }
379  }
380 
381  virtual weighttype get2DWeight(T x, T y){
382  T expressionRes = this->a1 * pow( (x - this->x1), b1) + this->a2 * pow( (y - this->y1), b2) + c;
383  if(this->stepCount > 0){
384  for (int i = 0; i < this->stepCount; ++i){
385  if (expressionRes < this->steps[i]) return this->values[i];
386  }
387  return this->values[this->stepCount];
388  }
389  else {
390  return weighttype(expressionRes);
391  }
392  }
393 
394  void print (T x, T y, T z){
395  std::cout << this->a1 << "*" << "math.pow( (" << x << "- " << this->x1 << " ), " << b1 <<")" << "+" << this->a2<< "*"<< "math.pow( (" << y << "-" << this->y1 << "), " <<
396  b2 << " ) + " << this->a3 << " * math.pow( (" << z << "-" << this->z1 << "), " << b3 << ")+ " << c << " == " <<
397  this->a1 * pow( (x - this->x1), b1) + this->a2 * pow( (y - this->y1), b2) + this->a3 * pow( (z - this->z1), b3) + c << std::endl;
398 
399  }
400 
401  virtual weighttype get3DWeight(T x, T y, T z){
402  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;
403 
404  //this->print(x,y,z);
405  if(this->stepCount > 0){
406  for (int i = 0; i < this->stepCount; ++i){
407  if (expressionRes < this->steps[i]) {
408  //std::cout << "0exp:" << expressionRes << " step:" << steps[i] << " value:" << values[i] << std::endl;
409  return this->values[i];
410  }
411  }
412 
413  //std::cout << "1exp:" << expressionRes << " step:" << steps[stepCount] << " value:" << values[stepCount] << std::endl;
414  return this->values[this->stepCount];
415  }
416  else {
417  return weighttype(expressionRes);
418  }
419  }
420 
421  virtual weighttype getWeight(CoordinatePoint<T> p){
422  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);
423  if(this->stepCount > 0){
424  for (int i = 0; i < this->stepCount; ++i){
425  if (expressionRes < this->steps[i]) return this->values[i];
426  }
427  return this->values[this->stepCount];
428  }
429  else {
430  return weighttype(expressionRes);
431  }
432  }
433 };
434 
435 template <typename T, typename lno_t, typename gno_t>
437 public:
444 
445  CoordinateDistribution(gno_t np_, int dim, int wSize) :
446  numPoints(np_), dimension(dim), requested(0), assignedPrevious(0),
447  worldSize(wSize){}
448 
449  virtual CoordinatePoint<T> getPoint(gno_t point_index, unsigned int &state) = 0;
450  virtual T getXCenter() = 0;
451  virtual T getXRadius() =0;
452 
453  void GetPoints(lno_t requestedPointcount, CoordinatePoint<T> *points /*preallocated sized numPoints*/,
454  Hole<T> **holes, lno_t holeCount,
455  float *sharedRatios_, int myRank){
456 
457  for (int i = 0; i < myRank; ++i){
458  //std::cout << "me:" << myRank << " i:" << i << " s:" << sharedRatios_[i]<< std::endl;
459  this->assignedPrevious += lno_t(sharedRatios_[i] * this->numPoints);
460  if (i < this->numPoints % this->worldSize){
461  this->assignedPrevious += 1;
462  }
463  }
464 
465  this->requested = requestedPointcount;
466 
467  unsigned int slice = UINT_MAX/(this->worldSize);
468  unsigned int stateBegin = myRank * slice;
469 
470 //#ifdef HAVE_ZOLTAN2_OMP
471 //#pragma omp parallel for
472 //#endif
473 #ifdef HAVE_ZOLTAN2_OMP
474 #pragma omp parallel
475 #endif
476  {
477  int me = 0;
478  int tsize = 1;
479 #ifdef HAVE_ZOLTAN2_OMP
480  me = omp_get_thread_num();
481  tsize = omp_get_num_threads();
482 #endif
483  unsigned int state = stateBegin + me * slice/(tsize);
484 
485 #ifdef HAVE_ZOLTAN2_OMP
486 #pragma omp for
487 #endif
488  for(lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
489  lno_t iteration = 0;
490  while(1){
491  if(++iteration > MAX_ITER_ALLOWED) {
492  throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
493  }
494  CoordinatePoint <T> p = this->getPoint( this->assignedPrevious + cnt, state);
495 
496  bool isInHole = false;
497  for(lno_t i = 0; i < holeCount; ++i){
498  if(holes[i][0].isInArea(p)){
499  isInHole = true;
500  break;
501  }
502  }
503  if(isInHole) continue;
504  points[cnt].x = p.x;
505 
506  points[cnt].y = p.y;
507  points[cnt].z = p.z;
508  break;
509  }
510  }
511  }
512 //#pragma omp parallel
513  /*
514  {
515 
516  lno_t cnt = 0;
517  lno_t iteration = 0;
518  while (cnt < requestedPointcount){
519  if(++iteration > MAX_ITER_ALLOWED) {
520  throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
521  }
522  CoordinatePoint <T> p = this->getPoint();
523 
524  bool isInHole = false;
525  for(lno_t i = 0; i < holeCount; ++i){
526  if(holes[i][0].isInArea(p)){
527  isInHole = true;
528  break;
529  }
530  }
531  if(isInHole) continue;
532  iteration = 0;
533  points[cnt].x = p.x;
534  points[cnt].y = p.y;
535  points[cnt].z = p.z;
536  ++cnt;
537  }
538  }
539  */
540  }
541 
542  void GetPoints(lno_t requestedPointcount, T **coords/*preallocated sized numPoints*/, lno_t tindex,
543  Hole<T> **holes, lno_t holeCount,
544  float *sharedRatios_, int myRank){
545 
546  for (int i = 0; i < myRank; ++i){
547  //std::cout << "me:" << myRank << " i:" << i << " s:" << sharedRatios_[i]<< std::endl;
548  this->assignedPrevious += lno_t(sharedRatios_[i] * this->numPoints);
549  if (gno_t(i) < this->numPoints % this->worldSize){
550  this->assignedPrevious += 1;
551  }
552  }
553 
554  this->requested = requestedPointcount;
555 
556  unsigned int slice = UINT_MAX/(this->worldSize);
557  unsigned int stateBegin = myRank * slice;
558 #ifdef HAVE_ZOLTAN2_OMP
559 #pragma omp parallel
560 #endif
561  {
562  int me = 0;
563  int tsize = 1;
564 #ifdef HAVE_ZOLTAN2_OMP
565  me = omp_get_thread_num();
566  tsize = omp_get_num_threads();
567 #endif
568  unsigned int state = stateBegin + me * (slice/(tsize));
569  /*
570 #pragma omp critical
571  {
572 
573  std::cout << "myRank:" << me << " stateBeg:" << stateBegin << " tsize:" << tsize << " state:" << state << " slice: " << slice / tsize << std::endl;
574  }
575  */
576 #ifdef HAVE_ZOLTAN2_OMP
577 #pragma omp for
578 #endif
579  for(lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
580  lno_t iteration = 0;
581  while(1){
582  if(++iteration > MAX_ITER_ALLOWED) {
583  throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
584  }
585  CoordinatePoint <T> p = this->getPoint( this->assignedPrevious + cnt, state);
586 
587  bool isInHole = false;
588  for(lno_t i = 0; i < holeCount; ++i){
589  if(holes[i][0].isInArea(p)){
590  isInHole = true;
591  break;
592  }
593  }
594  if(isInHole) continue;
595  coords[0][cnt + tindex] = p.x;
596  if(this->dimension > 1){
597  coords[1][cnt + tindex] = p.y;
598  if(this->dimension > 2){
599  coords[2][cnt + tindex] = p.z;
600  }
601  }
602  break;
603  }
604  }
605  }
606  }
607 };
608 
609 template <typename T, typename lno_t, typename gno_t>
611 public:
616 
617 
618  virtual T getXCenter(){
619  return center.x;
620  }
621  virtual T getXRadius(){
622  return standartDevx;
623  }
624 
626  T sd_x, T sd_y, T sd_z, int wSize) :
627  CoordinateDistribution<T,lno_t,gno_t>(np_,dim,wSize),
628  standartDevx(sd_x), standartDevy(sd_y), standartDevz(sd_z)
629  {
630  this->center.x = center_.x;
631  this->center.y = center_.y;
632  this->center.z = center_.z;
633  }
634 
635  virtual CoordinatePoint<T> getPoint(gno_t pindex, unsigned int &state){
636 
637  //pindex = 0; // not used in normal distribution.
639 
640  for(int i = 0; i < this->dimension; ++i){
641  switch(i){
642  case 0:
643  p.x = normalDist(this->center.x, this->standartDevx, state);
644  break;
645  case 1:
646  p.y = normalDist(this->center.y, this->standartDevy, state);
647  break;
648  case 2:
649  p.z = normalDist(this->center.z, this->standartDevz, state);
650  break;
651  default:
652  throw "unsupported dimension";
653  }
654  }
655  return p;
656  }
657 
659 private:
660  T normalDist(T center_, T sd, unsigned int &state) {
661  T polarsqrt, normalsquared, normal1, normal2;
662  do {
663  normal1=2.0*( T(rand_r(&state))/T(RAND_MAX) ) - 1.0;
664  normal2=2.0*( T(rand_r(&state))/T(RAND_MAX) ) - 1.0;
665  normalsquared=normal1*normal1+normal2*normal2;
666  } while ( normalsquared>=1.0 || normalsquared == 0.0);
667 
668  polarsqrt=sqrt(-2.0*log(normalsquared)/normalsquared);
669  return normal2*polarsqrt*sd + center_;
670  }
671 };
672 
673 template <typename T, typename lno_t, typename gno_t>
675 public:
682 
683 
684  virtual T getXCenter(){
685  return (rightMostx - leftMostx)/2 + leftMostx;
686  }
687  virtual T getXRadius(){
688  return (rightMostx - leftMostx)/2;
689  }
690 
691 
692  CoordinateUniformDistribution(gno_t np_, int dim, T l_x, T r_x, T l_y, T r_y,
693  T l_z, T r_z, int wSize ) :
694  CoordinateDistribution<T,lno_t,gno_t>(np_,dim,wSize),
695  leftMostx(l_x), rightMostx(r_x), leftMosty(l_y), rightMosty(r_y),
696  leftMostz(l_z), rightMostz(r_z){}
697 
699  virtual CoordinatePoint<T> getPoint(gno_t pindex, unsigned int &state){
700 
701 
702  //pindex = 0; //not used in uniform dist.
704  for(int i = 0; i < this->dimension; ++i){
705  switch(i){
706  case 0:
707  p.x = uniformDist(this->leftMostx, this->rightMostx, state);
708  break;
709  case 1:
710  p.y = uniformDist(this->leftMosty, this->rightMosty, state);
711  break;
712  case 2:
713  p.z = uniformDist(this->leftMostz, this->rightMostz, state);
714  break;
715  default:
716  throw "unsupported dimension";
717  }
718  }
719  return p;
720  }
721 
722 private:
723 
724  T uniformDist(T a, T b, unsigned int &state)
725  {
726  return (b-a)*(rand_r(&state) / double(RAND_MAX)) + a;
727  }
728 };
729 
730 template <typename T, typename lno_t, typename gno_t>
732 public:
740  //T currentX, currentY, currentZ;
742  int myRank;
745 
746  virtual T getXCenter(){
747  return (rightMostx - leftMostx)/2 + leftMostx;
748  }
749  virtual T getXRadius(){
750  return (rightMostx - leftMostx)/2;
751  }
752 
753 
754  CoordinateGridDistribution(gno_t alongX, gno_t alongY, gno_t alongZ, int dim,
755  T l_x, T r_x, T l_y, T r_y, T l_z, T r_z ,
756  int myRank_, int wSize) :
757  CoordinateDistribution<T,lno_t,gno_t>(alongX * alongY * alongZ,dim,wSize),
758  leftMostx(l_x), rightMostx(r_x), leftMosty(l_y), rightMosty(r_y), leftMostz(l_z), rightMostz(r_z), myRank(myRank_){
759  //currentX = leftMostx, currentY = leftMosty, currentZ = leftMostz;
760  this->processCnt = 0;
761  this->along_X = alongX; this->along_Y = alongY; this->along_Z = alongZ;
762 
763  if(this->along_X > 1)
764  this->xstep = (rightMostx - leftMostx) / (alongX - 1);
765  else
766  this->xstep = 1;
767  if(this->along_Y > 1)
768  this->ystep = (rightMosty - leftMosty) / (alongY - 1);
769  else
770  this->ystep = 1;
771  if(this->along_Z > 1)
772  this->zstep = (rightMostz - leftMostz) / (alongZ - 1);
773  else
774  this->zstep = 1;
775  xshift = 0; yshift = 0; zshift = 0;
776  }
777 
779  virtual CoordinatePoint<T> getPoint(gno_t pindex, unsigned int &state){
780  //lno_t before = processCnt + this->assignedPrevious;
781  //std::cout << "before:" << processCnt << " " << this->assignedPrevious << std::endl;
782  //lno_t xshift = 0, yshift = 0, zshift = 0;
783 
784  //lno_t tmp = before % (this->along_X * this->along_Y);
785  //xshift = tmp % this->along_X;
786  //yshift = tmp / this->along_X;
787  //zshift = before / (this->along_X * this->along_Y);
788 
789  state = 0; //not used here
790  this->zshift = pindex / (along_X * along_Y);
791  this->yshift = (pindex % (along_X * along_Y)) / along_X;
792  this->xshift = (pindex % (along_X * along_Y)) % along_X;
793 
794  //this->xshift = pindex / (along_Z * along_Y);
795  // this->zshift = (pindex % (along_Z * along_Y)) / along_Y;
796  //this->yshift = (pindex % (along_Z * along_Y)) % along_Y;
797 
799  p.x = xshift * this->xstep + leftMostx;
800  p.y = yshift * this->ystep + leftMosty;
801  p.z = zshift * this->zstep + leftMostz;
802 /*
803  ++xshift;
804  if(xshift == this->along_X){
805  ++yshift;
806  xshift = 0;
807  if(yshift == this->along_Y){
808  ++zshift;
809  yshift = 0;
810  }
811  }
812 */
813  /*
814  if(this->processCnt == 0){
815  this->xshift = this->assignedPrevious / (along_Z * along_Y);
816  //this->yshift = (this->assignedPrevious % (along_X * along_Y)) / along_X;
817  this->zshift = (this->assignedPrevious % (along_Z * along_Y)) / along_Y;
818  //this->xshift = (this->assignedPrevious % (along_X * along_Y)) % along_X;
819  this->yshift = (this->assignedPrevious % (along_Z * along_Y)) % along_Y;
820  ++this->processCnt;
821  }
822 
823  CoordinatePoint <T> p;
824  p.x = xshift * this->xstep + leftMostx;
825  p.y = yshift * this->ystep + leftMosty;
826  p.z = zshift * this->zstep + leftMostz;
827 
828  ++yshift;
829  if(yshift == this->along_Y){
830  ++zshift;
831  yshift = 0;
832  if(zshift == this->along_Z){
833  ++xshift;
834  zshift = 0;
835  }
836 
837  }
838  */
839  /*
840  if(this->requested - 1 > this->processCnt){
841  this->processCnt++;
842  } else {
843  std::cout << "req:" << this->requested << " pr:" <<this->processCnt << std::endl;
844  std::cout << "p:" << p.x << " " << p.y << " " << p.z << std::endl ;
845  std::cout << "s:" << xshift << " " << yshift << " " << zshift << std::endl ;
846  std::cout << "st:" << this->xstep << " " << this->ystep << " " << this->zstep << std::endl ;
847  }
848  */
849  return p;
850  }
851 
852 private:
853 
854 };
855 
856 template <typename scalar_t, typename lno_t, typename gno_t, typename node_t>
858 private:
859  Hole<scalar_t> **holes; //to represent if there is any hole in the input
860  int holeCount;
861  int coordinate_dimension; //dimension of the geometry
862  gno_t numGlobalCoords; //global number of coordinates requested to be created.
863  lno_t numLocalCoords;
864  float *loadDistributions; //sized as the number of processors, the load of each processor.
865  bool loadDistSet;
866  bool distinctCoordSet;
867  CoordinateDistribution<scalar_t, lno_t,gno_t> **coordinateDistributions;
868  int distributionCount;
869  //CoordinatePoint<scalar_t> *points;
870  scalar_t **coords;
871  scalar_t **wghts;
873  int numWeightsPerCoord;
874  int predistribution;
875  RCP<const Teuchos::Comm<int> > comm;
876  //RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmVector;
877  //RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmwVector;
878  int worldSize;
879  int myRank;
880  scalar_t minx;
881  scalar_t maxx;
882  scalar_t miny;
883  scalar_t maxy;
884  scalar_t minz;
885  scalar_t maxz;
886  std::string outfile;
887  float perturbation_ratio;
888 
889  typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> tMVector_t;
890  typedef Tpetra::Map<lno_t, gno_t, node_t> tMap_t;
891 
892 
893  template <typename tt>
894  tt getParamVal( const Teuchos::ParameterEntry& pe, const std::string &paramname){
895  tt returnVal;
896  try {
897  returnVal = Teuchos::getValue<tt>(pe);
898  }
899  catch (...){
900  throw INVALID(paramname);
901  }
902  return returnVal;
903  }
904 
905  int countChar (std::string inStr, char cntChar){
906  int cnt = 0;
907  for (unsigned int i = 0; i < inStr.size(); ++i){
908  if (inStr[i] == cntChar) {
909  cnt++;
910  }
911  }
912  return cnt;
913  }
914 
915  template <typename tt>
916  tt fromString(std::string obj){
917  std::stringstream ss (std::stringstream::in | std::stringstream::out);
918  ss << obj;
919  tt tmp;
920  ss >> tmp;
921  if (ss.fail()){
922  throw "Cannot convert string " + obj;
923  }
924  return tmp;
925  }
926 
927 
928  void splitString(std::string inStr, char splitChar, std::string *outSplittedStr){
929  std::stringstream ss (std::stringstream::in | std::stringstream::out);
930  ss << inStr;
931  int cnt = 0;
932  while (!ss.eof()){
933  std::string tmp = "";
934  std::getline(ss, tmp ,splitChar);
935  outSplittedStr[cnt++] = tmp;
936  }
937  }
938 
939  /*
940  void getDistinctCoordinateDescription(std::string distinctDescription){
941 
942  this->distinctCoordinates = new bool[this->dimension];
943  if(distinctDescription != ""){
944  int argCnt = this->countChar(distinctDescription, ',') + 1;
945  if(argCnt != this->dimension) {
946  throw "Invalid parameter count for distinct_coordinates. Size should be equal to dimension.";
947  }
948 
949  std::string *splittedStr = new std::string[argCnt];
950  splitString(holeDescription, ',', splittedStr);
951 
952  for(int i = 0; i < argCnt; ++i){
953  if(splittedStr[i] == "T"){
954  distinctCoordinates[i] = true;
955  } else if(splittedStr[i] == "F"){
956  distinctCoordinates[i] = false;
957  } else {
958  throw "Invalid parameter " + splittedStr[i] + " for distinct_coordinates.";
959  }
960  }
961  delete []splittedStr;
962  }
963  else {
964  for(int i = 0; i < this->dimension; ++i){
965  distinctCoordinates[i] = false;
966  }
967  }
968  }
969  */
970 
971 
972  void getCoordinateDistributions(std::string coordinate_distributions){
973  if(coordinate_distributions == ""){
974  throw "At least one distribution function must be provided to coordinate generator.";
975  }
976 
977  int argCnt = this->countChar(coordinate_distributions, ',') + 1;
978  std::string *splittedStr = new std::string[argCnt];
979  splitString(coordinate_distributions, ',', splittedStr);
980  coordinateDistributions = (CoordinateDistribution<scalar_t, lno_t,gno_t> **) malloc(sizeof (CoordinateDistribution<scalar_t, lno_t,gno_t> *) * 1);
981  for(int i = 0; i < argCnt; ){
982  coordinateDistributions = (CoordinateDistribution<scalar_t, lno_t,gno_t> **)realloc((void *)coordinateDistributions, (this->distributionCount + 1)* sizeof(CoordinateDistribution<scalar_t, lno_t,gno_t> *));
983 
984  std::string distName = splittedStr[i++];
985  gno_t np_ = 0;
986  if(distName == "NORMAL"){
987  int reqArg = 5;
988  if (this->coordinate_dimension == 3){
989  reqArg = 7;
990  }
991  if(i + reqArg > argCnt) {
992  std::string tmp = Teuchos::toString<int>(reqArg);
993  throw INVALID_SHAPE_ARG(distName, tmp);
994  }
995  np_ = fromString<gno_t>(splittedStr[i++]);
997 
998  pp.x = fromString<scalar_t>(splittedStr[i++]);
999  pp.y = fromString<scalar_t>(splittedStr[i++]);
1000  pp.z = 0;
1001  if(this->coordinate_dimension == 3){
1002  pp.z = fromString<scalar_t>(splittedStr[i++]);
1003  }
1004 
1005  scalar_t sd_x = fromString<scalar_t>(splittedStr[i++]);
1006  scalar_t sd_y = fromString<scalar_t>(splittedStr[i++]);
1007  scalar_t sd_z = 0;
1008  if(this->coordinate_dimension == 3){
1009  sd_z = fromString<scalar_t>(splittedStr[i++]);
1010  }
1011  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 );
1012 
1013  } else if(distName == "UNIFORM" ){
1014  int reqArg = 5;
1015  if (this->coordinate_dimension == 3){
1016  reqArg = 7;
1017  }
1018  if(i + reqArg > argCnt) {
1019  std::string tmp = Teuchos::toString<int>(reqArg);
1020  throw INVALID_SHAPE_ARG(distName, tmp);
1021  }
1022  np_ = fromString<gno_t>(splittedStr[i++]);
1023  scalar_t l_x = fromString<scalar_t>(splittedStr[i++]);
1024  scalar_t r_x = fromString<scalar_t>(splittedStr[i++]);
1025  scalar_t l_y = fromString<scalar_t>(splittedStr[i++]);
1026  scalar_t r_y = fromString<scalar_t>(splittedStr[i++]);
1027 
1028  scalar_t l_z = 0, r_z = 0;
1029 
1030  if(this->coordinate_dimension == 3){
1031  l_z = fromString<scalar_t>(splittedStr[i++]);
1032  r_z = fromString<scalar_t>(splittedStr[i++]);
1033  }
1034 
1035  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 );
1036  } else if (distName == "GRID"){
1037  int reqArg = 6;
1038  if(this->coordinate_dimension == 3){
1039  reqArg = 9;
1040  }
1041  if(i + reqArg > argCnt) {
1042  std::string tmp = Teuchos::toString<int>(reqArg);
1043  throw INVALID_SHAPE_ARG(distName, tmp);
1044  }
1045 
1046  gno_t np_x = fromString<gno_t>(splittedStr[i++]);
1047  gno_t np_y = fromString<gno_t>(splittedStr[i++]);
1048  gno_t np_z = 1;
1049 
1050 
1051  if(this->coordinate_dimension == 3){
1052  np_z = fromString<gno_t>(splittedStr[i++]);
1053  }
1054 
1055  np_ = np_x * np_y * np_z;
1056  scalar_t l_x = fromString<scalar_t>(splittedStr[i++]);
1057  scalar_t r_x = fromString<scalar_t>(splittedStr[i++]);
1058  scalar_t l_y = fromString<scalar_t>(splittedStr[i++]);
1059  scalar_t r_y = fromString<scalar_t>(splittedStr[i++]);
1060 
1061  scalar_t l_z = 0, r_z = 0;
1062 
1063  if(this->coordinate_dimension == 3){
1064  l_z = fromString<scalar_t>(splittedStr[i++]);
1065  r_z = fromString<scalar_t>(splittedStr[i++]);
1066  }
1067 
1068  if(np_x < 1 || np_z < 1 || np_y < 1 ){
1069  throw "Provide at least 1 point along each dimension for grid test.";
1070  }
1071  //std::cout << "ly:" << l_y << " ry:" << r_y << std::endl;
1072  this->coordinateDistributions[this->distributionCount++] = new CoordinateGridDistribution<scalar_t, lno_t,gno_t>
1073  (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);
1074 
1075  }
1076  else {
1077  std::string tmp = Teuchos::toString<int>(this->coordinate_dimension);
1078  throw INVALIDSHAPE(distName, tmp);
1079  }
1080  this->numGlobalCoords += (gno_t) np_;
1081  }
1082  delete []splittedStr;
1083  }
1084 
1085  void getProcLoadDistributions(std::string proc_load_distributions){
1086 
1087  this->loadDistributions = new float[this->worldSize];
1088  if(proc_load_distributions == ""){
1089  float r = 1.0 / this->worldSize;
1090  for(int i = 0; i < this->worldSize; ++i){
1091  this->loadDistributions[i] = r;
1092  }
1093  } else{
1094 
1095 
1096  int argCnt = this->countChar(proc_load_distributions, ',') + 1;
1097  if(argCnt != this->worldSize) {
1098  throw "Invalid parameter count load distributions. Given " + Teuchos::toString<int>(argCnt) + " processor size is " + Teuchos::toString<int>(this->worldSize);
1099  }
1100  std::string *splittedStr = new std::string[argCnt];
1101  splitString(proc_load_distributions, ',', splittedStr);
1102  for(int i = 0; i < argCnt; ++i){
1103  this->loadDistributions[i] = fromString<float>(splittedStr[i]);
1104  }
1105  delete []splittedStr;
1106 
1107 
1108  float sum = 0;
1109  for(int i = 0; i < this->worldSize; ++i){
1110  sum += this->loadDistributions[i];
1111  }
1112  if (fabs(sum - 1.0) > 10*std::numeric_limits<float>::epsilon()){
1113  throw "Processor load ratios do not sum to 1.0.";
1114  }
1115  }
1116 
1117  }
1118 
1119  void getHoles(std::string holeDescription){
1120  if(holeDescription == ""){
1121  return;
1122  }
1123  this->holes = (Hole<scalar_t> **) malloc(sizeof (Hole <scalar_t>*));
1124  int argCnt = this->countChar(holeDescription, ',') + 1;
1125  std::string *splittedStr = new std::string[argCnt];
1126  splitString(holeDescription, ',', splittedStr);
1127 
1128  for(int i = 0; i < argCnt; ){
1129  holes = (Hole<scalar_t> **)realloc((void *)holes, (this->holeCount + 1)* sizeof(Hole<scalar_t> *));
1130 
1131  std::string shapeName = splittedStr[i++];
1132  if(shapeName == "SQUARE" && this->coordinate_dimension == 2){
1133  if(i + 3 > argCnt) {
1134  throw INVALID_SHAPE_ARG(shapeName, "3");
1135  }
1137  pp.x = fromString<scalar_t>(splittedStr[i++]);
1138  pp.y = fromString<scalar_t>(splittedStr[i++]);
1139  scalar_t edge = fromString<scalar_t>(splittedStr[i++]);
1140  this->holes[this->holeCount++] = new SquareHole<scalar_t>(pp, edge);
1141  } else if(shapeName == "RECTANGLE" && this->coordinate_dimension == 2){
1142  if(i + 4 > argCnt) {
1143  throw INVALID_SHAPE_ARG(shapeName, "4");
1144  }
1146  pp.x = fromString<scalar_t>(splittedStr[i++]);
1147  pp.y = fromString<scalar_t>(splittedStr[i++]);
1148  scalar_t edgex = fromString<scalar_t>(splittedStr[i++]);
1149  scalar_t edgey = fromString<scalar_t>(splittedStr[i++]);
1150 
1151  this->holes[this->holeCount++] = new RectangleHole<scalar_t>(pp, edgex,edgey);
1152  } else if(shapeName == "CIRCLE" && this->coordinate_dimension == 2){
1153  if(i + 3 > argCnt) {
1154  throw INVALID_SHAPE_ARG(shapeName, "3");
1155  }
1157  pp.x = fromString<scalar_t>(splittedStr[i++]);
1158  pp.y = fromString<scalar_t>(splittedStr[i++]);
1159  scalar_t r = fromString<scalar_t>(splittedStr[i++]);
1160  this->holes[this->holeCount++] = new CircleHole<scalar_t>(pp, r);
1161  } else if(shapeName == "CUBE" && this->coordinate_dimension == 3){
1162  if(i + 4 > argCnt) {
1163  throw INVALID_SHAPE_ARG(shapeName, "4");
1164  }
1166  pp.x = fromString<scalar_t>(splittedStr[i++]);
1167  pp.y = fromString<scalar_t>(splittedStr[i++]);
1168  pp.z = fromString<scalar_t>(splittedStr[i++]);
1169  scalar_t edge = fromString<scalar_t>(splittedStr[i++]);
1170  this->holes[this->holeCount++] = new CubeHole<scalar_t>(pp, edge);
1171  } else if(shapeName == "RECTANGULAR_PRISM" && this->coordinate_dimension == 3){
1172  if(i + 6 > argCnt) {
1173  throw INVALID_SHAPE_ARG(shapeName, "6");
1174  }
1176  pp.x = fromString<scalar_t>(splittedStr[i++]);
1177  pp.y = fromString<scalar_t>(splittedStr[i++]);
1178  pp.z = fromString<scalar_t>(splittedStr[i++]);
1179  scalar_t edgex = fromString<scalar_t>(splittedStr[i++]);
1180  scalar_t edgey = fromString<scalar_t>(splittedStr[i++]);
1181  scalar_t edgez = fromString<scalar_t>(splittedStr[i++]);
1182  this->holes[this->holeCount++] = new RectangularPrismHole<scalar_t>(pp, edgex, edgey, edgez);
1183 
1184  } else if(shapeName == "SPHERE" && this->coordinate_dimension == 3){
1185  if(i + 4 > argCnt) {
1186  throw INVALID_SHAPE_ARG(shapeName, "4");
1187  }
1189  pp.x = fromString<scalar_t>(splittedStr[i++]);
1190  pp.y = fromString<scalar_t>(splittedStr[i++]);
1191  pp.z = fromString<scalar_t>(splittedStr[i++]);
1192  scalar_t r = fromString<scalar_t>(splittedStr[i++]);
1193  this->holes[this->holeCount++] = new SphereHole<scalar_t>(pp, r);
1194  } else {
1195  std::string tmp = Teuchos::toString<int>(this->coordinate_dimension);
1196  throw INVALIDSHAPE(shapeName, tmp);
1197  }
1198  }
1199  delete [] splittedStr;
1200  }
1201 
1202  void getWeightDistribution(std::string *weight_distribution_arr, int wdimension){
1203  int wcount = 0;
1204 
1205  this->wd = new WeightDistribution<scalar_t,scalar_t> *[wdimension];
1206  for(int ii = 0; ii < MAX_WEIGHT_DIM; ++ii){
1207  std::string weight_distribution = weight_distribution_arr[ii];
1208  if(weight_distribution == "") continue;
1209  if(wcount == wdimension) {
1210  throw "Weight Dimension is provided as " + Teuchos::toString<int>(wdimension) + ". More weight distribution is provided.";
1211  }
1212 
1213  int count = this->countChar(weight_distribution, ' ');
1214  std::string *splittedStr = new string[count + 1];
1215  this->splitString(weight_distribution, ' ', splittedStr);
1216  //std::cout << count << std::endl;
1217  scalar_t c=1;
1218  scalar_t a1=0,a2=0,a3=0;
1219  scalar_t x1=0,y1=0,z1=0;
1220  scalar_t b1=1,b2=1,b3=1;
1221  scalar_t *steps = NULL;
1222  scalar_t *values= NULL;
1223  int stepCount = 0;
1224  int valueCount = 1;
1225 
1226  for (int i = 1; i < count + 1; ++i){
1227  int assignmentCount = this->countChar(splittedStr[i], '=');
1228  if (assignmentCount != 1){
1229  throw "Error at the argument " + splittedStr[i];
1230  }
1231  std::string parameter_vs_val[2];
1232  this->splitString(splittedStr[i], '=', parameter_vs_val);
1233  std::string parameter = parameter_vs_val[0];
1234  std::string value = parameter_vs_val[1];
1235  //std::cout << "parameter:" << parameter << " value:" << value << std::endl;
1236 
1237  if (parameter == "a1"){
1238  a1 = this->fromString<scalar_t>(value);
1239  }
1240  else if (parameter == "a2"){
1241  if(this->coordinate_dimension > 1){
1242  a2 = this->fromString<scalar_t>(value);
1243  }
1244  else {
1245  throw parameter+ " argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1246  }
1247 
1248  }
1249  else if (parameter == "a3"){
1250  if(this->coordinate_dimension > 2){
1251  a3 = this->fromString<scalar_t>(value);
1252  }
1253  else {
1254  throw parameter+ " argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1255  }
1256  }
1257  else if (parameter == "b1"){
1258  b1 = this->fromString<scalar_t>(value);
1259  }
1260  else if (parameter == "b2"){
1261  if(this->coordinate_dimension > 1){
1262  b2 = this->fromString<scalar_t>(value);
1263  }
1264  else {
1265  throw parameter+ " argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1266  }
1267  }
1268  else if (parameter == "b3"){
1269 
1270  if(this->coordinate_dimension > 2){
1271  b3 = this->fromString<scalar_t>(value);
1272  }
1273  else {
1274  throw parameter+ " argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1275  }
1276  }
1277  else if (parameter == "c"){
1278  c = this->fromString<scalar_t>(value);
1279  }
1280  else if (parameter == "x1"){
1281  x1 = this->fromString<scalar_t>(value);
1282  }
1283  else if (parameter == "y1"){
1284  if(this->coordinate_dimension > 1){
1285  y1 = this->fromString<scalar_t>(value);
1286  }
1287  else {
1288  throw parameter+ " argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1289  }
1290  }
1291  else if (parameter == "z1"){
1292  if(this->coordinate_dimension > 2){
1293  z1 = this->fromString<scalar_t>(value);
1294  }
1295  else {
1296  throw parameter+ " argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1297  }
1298  }
1299  else if (parameter == "steps"){
1300  stepCount = this->countChar(value, ',') + 1;
1301  std::string *stepstr = new std::string[stepCount];
1302  this->splitString(value, ',', stepstr);
1303  steps = new scalar_t[stepCount];
1304  for (int j = 0; j < stepCount; ++j){
1305  steps[j] = this->fromString<scalar_t>(stepstr[j]);
1306  }
1307  delete [] stepstr;
1308  }
1309  else if (parameter == "values"){
1310  valueCount = this->countChar(value, ',') + 1;
1311  std::string *stepstr = new std::string[valueCount];
1312  this->splitString(value, ',', stepstr);
1313  values = new scalar_t[valueCount];
1314  for (int j = 0; j < valueCount; ++j){
1315  values[j] = this->fromString<scalar_t>(stepstr[j]);
1316  }
1317  delete [] stepstr;
1318  }
1319  else {
1320  throw "Invalid parameter name at " + splittedStr[i];
1321  }
1322  }
1323 
1324  delete []splittedStr;
1325  if(stepCount + 1!= valueCount){
1326  throw "Step count: " + Teuchos::toString<int>(stepCount) + " must be 1 less than value count: " + Teuchos::toString<int>(valueCount);
1327  }
1328 
1329 
1330  this->wd[wcount++] = new SteppedEquation<scalar_t,scalar_t>(a1, a2, a3, b1, b2, b3, c, x1, y1, z1, steps, values, stepCount);
1331 
1332  if(stepCount > 0){
1333  delete [] steps;
1334  delete [] values;
1335 
1336  }
1337  }
1338  if(wcount != this->numWeightsPerCoord){
1339  throw "Weight Dimension is provided as " + Teuchos::toString<int>(wdimension) + ". But " + Teuchos::toString<int>(wcount)+" weight distributions are provided.";
1340  }
1341  }
1342 
1343  void parseParams(const Teuchos::ParameterList & params){
1344  try {
1345  std::string holeDescription = "";
1346  std::string proc_load_distributions = "";
1347  std::string distinctDescription = "";
1348  std::string coordinate_distributions = "";
1349  std::string numWeightsPerCoord_parameters[MAX_WEIGHT_DIM];
1350  for (int i = 0; i < MAX_WEIGHT_DIM; ++i){
1351  numWeightsPerCoord_parameters[i] = "";
1352  }
1353 
1354 
1355  for (Teuchos::ParameterList::ConstIterator pit = params.begin(); pit != params.end(); ++pit ){
1356  const std::string &paramName = params.name(pit);
1357 
1358  const Teuchos::ParameterEntry &pe = params.entry(pit);
1359 
1360  if(paramName.find("hole-") == 0){
1361  if(holeDescription == ""){
1362  holeDescription = getParamVal<std::string>(pe, paramName);
1363  }
1364  else {
1365  holeDescription +=","+getParamVal<std::string>(pe, paramName);
1366  }
1367  }
1368  else if(paramName.find("distribution-") == 0){
1369  if(coordinate_distributions == "")
1370  coordinate_distributions = getParamVal<std::string>(pe, paramName);
1371  else
1372  coordinate_distributions += ","+getParamVal<std::string>(pe, paramName);
1373  //std::cout << coordinate_distributions << std::endl;
1374  //TODO coordinate distribution description
1375  }
1376 
1377  else if (paramName.find(weight_distribution_string) == 0){
1378  std::string weight_dist_param = paramName.substr(weight_distribution_string.size());
1379  int dash_pos = weight_dist_param.find("-");
1380  std::string distribution_index_string = weight_dist_param.substr(0, dash_pos);
1381  int distribution_index = fromString<int>(distribution_index_string);
1382 
1383  if(distribution_index >= MAX_WEIGHT_DIM){
1384  throw "Given distribution index:" + distribution_index_string + " larger than maximum allowed number of weights:" + Teuchos::toString<int>(MAX_WEIGHT_DIM);
1385  }
1386  numWeightsPerCoord_parameters[distribution_index] += " " + weight_dist_param.substr(dash_pos + 1)+ "="+ getParamVal<std::string>(pe, paramName);
1387  }
1388  else if(paramName == "dim"){
1389  int dim = fromString<int>(getParamVal<std::string>(pe, paramName));
1390  if(dim < 2 || dim > 3){
1391  throw INVALID(paramName);
1392  } else {
1393  this->coordinate_dimension = dim;
1394  }
1395  }
1396  else if(paramName == "wdim"){
1397  int dim = fromString<int>(getParamVal<std::string>(pe, paramName));
1398  if(dim < 1 && dim > MAX_WEIGHT_DIM){
1399  throw INVALID(paramName);
1400  } else {
1401  this->numWeightsPerCoord = dim;
1402  }
1403  }
1404  else if(paramName == "predistribution"){
1405  int pre_distribution = fromString<int>(getParamVal<std::string>(pe, paramName));
1406  if(pre_distribution < 0 || pre_distribution > 3){
1407  throw INVALID(paramName);
1408  } else {
1409  this->predistribution = pre_distribution;
1410  }
1411  }
1412  else if(paramName == "perturbation_ratio"){
1413  float perturbation = fromString<float>(getParamVal<std::string>(pe, paramName));
1414  if(perturbation < 0 && perturbation > 1){
1415  throw INVALID(paramName);
1416  } else {
1417  this->perturbation_ratio = perturbation;
1418  }
1419  }
1420 
1421 
1422  else if(paramName == "proc_load_distributions"){
1423  proc_load_distributions = getParamVal<std::string>(pe, paramName);
1424  this->loadDistSet = true;
1425  }
1426 
1427  else if(paramName == "distinct_coordinates"){
1428  distinctDescription = getParamVal<std::string>(pe, paramName);
1429  if(distinctDescription == "T"){
1430  this->distinctCoordSet = true;
1431  } else if(distinctDescription == "F"){
1432  this->distinctCoordSet = true;
1433  } else {
1434  throw "Invalid parameter for distinct_coordinates: " + distinctDescription + ". Candidates: T or F." ;
1435  }
1436  }
1437 
1438  else if(paramName == "out_file"){
1439  this->outfile = getParamVal<std::string>(pe, paramName);
1440  }
1441 
1442  else {
1443  throw INVALID(paramName);
1444  }
1445  }
1446 
1447 
1448  if(this->coordinate_dimension == 0){
1449  throw "Dimension must be provided to coordinate generator.";
1450  }
1451  /*
1452  if(this->globalNumCoords == 0){
1453  throw "Number of coordinates must be provided to coordinate generator.";
1454  }
1455  */
1456  /*
1457  if(maxx <= minx ){
1458  throw "Error: maxx= "+ Teuchos::toString<scalar_t>(maxx)+ " and minx=" + Teuchos::toString<scalar_t>(minx);
1459  }
1460  if(maxy <= miny ){
1461  throw "Error: maxy= "+ Teuchos::toString<scalar_t>(maxy)+ " and miny=" + Teuchos::toString<scalar_t>(miny);
1462 
1463  }
1464  if(this->dimension == 3 && maxz <= minz ){
1465  throw "Error: maxz= "+ Teuchos::toString<scalar_t>(maxz)+ " and minz=" + Teuchos::toString<scalar_t>(minz);
1466  }
1467  */
1468  if (this->loadDistSet && this->distinctCoordSet){
1469  throw "distinct_coordinates and proc_load_distributions parameters cannot be satisfied together.";
1470  }
1471  this->getHoles(holeDescription);
1472  //this->getDistinctCoordinateDescription(distinctDescription);
1473  this->getProcLoadDistributions(proc_load_distributions);
1474  this->getCoordinateDistributions(coordinate_distributions);
1475  this->getWeightDistribution(numWeightsPerCoord_parameters, this->numWeightsPerCoord);
1476  /*
1477  if(this->numGlobalCoords <= 0){
1478  throw "Must have at least 1 point";
1479  }
1480  */
1481  }
1482  catch(std::string &s){
1483  throw std::runtime_error(s);
1484  }
1485 
1486  catch(const char *s){
1487  throw std::runtime_error(s);
1488  }
1489  }
1490 public:
1491 
1493  if(this->holes){
1494  for (int i = 0; i < this->holeCount; ++i){
1495  delete this->holes[i];
1496  }
1497  free (this->holes);
1498  }
1499 
1500 
1501  delete []loadDistributions; //sized as the number of processors, the load of each processor.
1502  //delete []distinctCoordinates; // if processors have different or same range for coordinates to be created.
1503  if(coordinateDistributions){
1504 
1505  for (int i = 0; i < this->distributionCount; ++i){
1506  delete this->coordinateDistributions[i];
1507  }
1508  free (this->coordinateDistributions);
1509  }
1510  if (this->wd){
1511  for (int i = 0; i < this->numWeightsPerCoord; ++i){
1512  delete this->wd[i];
1513  }
1514  delete []this->wd;
1515  }
1516 
1517  if(this->numWeightsPerCoord){
1518  for(int i = 0; i < this->numWeightsPerCoord; ++i)
1519  delete [] this->wghts[i];
1520  delete []this->wghts;
1521  }
1522  if(this->coordinate_dimension){
1523  for(int i = 0; i < this->coordinate_dimension; ++i)
1524  delete [] this->coords[i];
1525  delete [] this->coords;
1526  }
1527  //delete []this->points;
1528  }
1529 
1531  std::cout <<"\nGeometric Generator Parameter File Format:" << std::endl;
1532  std::cout <<"- dim=Coordinate Dimension: 2 or 3" << std::endl;
1533  std::cout <<"- Available distributions:" << std::endl;
1534  std::cout <<"\tUNIFORM: -> distribution-1=UNIFORM,NUMCOORDINATES,XMIN,XMAX,YMIN,YMAX{,ZMIN,ZMAX}" << std::endl;
1535  std::cout <<"\tGRID: -> distribution-2=GRID,XLENGTH,YLENGTH{,ZLENGTH},XMIN,XMAX,YMIN,YMAX{,ZMIN,ZMAX}" << std::endl;
1536  std::cout <<"\tNORMAL: -> distribution-3=NORMAL,XCENTER,YCENTER{,ZCENTER},XSD,YSD,{,ZSD}" << std::endl;
1537  std::cout <<"- wdim=numWeightsPerCoord: There should be as many weight function as number of weights per coord." << std::endl;
1538  std::cout <<"- Weight Equation: w = (a1 * (x - x1)^b1) + (a2 * (y - y1)^b2) + (a3 * (z - z1)^b3) + c" << std::endl;
1539  std::cout << "Parameter settings:" << std::endl;
1540  std::cout << "\tWeightDistribution-1-a1=a1 " << std::endl;
1541  std::cout << "\tWeightDistribution-1-a2=a2 " << std::endl;
1542  std::cout << "\tWeightDistribution-1-a3=a3 " << std::endl;
1543  std::cout << "\tWeightDistribution-1-b1=b1 " << std::endl;
1544  std::cout << "\tWeightDistribution-1-b2=b2 " << std::endl;
1545  std::cout << "\tWeightDistribution-1-b3=b3 " << std::endl;
1546  std::cout << "\tWeightDistribution-1-x1=x1 " << std::endl;
1547  std::cout << "\tWeightDistribution-1-y1=y1 " << std::endl;
1548  std::cout << "\tWeightDistribution-1-z1=z1 " << std::endl;
1549  std::cout << "\tWeightDistribution-1-c=c " << std::endl;
1550  std::cout << "\tIt is possible to set step function to the result of weight equation." << std::endl;
1551  std::cout << "\tWeightDistribution-1-steps=step1,step2,step3:increasing order" << std::endl;
1552  std::cout << "\tWeightDistribution-1-values=val1,val2,val3,val4." << std::endl;
1553  std::cout << "\t\tIf w < step1 -> w = val1" << std::endl;
1554  std::cout << "\t\tElse if w < step2 -> w = val2" << std::endl;
1555  std::cout << "\t\tElse if w < step3 -> w = val3" << std::endl;
1556  std::cout << "\t\tElse -> w = val4" << std::endl;
1557  std::cout <<"- Holes:" << std::endl;
1558  std::cout << "\thole-1:SPHERE,XCENTER,YCENTER,ZCENTER,RADIUS (only for dim=3)" << std::endl;
1559  std::cout << "\thole-2:CUBE,XCENTER,YCENTER,ZCENTER,EDGE (only for dim=3)" << std::endl;
1560  std::cout << "\thole-3:RECTANGULAR_PRISM,XCENTER,YCENTER,ZCENTER,XEDGE,YEDGE,ZEDGE (only for dim=3)" << std::endl;
1561  std::cout << "\thole-4:SQUARE,XCENTER,YCENTER,EDGE (only for dim=2)" << std::endl;
1562  std::cout << "\thole-5:RECTANGLE,XCENTER,YCENTER,XEDGE,YEDGE (only for dim=2)" << std::endl;
1563  std::cout << "\thole-6:CIRCLE,XCENTER,YCENTER,RADIUS (only for dim=2)" << std::endl;
1564  std::cout << "- out_file:out_file_path : if provided output will be written to files." << std::endl;
1565  std::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." << std::endl;
1566  std::cout << "- predistribution:distribution_option. Predistribution of the coordinates to the processors. 0 for NONE, 1 RCB, 2 MJ, 3 BLOCK." << std::endl;
1567  std::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." << std::endl;
1568  }
1569 
1570  GeometricGenerator(Teuchos::ParameterList &params, const RCP<const Teuchos::Comm<int> > & comm_){
1571  this->wd = NULL;
1572  this->comm = comm_;
1573  this->holes = NULL; //to represent if there is any hole in the input
1574  this->coordinate_dimension = 0; //dimension of the geometry
1575  this->numWeightsPerCoord = 0;
1576  this->worldSize = comm_->getSize(); //comminication world object.
1577  this->numGlobalCoords = 0; //global number of coordinates requested to be created.
1578  this->loadDistributions = NULL; //sized as the number of processors, the load of each processor.
1579  //this->distinctCoordinates = NULL; // if processors have different or same range for coordinates to be created.
1580  this->coordinateDistributions = NULL;
1581  this->holeCount = 0;
1582  this->distributionCount = 0;
1583  this->outfile = "";
1584  this->predistribution = 0;
1585  this->perturbation_ratio = 0;
1586  //this->points = NULL;
1587 
1588  /*
1589  this->minx = 0;
1590  this->maxx = 0;
1591  this->miny = 0;
1592  this->maxy = 0;
1593  this->minz = 0;
1594  this->maxz = 0;
1595  */
1596  this->loadDistSet = false;
1597  this->distinctCoordSet = false;
1598  this->myRank = comm_->getRank();
1599 
1600  try {
1601  this->parseParams(params);
1602  }
1603  catch(std::string &s){
1604  if(myRank == 0){
1606  }
1607  throw std::runtime_error(s);
1608  }
1609 
1610  catch(const char *s){
1611  if(myRank == 0){
1613  }
1614  throw std::runtime_error(s);
1615  }
1616 
1617 
1618  lno_t myPointCount = 0;
1619  this->numGlobalCoords = 0;
1620 
1621  gno_t prefixSum = 0;
1622  for(int i = 0; i < this->distributionCount; ++i){
1623  for(int ii = 0; ii < this->worldSize; ++ii){
1624  lno_t increment = lno_t (this->coordinateDistributions[i]->numPoints * this->loadDistributions[ii]);
1625  if (gno_t(ii) < this->coordinateDistributions[i]->numPoints % this->worldSize){
1626  increment += 1;
1627  }
1628  this->numGlobalCoords += increment;
1629  if(ii < myRank){
1630  prefixSum += increment;
1631  }
1632  }
1633  myPointCount += lno_t(this->coordinateDistributions[i]->numPoints * this->loadDistributions[myRank]);
1634  if (gno_t(myRank) < this->coordinateDistributions[i]->numPoints % this->worldSize){
1635  myPointCount += 1;
1636  }
1637  }
1638 
1639  this->coords = new scalar_t *[this->coordinate_dimension];
1640  for(int i = 0; i < this->coordinate_dimension; ++i){
1641  this->coords[i] = new scalar_t[myPointCount];
1642  }
1643 
1644  for (int ii = 0; ii < this->coordinate_dimension; ++ii){
1645 #ifdef HAVE_ZOLTAN2_OMP
1646 #pragma omp parallel for
1647 #endif
1648  for(lno_t i = 0; i < myPointCount; ++i){
1649  this->coords[ii][i] = 0;
1650  }
1651  }
1652 
1653  this->numLocalCoords = 0;
1654  srand ((myRank + 1) * this->numLocalCoords);
1655  for (int i = 0; i < distributionCount; ++i){
1656 
1657  lno_t requestedPointCount = lno_t(this->coordinateDistributions[i]->numPoints * this->loadDistributions[myRank]);
1658  if (gno_t(myRank) < this->coordinateDistributions[i]->numPoints % this->worldSize){
1659  requestedPointCount += 1;
1660  }
1661  //std::cout << "req:" << requestedPointCount << std::endl;
1662  //this->coordinateDistributions[i]->GetPoints(requestedPointCount,this->points + this->numLocalCoords, this->holes, this->holeCount, this->loadDistributions, myRank);
1663  this->coordinateDistributions[i]->GetPoints(requestedPointCount,this->coords, this->numLocalCoords, this->holes, this->holeCount, this->loadDistributions, myRank);
1664  this->numLocalCoords += requestedPointCount;
1665  }
1666 
1667  /*
1668 
1669  if (this->myRank >= 0){
1670  for(lno_t i = 0; i < this->numLocalCoords; ++i){
1671 
1672  std::cout <<"me:" << this->myRank << " "<< this->coords[0][i];
1673  if(this->coordinate_dimension > 1){
1674  std::cout << " " << this->coords[1][i];
1675  }
1676  if(this->coordinate_dimension > 2){
1677  std::cout << " " << this->coords[2][i];
1678  }
1679  std::cout << std::endl;
1680  }
1681  }
1682  */
1683 
1684 
1685 
1686  if (this->predistribution){
1687  redistribute();
1688  }
1689 
1690 
1691 
1692  int scale = 3;
1693  if (this->perturbation_ratio > 0){
1694  this->perturb_data(this->perturbation_ratio, scale);
1695  }
1696  /*
1697  if (this->myRank >= 0){
1698  std::cout << "after distribution" << std::endl;
1699  for(lno_t i = 0; i < this->numLocalCoords; ++i){
1700 
1701  std::cout <<"me:" << this->myRank << " " << this->coords[0][i];
1702  if(this->coordinate_dimension > 1){
1703  std::cout << " " << this->coords[1][i];
1704  }
1705  if(this->coordinate_dimension > 2){
1706  std::cout << " " << this->coords[2][i];
1707  }
1708  std::cout << std::endl;
1709  }
1710  }
1711 
1712  */
1713 
1714 
1715  if (this->distinctCoordSet){
1716  //TODO: Partition and migration.
1717  }
1718 
1719  if(this->outfile != ""){
1720 
1721  std::ofstream myfile;
1722  myfile.open ((this->outfile + Teuchos::toString<int>(myRank)).c_str());
1723  for(lno_t i = 0; i < this->numLocalCoords; ++i){
1724 
1725  myfile << this->coords[0][i];
1726  if(this->coordinate_dimension > 1){
1727  myfile << " " << this->coords[1][i];
1728  }
1729  if(this->coordinate_dimension > 2){
1730  myfile << " " << this->coords[2][i];
1731  }
1732  myfile << std::endl;
1733  }
1734  myfile.close();
1735 
1736  if (this->myRank == 0){
1737  std::ofstream gnuplotfile("gnu.gnuplot");
1738  for(int i = 0; i < this->worldSize; ++i){
1739  string s = "splot";
1740  if (this->coordinate_dimension == 2){
1741  s = "plot";
1742  }
1743  if (i > 0){
1744  s = "replot";
1745  }
1746  gnuplotfile << s << " \"" << (this->outfile + Teuchos::toString<int>(i)) << "\"" << std::endl;
1747  }
1748  gnuplotfile << "pause -1" << std::endl;
1749  gnuplotfile.close();
1750  }
1751  }
1752 
1753 
1754 
1755  /*
1756  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));
1757 
1758  RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmVector2;
1759  Zoltan2::PartitioningSolution< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> > solution;
1760  xmv.applyPartitioningSolution<Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >(this->tmVector, &tmVector2, solution);
1761  */
1762  if (this->numWeightsPerCoord > 0){
1763  this->wghts = new scalar_t *[this->numWeightsPerCoord];
1764  for(int i = 0; i < this->numWeightsPerCoord; ++i){
1765  this->wghts[i] = new scalar_t[this->numLocalCoords];
1766  }
1767  }
1768 
1769  for(int ii = 0; ii < this->numWeightsPerCoord; ++ii){
1770  switch(this->coordinate_dimension){
1771  case 1:
1772  {
1773 #ifdef HAVE_ZOLTAN2_OMP
1774 #pragma omp parallel for
1775 #endif
1776  for (lno_t i = 0; i < this->numLocalCoords; ++i){
1777  this->wghts[ii][i] = this->wd[ii]->get1DWeight(this->coords[0][i]);
1778  }
1779  }
1780  break;
1781  case 2:
1782  {
1783 #ifdef HAVE_ZOLTAN2_OMP
1784 #pragma omp parallel for
1785 #endif
1786  for (lno_t i = 0; i < this->numLocalCoords; ++i){
1787  this->wghts[ii][i] = this->wd[ii]->get2DWeight(this->coords[0][i], this->coords[1][i]);
1788  }
1789  }
1790  break;
1791  case 3:
1792  {
1793 #ifdef HAVE_ZOLTAN2_OMP
1794 #pragma omp parallel for
1795 #endif
1796  for (lno_t i = 0; i < this->numLocalCoords; ++i){
1797  this->wghts[ii][i] = this->wd[ii]->get3DWeight(this->coords[0][i], this->coords[1][i], this->coords[2][i]);
1798  }
1799  }
1800  break;
1801  }
1802  }
1803  }
1804 
1805  //############################################################//
1807  //############################################################//
1808  void perturb_data(float used_perturbation_ratio, int scale){
1809  scalar_t *maxCoords= new scalar_t [this->coordinate_dimension];
1810  scalar_t *minCoords= new scalar_t [this->coordinate_dimension];
1811  for (int dim = 0; dim < this->coordinate_dimension; ++dim){
1812  minCoords[dim] = maxCoords[dim] = this->coords[dim][0];
1813  for (lno_t i = 1; i < this->numLocalCoords; ++i){
1814  if (minCoords[dim] > this->coords[dim][i]){
1815  minCoords[dim] = this->coords[dim][i];
1816  }
1817 
1818  if (maxCoords[dim] < this->coords[dim][i]){
1819  maxCoords[dim] = this->coords[dim][i];
1820  }
1821  }
1822 
1823 
1824 
1825 
1826  scalar_t center = (maxCoords[dim] + minCoords[dim]) / 2;
1827 
1828  minCoords[dim] = center - (center - minCoords[dim]) * scale;
1829  maxCoords[dim] = (maxCoords[dim] - center) * scale + center;
1830 
1831  }
1832 
1833  gno_t numLocalToPerturb = gno_t(this->numLocalCoords*used_perturbation_ratio);
1834  //std::cout << "numLocalToPerturb :" << numLocalToPerturb << std::endl;
1835  for (int dim = 0; dim < this->coordinate_dimension; ++dim){
1836  scalar_t range = maxCoords[dim] - minCoords[dim];
1837  for (gno_t i = 0; i < numLocalToPerturb; ++i){
1838  this->coords[dim][i] = (rand() / double (RAND_MAX)) * (range) + minCoords[dim];
1839 
1840  }
1841  }
1842  delete []maxCoords;
1843  delete []minCoords;
1844  }
1845 
1846  //############################################################//
1848  //############################################################//
1849 
1850  //Returns the partitioning dimension as even as possible
1851  void getBestSurface (int remaining, int *dimProcs, int dim, int currentDim, int &bestSurface, int *bestDimProcs){
1852 
1853  if (currentDim < dim - 1){
1854  int ipx = 1;
1855  while(ipx <= remaining) {
1856  if(remaining % ipx == 0) {
1857  int nremain = remaining / ipx;
1858  dimProcs[currentDim] = ipx;
1859  getBestSurface (nremain, dimProcs, dim, currentDim + 1, bestSurface, bestDimProcs);
1860  }
1861  ipx++;
1862  }
1863  }
1864  else {
1865  dimProcs[currentDim] = remaining;
1866  int surface = 0;
1867  for (int i = 0; i < dim; ++i) surface += dimProcs[i];
1868  if (surface < bestSurface){
1869  bestSurface = surface;
1870  for (int i = 0; i < dim; ++i) bestDimProcs[i] = dimProcs[i];
1871  }
1872  }
1873 
1874  }
1875 
1876  //returns min and max coordinates along each dimension
1877  void getMinMaxCoords(scalar_t *globalMaxCoords, scalar_t *globalMinCoords){
1878  scalar_t *maxCoords= new scalar_t [this->coordinate_dimension];
1879  scalar_t *minCoords= new scalar_t [this->coordinate_dimension];
1880  for (int dim = 0; dim < this->coordinate_dimension; ++dim){
1881  minCoords[dim] = maxCoords[dim] = this->coords[dim][0];
1882  for (lno_t i = 1; i < this->numLocalCoords; ++i){
1883  if (minCoords[dim] > this->coords[dim][i]){
1884  minCoords[dim] = this->coords[dim][i];
1885  }
1886 
1887  if (maxCoords[dim] < this->coords[dim][i]){
1888  maxCoords[dim] = this->coords[dim][i];
1889  }
1890  }
1891  }
1892 
1893  reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MAX,
1894  this->coordinate_dimension,
1895  maxCoords,
1896  globalMaxCoords);
1897 
1898 
1899  reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MIN,
1900  this->coordinate_dimension,
1901  minCoords,
1902  globalMinCoords);
1903 
1904  delete []maxCoords;
1905  delete []minCoords;
1906  }
1907 
1908 
1909  //performs a block partitioning.
1910  //then distributes the points of the overloaded parts to underloaded parts.
1911  void blockPartition(int *coordinate_grid_parts){
1912 
1913 #ifdef _MSC_VER
1914  typedef SSIZE_T ssize_t;
1915 #endif
1916 
1917  //############################################################//
1919  //############################################################//
1920 
1921  scalar_t *maxCoords= new scalar_t [this->coordinate_dimension];
1922  scalar_t *minCoords= new scalar_t [this->coordinate_dimension];
1923  //global min and max coordinates in each dimension.
1924  this->getMinMaxCoords(maxCoords, minCoords);
1925 
1926 
1927  //############################################################//
1929  //############################################################//
1930  int remaining = this->worldSize;
1931  int coord_dim = this->coordinate_dimension;
1932  int *dimProcs = new int[coord_dim];
1933  int *bestDimProcs = new int[coord_dim];
1934  int currentDim = 0;
1935 
1936  int bestSurface = 0;
1937  dimProcs[0] = remaining;
1938  for (int i = 1; i < coord_dim; ++i) dimProcs[i] = 1;
1939  for (int i = 0; i < coord_dim; ++i) bestSurface += dimProcs[i];
1940  for (int i = 0; i < coord_dim; ++i) bestDimProcs[i] = dimProcs[i];
1941  //divides the parts into dimensions as even as possible.
1942  getBestSurface ( remaining, dimProcs, coord_dim, currentDim, bestSurface, bestDimProcs);
1943 
1944 
1945  delete []dimProcs;
1946 
1947  //############################################################//
1949  //############################################################//
1950  int *shiftProcCount = new int[coord_dim];
1951  //how the consecutive parts along a dimension
1952  //differs in the index.
1953 
1954  int remainingProc = this->worldSize;
1955  for (int dim = 0; dim < coord_dim; ++dim){
1956  remainingProc = remainingProc / bestDimProcs[dim];
1957  shiftProcCount[dim] = remainingProc;
1958  }
1959 
1960  scalar_t *dim_slices = new scalar_t[coord_dim];
1961  for (int dim = 0; dim < coord_dim; ++dim){
1962  scalar_t dim_range = maxCoords[dim] - minCoords[dim];
1963  scalar_t slice = dim_range / bestDimProcs[dim];
1964  dim_slices[dim] = slice;
1965  }
1966 
1967  //############################################################//
1969  //############################################################//
1970 
1971  gno_t *numPointsInParts = new gno_t[this->worldSize];
1972  gno_t *numGlobalPointsInParts = new gno_t[this->worldSize];
1973  gno_t *numPointsInPartsInclusiveUptoMyIndex = new gno_t[this->worldSize];
1974 
1975  gno_t *partBegins = new gno_t [this->worldSize];
1976  gno_t *partNext = new gno_t[this->numLocalCoords];
1977 
1978 
1979  for (lno_t i = 0; i < this->numLocalCoords; ++i){
1980  partNext[i] = -1;
1981  }
1982  for (int i = 0; i < this->worldSize; ++i) {
1983  partBegins[i] = 1;
1984  }
1985 
1986  for (int i = 0; i < this->worldSize; ++i)
1987  numPointsInParts[i] = 0;
1988 
1989  for (lno_t i = 0; i < this->numLocalCoords; ++i){
1990  int partIndex = 0;
1991  for (int dim = 0; dim < coord_dim; ++dim){
1992  int shift = int ((this->coords[dim][i] - minCoords[dim]) / dim_slices[dim]);
1993  if (shift >= bestDimProcs[dim]){
1994  shift = bestDimProcs[dim] - 1;
1995  }
1996  shift = shift * shiftProcCount[dim];
1997  partIndex += shift;
1998  }
1999  numPointsInParts[partIndex] += 1;
2000  coordinate_grid_parts[i] = partIndex;
2001 
2002  partNext[i] = partBegins[partIndex];
2003  partBegins[partIndex] = i;
2004 
2005  }
2006 
2007  //############################################################//
2009  //############################################################//
2010  reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
2011  this->worldSize,
2012  numPointsInParts,
2013  numGlobalPointsInParts);
2014 
2015 
2016  Teuchos::scan<int,gno_t>(
2017  *(this->comm), Teuchos::REDUCE_SUM,
2018  this->worldSize,
2019  numPointsInParts,
2020  numPointsInPartsInclusiveUptoMyIndex
2021  );
2022 
2023 
2024 
2025 
2026  /*
2027  gno_t totalSize = 0;
2028  for (int i = 0; i < this->worldSize; ++i){
2029  totalSize += numPointsInParts[i];
2030  }
2031  if (totalSize != this->numLocalCoords){
2032  std::cout << "me:" << this->myRank << " ts:" << totalSize << " nl:" << this->numLocalCoords << std::endl;
2033  }
2034  */
2035 
2036 
2037  //std::cout << "me:" << this->myRank << " ilk print" << std::endl;
2038 
2039  gno_t optimal_num = gno_t(this->numGlobalCoords/double(this->worldSize)+0.5);
2040 #ifdef printparts
2041  if (this->myRank == 0){
2042  gno_t totalSize = 0;
2043  for (int i = 0; i < this->worldSize; ++i){
2044  std::cout << "me:" << this->myRank << " NumPoints in part:" << i << " is: " << numGlobalPointsInParts[i] << std::endl;
2045  totalSize += numGlobalPointsInParts[i];
2046  }
2047  std::cout << "Total:" << totalSize << " ng:" << this->numGlobalCoords << std::endl;
2048  std::cout << "optimal_num:" << optimal_num << std::endl;
2049  }
2050 #endif
2051  ssize_t *extraInPart = new ssize_t [this->worldSize];
2052 
2053  ssize_t extraExchange = 0;
2054  for (int i = 0; i < this->worldSize; ++i){
2055  extraInPart[i] = numGlobalPointsInParts[i] - optimal_num;
2056  extraExchange += extraInPart[i];
2057  }
2058  if (extraExchange != 0){
2059  int addition = -1;
2060  if (extraExchange < 0) addition = 1;
2061  for (ssize_t i = 0; i < extraExchange; ++i){
2062  extraInPart[i % this->worldSize] += addition;
2063  }
2064  }
2065 
2066  //############################################################//
2068  //############################################################//
2069 
2070  int overloadedPartCount = 0;
2071  int *overloadedPartIndices = new int [this->worldSize];
2072 
2073 
2074  int underloadedPartCount = 0;
2075  int *underloadedPartIndices = new int [this->worldSize];
2076 
2077  for (int i = 0; i < this->worldSize; ++i){
2078  if(extraInPart[i] > 0){
2079  overloadedPartIndices[overloadedPartCount++] = i;
2080  }
2081  else if(extraInPart[i] < 0){
2082  underloadedPartIndices[underloadedPartCount++] = i;
2083  }
2084  }
2085 
2086  int underloadpartindex = underloadedPartCount - 1;
2087 
2088 
2089  int numPartsISendFrom = 0;
2090  int *mySendFromParts = new int[this->worldSize * 2];
2091  gno_t *mySendFromPartsCounts = new gno_t[this->worldSize * 2];
2092 
2093  int numPartsISendTo = 0;
2094  int *mySendParts = new int[this->worldSize * 2];
2095  gno_t *mySendCountsToParts = new gno_t[this->worldSize * 2];
2096 
2097 
2098  //############################################################//
2103  //############################################################//
2104  for (int i = overloadedPartCount - 1; i >= 0; --i){
2105  //get the overloaded part
2106  //the overload
2107  int overloadPart = overloadedPartIndices[i];
2108  gno_t overload = extraInPart[overloadPart];
2109  gno_t myload = numPointsInParts[overloadPart];
2110 
2111 
2112  //the inclusive load of the processors up to me
2113  gno_t inclusiveLoadUpToMe = numPointsInPartsInclusiveUptoMyIndex[overloadPart];
2114 
2115  //the exclusive load of the processors up to me
2116  gno_t exclusiveLoadUptoMe = inclusiveLoadUpToMe - myload;
2117 
2118 
2119  if (exclusiveLoadUptoMe >= overload){
2120  //this processor does not have to convert anything.
2121  //for this overloaded part.
2122  //set the extra for this processor to zero.
2123  overloadedPartIndices[i] = -1;
2124  extraInPart[overloadPart] = 0;
2125  //then consume underloaded parts.
2126  while (overload > 0){
2127  int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2128  ssize_t underload = extraInPart[nextUnderLoadedPart];
2129  ssize_t left = overload + underload;
2130 
2131  if(left >= 0){
2132  extraInPart[nextUnderLoadedPart] = 0;
2133  underloadedPartIndices[underloadpartindex--] = -1;
2134  }
2135  else {
2136  extraInPart[nextUnderLoadedPart] = left;
2137  }
2138  overload = left;
2139  }
2140  }
2141  else if (exclusiveLoadUptoMe < overload){
2142  //if the previous processors load is not enough
2143  //then this processor should convert some of its elements.
2144  gno_t mySendCount = overload - exclusiveLoadUptoMe;
2145  //how much more needed.
2146  gno_t sendAfterMe = 0;
2147  //if my load is not enough
2148  //then the next processor will continue to convert.
2149  if (mySendCount > myload){
2150  sendAfterMe = mySendCount - myload;
2151  mySendCount = myload;
2152  }
2153 
2154 
2155  //this processors will convert from overloaded part
2156  //as many as mySendCount items.
2157  mySendFromParts[numPartsISendFrom] = overloadPart;
2158  mySendFromPartsCounts[numPartsISendFrom++] = mySendCount;
2159 
2160  //first consume underloaded parts for the previous processors.
2161  while (exclusiveLoadUptoMe > 0){
2162  int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2163  ssize_t underload = extraInPart[nextUnderLoadedPart];
2164  ssize_t left = exclusiveLoadUptoMe + underload;
2165 
2166  if(left >= 0){
2167  extraInPart[nextUnderLoadedPart] = 0;
2168  underloadedPartIndices[underloadpartindex--] = -1;
2169  }
2170  else {
2171  extraInPart[nextUnderLoadedPart] = left;
2172  }
2173  exclusiveLoadUptoMe = left;
2174  }
2175 
2176  //consume underloaded parts for my load.
2177  while (mySendCount > 0){
2178  int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2179  ssize_t underload = extraInPart[nextUnderLoadedPart];
2180  ssize_t left = mySendCount + underload;
2181 
2182  if(left >= 0){
2183  mySendParts[numPartsISendTo] = nextUnderLoadedPart;
2184  mySendCountsToParts[numPartsISendTo++] = -underload;
2185 
2186  extraInPart[nextUnderLoadedPart] = 0;
2187  underloadedPartIndices[underloadpartindex--] = -1;
2188  }
2189  else {
2190  extraInPart[nextUnderLoadedPart] = left;
2191 
2192  mySendParts[numPartsISendTo] = nextUnderLoadedPart;
2193  mySendCountsToParts[numPartsISendTo++] = mySendCount;
2194 
2195  }
2196  mySendCount = left;
2197  }
2198  //consume underloaded parts for the load of the processors after my index.
2199  while (sendAfterMe > 0){
2200  int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2201  ssize_t underload = extraInPart[nextUnderLoadedPart];
2202  ssize_t left = sendAfterMe + underload;
2203 
2204  if(left >= 0){
2205  extraInPart[nextUnderLoadedPart] = 0;
2206  underloadedPartIndices[underloadpartindex--] = -1;
2207  }
2208  else {
2209  extraInPart[nextUnderLoadedPart] = left;
2210  }
2211  sendAfterMe = left;
2212  }
2213  }
2214  }
2215 
2216 
2217  //############################################################//
2219  //############################################################//
2220  for (int i = 0 ; i < numPartsISendFrom; ++i){
2221 
2222  //get the part from which the elements will be converted.
2223  int sendFromPart = mySendFromParts[i];
2224  ssize_t sendCount = mySendFromPartsCounts[i];
2225  while(sendCount > 0){
2226  int partToSendIndex = numPartsISendTo - 1;
2227  int partToSend = mySendParts[partToSendIndex];
2228 
2229  int sendCountToThisPart = mySendCountsToParts[partToSendIndex];
2230 
2231  //determine which part i should convert to
2232  //and how many to this part.
2233  if (sendCountToThisPart <= sendCount){
2234  mySendParts[partToSendIndex] = 0;
2235  mySendCountsToParts[partToSendIndex] = 0;
2236  --numPartsISendTo;
2237  sendCount -= sendCountToThisPart;
2238  }
2239  else {
2240  mySendCountsToParts[partToSendIndex] = sendCountToThisPart - sendCount;
2241  sendCountToThisPart = sendCount;
2242  sendCount = 0;
2243  }
2244 
2245 
2246  gno_t toChange = partBegins[sendFromPart];
2247  gno_t previous_begin = partBegins[partToSend];
2248 
2249  //do the conversion.
2250  for (int k = 0; k < sendCountToThisPart - 1; ++k){
2251  coordinate_grid_parts[toChange] = partToSend;
2252  toChange = partNext[toChange];
2253  }
2254  coordinate_grid_parts[toChange] = partToSend;
2255 
2256  gno_t newBegin = partNext[toChange];
2257  partNext[toChange] = previous_begin;
2258  partBegins[partToSend] = partBegins[sendFromPart];
2259  partBegins[sendFromPart] = newBegin;
2260  }
2261  }
2262 
2263  //if (this->myRank == 0) std::cout << "4" << std::endl;
2264 
2265 #ifdef printparts
2266 
2267 
2268  for (int i = 0; i < this->worldSize; ++i) numPointsInParts[i] = 0;
2269 
2270  for (int i = 0; i < this->numLocalCoords; ++i){
2271  numPointsInParts[coordinate_grid_parts[i]] += 1;
2272  }
2273 
2274  reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
2275  this->worldSize,
2276  numPointsInParts,
2277  numGlobalPointsInParts);
2278  if (this->myRank == 0){
2279  std::cout << "reassigning" << std::endl;
2280  gno_t totalSize = 0;
2281  for (int i = 0; i < this->worldSize; ++i){
2282  std::cout << "me:" << this->myRank << " NumPoints in part:" << i << " is: " << numGlobalPointsInParts[i] << std::endl;
2283  totalSize += numGlobalPointsInParts[i];
2284  }
2285  std::cout << "Total:" << totalSize << " ng:" << this->numGlobalCoords << std::endl;
2286  }
2287 #endif
2288  delete []mySendCountsToParts;
2289  delete []mySendParts;
2290  delete []mySendFromPartsCounts;
2291  delete []mySendFromParts;
2292  delete []underloadedPartIndices;
2293  delete []overloadedPartIndices;
2294  delete []extraInPart;
2295  delete []partNext;
2296  delete []partBegins;
2297  delete []numPointsInPartsInclusiveUptoMyIndex;
2298  delete []numPointsInParts;
2299  delete []numGlobalPointsInParts;
2300 
2301  delete []shiftProcCount;
2302  delete []bestDimProcs;
2303  delete []dim_slices;
2304  delete []minCoords;
2305  delete []maxCoords;
2306  }
2307 
2308  //given the part numbers for each local coordinate,
2309  //distributes the coordinates to the corresponding processors.
2310  void distribute_points(int *coordinate_grid_parts){
2311 
2312  Tpetra::Distributor distributor(comm);
2313  ArrayView<const int> pIds( coordinate_grid_parts, this->numLocalCoords);
2314  gno_t numMyNewGnos = distributor.createFromSends(pIds);
2315 
2316 
2317  Kokkos::View<scalar_t*, Kokkos::HostSpace> recvBuf2(
2318  Kokkos::ViewAllocateWithoutInitializing("recvBuf2"),
2319  numMyNewGnos);
2320 
2321  for (int i = 0; i < this->coordinate_dimension; ++i){
2322  Kokkos::View<scalar_t*, Kokkos::HostSpace> s;
2323  if (this->numLocalCoords > 0)
2324  s = Kokkos::View<scalar_t *, Kokkos::HostSpace>(
2325  this->coords[i], this->numLocalCoords); //unmanaged
2326 
2327  distributor.doPostsAndWaits(s, 1, recvBuf2);
2328 
2329  delete [] this->coords[i];
2330  this->coords[i] = new scalar_t[numMyNewGnos];
2331  for (lno_t j = 0; j < numMyNewGnos; ++j){
2332  this->coords[i][j] = recvBuf2[j];
2333  }
2334 
2335  }
2336  this->numLocalCoords = numMyNewGnos;
2337  }
2338 
2339  //calls MJ for p = numProcs
2340  int predistributeMJ(int *coordinate_grid_parts){
2341  int coord_dim = this->coordinate_dimension;
2342 
2343  lno_t numLocalPoints = this->numLocalCoords;
2344  gno_t numGlobalPoints = this->numGlobalCoords;
2345 
2346 
2347  //T **weight = NULL;
2348  //typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> tMVector_t;
2349  RCP<Tpetra::Map<lno_t, gno_t, node_t> > mp = rcp(
2350  new Tpetra::Map<lno_t, gno_t, node_t> (numGlobalPoints, numLocalPoints, 0, comm));
2351 
2352  Teuchos::Array<Teuchos::ArrayView<const scalar_t> > coordView(coord_dim);
2353 
2354 
2355 
2356  for (int i=0; i < coord_dim; i++){
2357  if(numLocalPoints > 0){
2358  Teuchos::ArrayView<const scalar_t> a(coords[i], numLocalPoints);
2359  coordView[i] = a;
2360  } else{
2361  Teuchos::ArrayView<const scalar_t> a;
2362  coordView[i] = a;
2363  }
2364  }
2365 
2366  RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmVector = RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >(
2367  new Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t>( mp, coordView.view(0, coord_dim), coord_dim));
2368 
2369 
2370  RCP<const tMVector_t> coordsConst = Teuchos::rcp_const_cast<const tMVector_t>(tmVector);
2371  std::vector<const scalar_t *> weights;
2372  std::vector <int> stride;
2373 
2374  typedef Zoltan2::XpetraMultiVectorAdapter<tMVector_t> inputAdapter_t;
2375  //inputAdapter_t ia(coordsConst);
2376  inputAdapter_t ia(coordsConst,weights, stride);
2377 
2378  Teuchos::RCP <Teuchos::ParameterList> params ;
2379  params =RCP <Teuchos::ParameterList> (new Teuchos::ParameterList, true);
2380 
2381 
2382  params->set("algorithm", "multijagged");
2383  params->set("num_global_parts", this->worldSize);
2384 
2385  //TODO we need to fix the setting parts.
2386  //Although MJ sets the parts with
2387  //currently the part setting is not correct when migration is done.
2388  //params->set("migration_check_option", 2);
2389 
2390 
2392 
2393 
2394  try {
2395 #ifdef HAVE_ZOLTAN2_MPI
2396  problem = new Zoltan2::PartitioningProblem<inputAdapter_t>(&ia, params.getRawPtr(),
2397  MPI_COMM_WORLD);
2398 #else
2399  problem = new Zoltan2::PartitioningProblem<inputAdapter_t>(&ia, params.getRawPtr());
2400 #endif
2401  }
2402  CATCH_EXCEPTIONS("PartitioningProblem()")
2403 
2404  try {
2405  problem->solve();
2406  }
2407  CATCH_EXCEPTIONS("solve()")
2408 
2409  const typename inputAdapter_t::part_t *partIds = problem->getSolution().getPartListView();
2410 
2411  for (lno_t i = 0; i < this->numLocalCoords;++i){
2412  coordinate_grid_parts[i] = partIds[i];
2413  //std::cout << "me:" << this->myRank << " i:" << i << " goes to:" << partIds[i] << std::endl;
2414  }
2415  delete problem;
2416  return 0;
2417  }
2418 
2419  //calls RCP for p = numProcs
2420  int predistributeRCB(int *coordinate_grid_parts){
2421  int rank = this->myRank;
2422  int nprocs = this->worldSize;
2423  DOTS<tMVector_t> dots_;
2424 
2425  MEMORY_CHECK(rank==0 || rank==nprocs-1, "After initializing MPI");
2426 
2427 
2428  int nWeights = 0;
2429  int debugLevel=0;
2430  string memoryOn("memoryOn");
2431  string memoryOff("memoryOff");
2432  bool doMemory=false;
2433  int numGlobalParts = nprocs;
2434  int dummyTimer=0;
2435  bool remap=0;
2436 
2437  string balanceCount("balance_object_count");
2438  string balanceWeight("balance_object_weight");
2439  string mcnorm1("multicriteria_minimize_total_weight");
2440  string mcnorm2("multicriteria_balance_total_maximum");
2441  string mcnorm3("multicriteria_minimize_maximum_weight");
2442  string objective(balanceWeight); // default
2443 
2444  // Process command line input
2445  CommandLineProcessor commandLine(false, true);
2446  //commandLine.setOption("size", &numGlobalCoords,
2447  // "Approximate number of global coordinates.");
2448  int input_option = 0;
2449  commandLine.setOption("input_option", &input_option,
2450  "whether to use mesh creation, geometric generator, or file input");
2451  string inputFile = "";
2452 
2453  commandLine.setOption("input_file", &inputFile,
2454  "the input file for geometric generator or file input");
2455 
2456 
2457  commandLine.setOption("size", &numGlobalCoords,
2458  "Approximate number of global coordinates.");
2459  commandLine.setOption("numParts", &numGlobalParts,
2460  "Number of parts (default is one per proc).");
2461  commandLine.setOption("nWeights", &nWeights,
2462  "Number of weights per coordinate, zero implies uniform weights.");
2463  commandLine.setOption("debug", &debugLevel, "Zoltan1 debug level");
2464  commandLine.setOption("remap", "no-remap", &remap,
2465  "Zoltan1 REMAP parameter; disabled by default for scalability testing");
2466  commandLine.setOption("timers", &dummyTimer, "ignored");
2467  commandLine.setOption(memoryOn.c_str(), memoryOff.c_str(), &doMemory,
2468  "do memory profiling");
2469 
2470  string doc(balanceCount);
2471  doc.append(": ignore weights\n");
2472  doc.append(balanceWeight);
2473  doc.append(": balance on first weight\n");
2474  doc.append(mcnorm1);
2475  doc.append(": given multiple weights, balance their total.\n");
2476  doc.append(mcnorm3);
2477  doc.append(": given multiple weights, "
2478  "balance the maximum for each coordinate.\n");
2479  doc.append(mcnorm2);
2480  doc.append(": given multiple weights, balance the L2 norm of the weights.\n");
2481  commandLine.setOption("objective", &objective, doc.c_str());
2482 
2483  CommandLineProcessor::EParseCommandLineReturn rc =
2484  commandLine.parse(0, NULL);
2485 
2486 
2487 
2488  if (rc != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
2489  if (rc == Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED) {
2490  if (rank==0) std::cout << "PASS" << std::endl;
2491  return 1;
2492  }
2493  else {
2494  if (rank==0) std::cout << "FAIL" << std::endl;
2495  return 0;
2496  }
2497  }
2498 
2499  //MEMORY_CHECK(doMemory && rank==0, "After processing parameters");
2500 
2501  // Create the data structure
2502 
2503  int coord_dim = this->coordinate_dimension;
2504 
2505 
2506  RCP<Tpetra::Map<lno_t, gno_t, node_t> > mp = rcp(
2507  new Tpetra::Map<lno_t, gno_t, node_t> (this->numGlobalCoords, this->numLocalCoords, 0, this->comm));
2508 
2509  Teuchos::Array<Teuchos::ArrayView<const scalar_t> > coordView(coord_dim);
2510  for (int i=0; i < coord_dim; i++){
2511  if(numLocalCoords > 0){
2512  Teuchos::ArrayView<const scalar_t> a(coords[i], numLocalCoords);
2513  coordView[i] = a;
2514  } else{
2515  Teuchos::ArrayView<const scalar_t> a;
2516  coordView[i] = a;
2517  }
2518  }
2519 
2520  tMVector_t *tmVector = new tMVector_t( mp, coordView.view(0, coord_dim), coord_dim);
2521 
2522  dots_.coordinates = tmVector;
2523  dots_.weights.resize(nWeights);
2524 
2525 
2526  MEMORY_CHECK(doMemory && rank==0, "After creating input");
2527 
2528  // Now call Zoltan to partition the problem.
2529 
2530  float ver;
2531  int aok = Zoltan_Initialize(0,NULL, &ver);
2532 
2533  if (aok != 0){
2534  printf("Zoltan_Initialize failed\n");
2535  exit(0);
2536  }
2537 
2538  struct Zoltan_Struct *zz;
2539  zz = Zoltan_Create(MPI_COMM_WORLD);
2540 
2541  Zoltan_Set_Param(zz, "LB_METHOD", "RCB");
2542  Zoltan_Set_Param(zz, "LB_APPROACH", "PARTITION");
2543  Zoltan_Set_Param(zz, "CHECK_GEOM", "0");
2544  Zoltan_Set_Param(zz, "NUM_GID_ENTRIES", "1");
2545  Zoltan_Set_Param(zz, "NUM_LID_ENTRIES", "0");
2546  Zoltan_Set_Param(zz, "RETURN_LISTS", "PART");
2547  std::ostringstream oss;
2548  oss << numGlobalParts;
2549  Zoltan_Set_Param(zz, "NUM_GLOBAL_PARTS", oss.str().c_str());
2550  oss.str("");
2551  oss << debugLevel;
2552  Zoltan_Set_Param(zz, "DEBUG_LEVEL", oss.str().c_str());
2553 
2554  if (remap)
2555  Zoltan_Set_Param(zz, "REMAP", "1");
2556  else
2557  Zoltan_Set_Param(zz, "REMAP", "0");
2558 
2559  if (objective != balanceCount){
2560  oss.str("");
2561  oss << nWeights;
2562  Zoltan_Set_Param(zz, "OBJ_WEIGHT_DIM", oss.str().c_str());
2563 
2564  if (objective == mcnorm1)
2565  Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "1");
2566  else if (objective == mcnorm2)
2567  Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "2");
2568  else if (objective == mcnorm3)
2569  Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "3");
2570  }
2571  else{
2572  Zoltan_Set_Param(zz, "OBJ_WEIGHT_DIM", "0");
2573  }
2574 
2575  Zoltan_Set_Num_Obj_Fn(zz, getNumObj<tMVector_t>, &dots_);
2576  Zoltan_Set_Obj_List_Fn(zz, getObjList<tMVector_t>, &dots_);
2577  Zoltan_Set_Num_Geom_Fn(zz, getDim<tMVector_t>, &dots_);
2578  Zoltan_Set_Geom_Multi_Fn(zz, getCoords<tMVector_t>, &dots_);
2579 
2580  int changes, numGidEntries, numLidEntries, numImport, numExport;
2581  ZOLTAN_ID_PTR importGlobalGids, importLocalGids;
2582  ZOLTAN_ID_PTR exportGlobalGids, exportLocalGids;
2583  int *importProcs, *importToPart, *exportProcs, *exportToPart;
2584 
2585  MEMORY_CHECK(doMemory && rank==0, "Before Zoltan_LB_Partition");
2586 
2587 
2588  aok = Zoltan_LB_Partition(zz, &changes, &numGidEntries, &numLidEntries,
2589  &numImport, &importGlobalGids, &importLocalGids,
2590  &importProcs, &importToPart,
2591  &numExport, &exportGlobalGids, &exportLocalGids,
2592  &exportProcs, &exportToPart);
2593 
2594 
2595  MEMORY_CHECK(doMemory && rank==0, "After Zoltan_LB_Partition");
2596 
2597  for (lno_t i = 0; i < numLocalCoords; i++)
2598  coordinate_grid_parts[i] = exportToPart[i];
2599  Zoltan_Destroy(&zz);
2600  MEMORY_CHECK(doMemory && rank==0, "After Zoltan_Destroy");
2601 
2602  delete dots_.coordinates;
2603  return 0;
2604 }
2606  int *coordinate_grid_parts = new int[this->numLocalCoords];
2607  switch (this->predistribution){
2608  case 1:
2609  this->predistributeRCB(coordinate_grid_parts);
2610  break;
2611  case 2:
2612 
2613  this->predistributeMJ(coordinate_grid_parts);
2614  break;
2615  case 3:
2616  //block
2617  blockPartition(coordinate_grid_parts);
2618  break;
2619  }
2620  this->distribute_points(coordinate_grid_parts);
2621 
2622  delete []coordinate_grid_parts;
2623 
2624 
2625  }
2626 
2627  //############################################################//
2629  //############################################################//
2630 
2631 
2633  return this->numWeightsPerCoord;
2634  }
2636  return this->coordinate_dimension;
2637  }
2639  return this->numLocalCoords;
2640  }
2642  return this->numGlobalCoords;
2643  }
2644 
2646  return this->coords;
2647  }
2648 
2649  scalar_t **getLocalWeightsView(){
2650  return this->wghts;
2651  }
2652 
2653  void getLocalCoordinatesCopy( scalar_t ** c){
2654  for(int ii = 0; ii < this->coordinate_dimension; ++ii){
2655 #ifdef HAVE_ZOLTAN2_OMP
2656 #pragma omp parallel for
2657 #endif
2658  for (lno_t i = 0; i < this->numLocalCoords; ++i){
2659  c[ii][i] = this->coords[ii][i];
2660  }
2661  }
2662  }
2663 
2664  void getLocalWeightsCopy(scalar_t **w){
2665  for(int ii = 0; ii < this->numWeightsPerCoord; ++ii){
2666 #ifdef HAVE_ZOLTAN2_OMP
2667 #pragma omp parallel for
2668 #endif
2669  for (lno_t i = 0; i < this->numLocalCoords; ++i){
2670  w[ii][i] = this->wghts[ii][i];
2671  }
2672  }
2673  }
2674 };
2675 }
2676 
2677 #endif /* GEOMETRICGENERATOR */
virtual bool isInArea(CoordinatePoint< T > dot)=0
RectangleHole(CoordinatePoint< T > center_, T edge_x_, T edge_y_)
virtual weighttype get1DWeight(T x)
virtual bool isInArea(CoordinatePoint< T > dot)
#define INVALID(STR)
void getCoords(void *data, int numGid, int numLid, int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int dim, double *coords_, int *ierr)
CoordinateGridDistribution(gno_t alongX, gno_t alongY, gno_t alongZ, int dim, T l_x, T r_x, T l_y, T r_y, T l_z, T r_z, int myRank_, int wSize)
virtual weighttype get1DWeight(T x)=0
std::vector< std::vector< float > > weights
static ArrayRCP< ArrayRCP< zscalar_t > > weights
void GetPoints(lno_t requestedPointcount, CoordinatePoint< T > *points, Hole< T > **holes, lno_t holeCount, float *sharedRatios_, int myRank)
virtual weighttype getWeight(CoordinatePoint< T > P)=0
virtual bool isInArea(CoordinatePoint< T > dot)
virtual bool isInArea(CoordinatePoint< T > dot)
int predistributeRCB(int *coordinate_grid_parts)
virtual CoordinatePoint< T > getPoint(gno_t pindex, unsigned int &state)
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
virtual weighttype get2DWeight(T x, T y)
void GetPoints(lno_t requestedPointcount, T **coords, lno_t tindex, Hole< T > **holes, lno_t holeCount, float *sharedRatios_, int myRank)
Hole(CoordinatePoint< T > center_, T edge1_, T edge2_, T edge3_)
CoordinateUniformDistribution(gno_t np_, int dim, T l_x, T r_x, T l_y, T r_y, T l_z, T r_z, int wSize)
SphereHole(CoordinatePoint< T > center_, T edge_)
CircleHole(CoordinatePoint< T > center_, T edge_)
Defines the PartitioningSolution class.
void perturb_data(float used_perturbation_ratio, int scale)
Start perturbation function##########################//
virtual weighttype get3DWeight(T x, T y, T z)
virtual weighttype get3DWeight(T x, T y, T z)=0
Defines the XpetraMultiVectorAdapter.
void blockPartition(int *coordinate_grid_parts)
RectangularPrismHole(CoordinatePoint< T > center_, T edge_x_, T edge_y_, T edge_z_)
SparseMatrixAdapter_t::part_t part_t
CoordinateNormalDistribution(gno_t np_, int dim, CoordinatePoint< T > center_, T sd_x, T sd_y, T sd_z, int wSize)
virtual bool isInArea(CoordinatePoint< T > dot)
#define epsilon
Definition: nd.cpp:47
virtual bool isInArea(CoordinatePoint< T > dot)
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_)
int getNumObj(void *data, int *ierr)
const std::string shapes[]
virtual weighttype getWeight(CoordinatePoint< T > p)
int getDim(void *data, int *ierr)
void getObjList(void *data, int numGid, int numLid, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int num_wgts, float *obj_wgts, int *ierr)
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
const std::string weight_distribution_string
virtual CoordinatePoint< T > getPoint(gno_t pindex, unsigned int &state)
virtual weighttype get2DWeight(T x, T y)=0
An adapter for Xpetra::MultiVector.
void getBestSurface(int remaining, int *dimProcs, int dim, int currentDim, int &bestSurface, int *bestDimProcs)
Start Predistribution functions######################//
Expression is a generic following method.
virtual CoordinatePoint< T > getPoint(gno_t point_index, unsigned int &state)=0
void distribute_points(int *coordinate_grid_parts)
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
PartitioningProblem sets up partitioning problems for the user.
#define MAX_ITER_ALLOWED
GeometricGenerator(Teuchos::ParameterList &params, const RCP< const Teuchos::Comm< int > > &comm_)
int getNumWeights()
##END Predistribution functions######################//
CoordinatePoint< T > center
#define INVALID_SHAPE_ARG(SHAPE, REQUIRED)
#define INVALIDSHAPE(STR, DIM)
#define CATCH_EXCEPTIONS(pp)
Defines the PartitioningProblem class.
CoordinateDistribution(gno_t np_, int dim, int wSize)
int predistributeMJ(int *coordinate_grid_parts)
SquareHole(CoordinatePoint< T > center_, T edge_)
Tpetra::MultiVector< zscalar_t, zlno_t, zgno_t, znode_t > tMVector_t
void solve(bool updateInputData=true)
Direct the problem to create a solution.
virtual CoordinatePoint< T > getPoint(gno_t pindex, unsigned int &state)
CubeHole(CoordinatePoint< T > center_, T edge_)
#define MAX_WEIGHT_DIM
virtual bool isInArea(CoordinatePoint< T > dot)
void getMinMaxCoords(scalar_t *globalMaxCoords, scalar_t *globalMinCoords)
#define MEMORY_CHECK(iPrint, msg)