Zoltan2
Loading...
Searching...
No Matches
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
41using Teuchos::CommandLineProcessor;
42using Teuchos::ArrayView;
43using std::string;
44using Teuchos::ArrayRCP;
45
46namespace 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
72template <typename tMVector_t>
73class DOTS{
74public:
75 std::vector<std::vector<float> > weights;
77};
78
79template <typename tMVector_t>
80int getNumObj(void *data, int *ierr)
81{
82 *ierr = 0;
83 DOTS<tMVector_t> *dots_ = (DOTS<tMVector_t> *) data;
84 return dots_->coordinates->getLocalLength();
85}
87template <typename tMVector_t>
88void 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
121template <typename tMVector_t>
122int 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
132template <typename tMVector_t>
133void 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
162const std::string shapes[] = {"SQUARE", "RECTANGLE", "CIRCLE", "CUBE", "RECTANGULAR_PRISM", "SPHERE"};
163#define SHAPE_COUNT 6
164
166const 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
177const std::string weight_distribution_string = "WeightDistribution-";
178
179template <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
212template <typename T>
213class Hole{
214public:
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
229template <typename T>
230class SquareHole:public Hole<T>{
231public:
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
239template <typename T>
240class RectangleHole:public Hole<T>{
241public:
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
249template <typename T>
250class CircleHole:public Hole<T>{
251public:
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
259template <typename T>
260class CubeHole:public Hole<T>{
261public:
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
269template <typename T>
271public:
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
279template <typename T>
280class SphereHole:public Hole<T>{
281public:
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
293template <typename T, typename weighttype>
295public:
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;
302};
303
322template <typename T, typename weighttype>
323class 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;
332public:
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
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
435template <typename T, typename lno_t, typename gno_t>
437public:
444
445 CoordinateDistribution(gno_t np_, int dim, int wSize) :
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
609template <typename T, typename lno_t, typename gno_t>
611public:
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.
638 CoordinatePoint <T> p;
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
659private:
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
673template <typename T, typename lno_t, typename gno_t>
675public:
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.
703 CoordinatePoint <T> p;
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
722private:
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
730template <typename T, typename lno_t, typename gno_t>
732public:
740 //T currentX, currentY, currentZ;
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
798 CoordinatePoint <T> p;
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
852private:
853
854};
855
856template <typename scalar_t, typename lno_t, typename gno_t, typename node_t>
858private:
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 }
1490public:
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
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 */
#define INVALID_SHAPE_ARG(SHAPE, REQUIRED)
#define MAX_ITER_ALLOWED
#define INVALIDSHAPE(STR, DIM)
#define INVALID(STR)
#define CATCH_EXCEPTIONS(pp)
#define MAX_WEIGHT_DIM
Defines the PartitioningProblem class.
Defines the PartitioningSolution class.
#define MEMORY_CHECK(iPrint, msg)
Defines the XpetraMultiVectorAdapter.
virtual bool isInArea(CoordinatePoint< T > dot)
CircleHole(CoordinatePoint< T > center_, T edge_)
CoordinateDistribution(gno_t np_, int dim, int wSize)
void GetPoints(lno_t requestedPointcount, T **coords, lno_t tindex, Hole< T > **holes, lno_t holeCount, float *sharedRatios_, int myRank)
void GetPoints(lno_t requestedPointcount, CoordinatePoint< T > *points, Hole< T > **holes, lno_t holeCount, float *sharedRatios_, int myRank)
virtual CoordinatePoint< T > getPoint(gno_t point_index, unsigned int &state)=0
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 CoordinatePoint< T > getPoint(gno_t pindex, unsigned int &state)
CoordinateNormalDistribution(gno_t np_, int dim, CoordinatePoint< T > center_, T sd_x, T sd_y, T sd_z, int wSize)
virtual CoordinatePoint< T > getPoint(gno_t pindex, unsigned int &state)
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)
virtual CoordinatePoint< T > getPoint(gno_t pindex, unsigned int &state)
CubeHole(CoordinatePoint< T > center_, T edge_)
virtual bool isInArea(CoordinatePoint< T > dot)
std::vector< std::vector< float > > weights
int predistributeMJ(int *coordinate_grid_parts)
void distribute_points(int *coordinate_grid_parts)
int predistributeRCB(int *coordinate_grid_parts)
void perturb_data(float used_perturbation_ratio, int scale)
void getBestSurface(int remaining, int *dimProcs, int dim, int currentDim, int &bestSurface, int *bestDimProcs)
GeometricGenerator(Teuchos::ParameterList &params, const RCP< const Teuchos::Comm< int > > &comm_)
void getMinMaxCoords(scalar_t *globalMaxCoords, scalar_t *globalMinCoords)
void blockPartition(int *coordinate_grid_parts)
virtual bool isInArea(CoordinatePoint< T > dot)=0
CoordinatePoint< T > center
Hole(CoordinatePoint< T > center_, T edge1_, T edge2_, T edge3_)
virtual bool isInArea(CoordinatePoint< T > dot)
RectangleHole(CoordinatePoint< T > center_, T edge_x_, T edge_y_)
RectangularPrismHole(CoordinatePoint< T > center_, T edge_x_, T edge_y_, T edge_z_)
virtual bool isInArea(CoordinatePoint< T > dot)
virtual bool isInArea(CoordinatePoint< T > dot)
SphereHole(CoordinatePoint< T > center_, T edge_)
SquareHole(CoordinatePoint< T > center_, T edge_)
virtual bool isInArea(CoordinatePoint< T > dot)
Expression is a generic following method.
virtual weighttype get1DWeight(T x)
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_)
virtual weighttype get2DWeight(T x, T y)
virtual weighttype getWeight(CoordinatePoint< T > p)
virtual weighttype get3DWeight(T x, T y, T z)
virtual weighttype getWeight(CoordinatePoint< T > P)=0
virtual weighttype get1DWeight(T x)=0
virtual weighttype get2DWeight(T x, T y)=0
virtual weighttype get3DWeight(T x, T y, T z)=0
PartitioningProblem sets up partitioning problems for the user.
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
void solve(bool updateInputData=true)
Direct the problem to create a solution.
map_t::local_ordinal_type lno_t
map_t::global_ordinal_type gno_t
const std::string shapes[]
void getCoords(void *data, int numGid, int numLid, int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int dim, double *coords_, 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)
int getDim(void *data, int *ierr)
int getNumObj(void *data, int *ierr)
const std::string weight_distribution_string
static ArrayRCP< ArrayRCP< zscalar_t > > weights
Tpetra::MultiVector< zscalar_t, zlno_t, zgno_t, znode_t > tMVector_t