45 #ifndef GEOMETRICGENERATOR
46 #define GEOMETRICGENERATOR
48 #include <Teuchos_Comm.hpp>
49 #include <Teuchos_ParameterList.hpp>
50 #include <Teuchos_FilteredIterator.hpp>
51 #include <Teuchos_ParameterEntry.hpp>
60 #include <Tpetra_MultiVector_decl.hpp>
63 #include <Teuchos_ArrayViewDecl.hpp>
64 #include <Teuchos_RCP.hpp>
65 #include <Tpetra_Distributor.hpp>
76 using Teuchos::CommandLineProcessor;
77 using Teuchos::ArrayView;
79 using Teuchos::ArrayRCP;
81 namespace GeometricGen{
82 #define CATCH_EXCEPTIONS(pp) \
83 catch (std::runtime_error &e) { \
84 std::cout << "Runtime exception returned from " << pp << ": " \
85 << e.what() << " FAIL" << std::endl; \
88 catch (std::logic_error &e) { \
89 std::cout << "Logic exception returned from " << pp << ": " \
90 << e.what() << " FAIL" << std::endl; \
93 catch (std::bad_alloc &e) { \
94 std::cout << "Bad_alloc exception returned from " << pp << ": " \
95 << e.what() << " FAIL" << std::endl; \
98 catch (std::exception &e) { \
99 std::cout << "Unknown exception returned from " << pp << ": " \
100 << e.what() << " FAIL" << std::endl; \
107 template <
typename tMVector_t>
114 template <
typename tMVector_t>
122 template <
typename tMVector_t>
124 int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
125 int dim,
double *coords_,
int *ierr)
127 typedef typename tMVector_t::scalar_type scalar_t;
133 double *val = coords_;
134 const scalar_t *x = dots_->
coordinates->getData(0).getRawPtr();
135 const scalar_t *y = dots_->
coordinates->getData(1).getRawPtr();
136 const scalar_t *z = dots_->
coordinates->getData(2).getRawPtr();
137 for (
int i=0; i < numObj; i++){
138 *val++ =
static_cast<double>(x[i]);
139 *val++ =
static_cast<double>(y[i]);
140 *val++ =
static_cast<double>(z[i]);
146 double *val = coords_;
147 const scalar_t *x = dots_->
coordinates->getData(0).getRawPtr();
148 const scalar_t *y = dots_->
coordinates->getData(1).getRawPtr();
149 for (
int i=0; i < numObj; i++){
150 *val++ =
static_cast<double>(x[i]);
151 *val++ =
static_cast<double>(y[i]);
156 template <
typename tMVector_t>
167 template <
typename tMVector_t>
169 ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
170 int num_wgts,
float *obj_wgts,
int *ierr)
172 typedef typename tMVector_t::global_ordinal_type gno_t;
177 size_t localLen = dots_->
coordinates->getLocalLength();
179 dots_->
coordinates->getMap()->getNodeElementList().getRawPtr();
181 if (
sizeof(ZOLTAN_ID_TYPE) ==
sizeof(gno_t))
182 memcpy(gids, ids,
sizeof(ZOLTAN_ID_TYPE) * localLen);
184 for (
size_t i=0; i < localLen; i++)
185 gids[i] = static_cast<ZOLTAN_ID_TYPE>(ids[i]);
188 float *wgts = obj_wgts;
189 for (
size_t i=0; i < localLen; i++)
190 for (
int w=0; w < num_wgts; w++)
191 *wgts++ = dots_->
weights[w][i];
197 const std::string
shapes[] = {
"SQUARE",
"RECTANGLE",
"CIRCLE",
"CUBE",
"RECTANGULAR_PRISM",
"SPHERE"};
198 #define SHAPE_COUNT 6
202 #define DISTRIBUTION_COUNT 2
204 #define HOLE_ALLOC_STEP 10
205 #define MAX_WEIGHT_DIM 10
206 #define INVALID(STR) "Invalid argument at " + STR
207 #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"
209 #define INVALID_SHAPE_ARG(SHAPE, REQUIRED) "Invalid argument count for shape " + SHAPE + ". Requires " + REQUIRED + " argument(s)."
210 #define MAX_ITER_ALLOWED 500
214 template <
typename T>
247 template <
typename T>
256 this->
edge1 = edge1_;
257 this->
edge2 = edge2_;
258 this->
edge3 = edge3_;
264 template <
typename T>
270 return fabs(dot.
x - this->center.x) < this->
edge1 / 2 && fabs(dot.
y - this->center.y) < this->
edge1 / 2;
274 template <
typename T>
279 return fabs(dot.
x - this->center.x) < this->
edge1 / 2 && fabs(dot.
y - this->center.y) < this->
edge2 / 2;
284 template <
typename T>
290 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;
294 template <
typename T>
300 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;
304 template <
typename T>
310 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;
314 template <
typename T>
320 return fabs((dot.
x - this->center.x) * (dot.
x - this->center.x) * (dot.
x - this->center.x)) +
321 fabs((dot.
y - this->center.y) * (dot.
y - this->center.y) * (dot.
y - this->center.y)) +
322 fabs((dot.
z - this->center.z) * (dot.
z - this->center.z) * (dot.
z - this->center.z))
328 template <
typename T,
typename weighttype>
357 template <
typename T,
typename weighttype>
368 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>(){
381 this->stepCount = stepCount_;
382 if(this->stepCount > 0){
383 this->steps =
new T[this->stepCount];
384 this->values =
new T[this->stepCount + 1];
386 for (
int i = 0; i < this->stepCount; ++i){
387 this->steps[i] = steps_[i];
388 this->values[i] = values_[i];
390 this->values[this->stepCount] = values_[this->stepCount];
396 if(this->stepCount > 0){
397 delete [] this->steps;
398 delete [] this->values;
404 T expressionRes = this->a1 * pow( (x - this->x1), b1) + c;
405 if(this->stepCount > 0){
406 for (
int i = 0; i < this->stepCount; ++i){
407 if (expressionRes < this->steps[i])
return this->values[i];
409 return this->values[this->stepCount];
412 return weighttype(expressionRes);
417 T expressionRes = this->a1 * pow( (x - this->x1), b1) + this->a2 * pow( (y - this->y1), b2) + c;
418 if(this->stepCount > 0){
419 for (
int i = 0; i < this->stepCount; ++i){
420 if (expressionRes < this->steps[i])
return this->values[i];
422 return this->values[this->stepCount];
425 return weighttype(expressionRes);
430 std::cout << this->a1 <<
"*" <<
"math.pow( (" << x <<
"- " << this->x1 <<
" ), " << b1 <<
")" <<
"+" << this->a2<<
"*"<<
"math.pow( (" << y <<
"-" << this->y1 <<
"), " <<
431 b2 <<
" ) + " << this->a3 <<
" * math.pow( (" << z <<
"-" << this->z1 <<
"), " << b3 <<
")+ " << c <<
" == " <<
432 this->a1 * pow( (x - this->x1), b1) + this->a2 * pow( (y - this->y1), b2) + this->a3 * pow( (z - this->z1), b3) + c << std::endl;
437 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;
440 if(this->stepCount > 0){
441 for (
int i = 0; i < this->stepCount; ++i){
442 if (expressionRes < this->steps[i]) {
444 return this->values[i];
449 return this->values[this->stepCount];
452 return weighttype(expressionRes);
457 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);
458 if(this->stepCount > 0){
459 for (
int i = 0; i < this->stepCount; ++i){
460 if (expressionRes < this->steps[i])
return this->values[i];
462 return this->values[this->stepCount];
465 return weighttype(expressionRes);
470 template <
typename T,
typename lno_t,
typename gno_t>
489 Hole<T> **holes, lno_t holeCount,
490 float *sharedRatios_,
int myRank){
492 for (
int i = 0; i < myRank; ++i){
495 if (i < this->numPoints % this->
worldSize){
502 unsigned int slice = UINT_MAX/(this->
worldSize);
503 unsigned int stateBegin = myRank * slice;
508 #ifdef HAVE_ZOLTAN2_OMP
514 #ifdef HAVE_ZOLTAN2_OMP
515 me = omp_get_thread_num();
516 tsize = omp_get_num_threads();
518 unsigned int state = stateBegin + me * slice/(tsize);
520 #ifdef HAVE_ZOLTAN2_OMP
523 for(lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
527 throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
531 bool isInHole =
false;
532 for(lno_t i = 0; i < holeCount; ++i){
533 if(holes[i][0].isInArea(p)){
538 if(isInHole)
continue;
577 void GetPoints(lno_t requestedPointcount, T **coords, lno_t tindex,
578 Hole<T> **holes, lno_t holeCount,
579 float *sharedRatios_,
int myRank){
581 for (
int i = 0; i < myRank; ++i){
584 if (gno_t(i) < this->numPoints % this->
worldSize){
591 unsigned int slice = UINT_MAX/(this->
worldSize);
592 unsigned int stateBegin = myRank * slice;
593 #ifdef HAVE_ZOLTAN2_OMP
599 #ifdef HAVE_ZOLTAN2_OMP
600 me = omp_get_thread_num();
601 tsize = omp_get_num_threads();
603 unsigned int state = stateBegin + me * (slice/(tsize));
611 #ifdef HAVE_ZOLTAN2_OMP
614 for(lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
618 throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
622 bool isInHole =
false;
623 for(lno_t i = 0; i < holeCount; ++i){
624 if(holes[i][0].isInArea(p)){
629 if(isInHole)
continue;
630 coords[0][cnt + tindex] = p.
x;
632 coords[1][cnt + tindex] = p.
y;
634 coords[2][cnt + tindex] = p.
z;
644 template <
typename T,
typename lno_t,
typename gno_t>
661 T sd_x, T sd_y, T sd_z,
int wSize) :
675 for(
int i = 0; i < this->
dimension; ++i){
678 p.
x = normalDist(this->
center.x, this->standartDevx, state);
681 p.
y = normalDist(this->
center.y, this->standartDevy, state);
684 p.
z = normalDist(this->
center.z, this->standartDevz, state);
687 throw "unsupported dimension";
695 T normalDist(T center_, T sd,
unsigned int &state) {
696 static bool derived=
false;
697 static T storedDerivation;
698 T polarsqrt, normalsquared, normal1, normal2;
701 normal1=2.0*( T(rand_r(&state))/T(RAND_MAX) ) - 1.0;
702 normal2=2.0*( T(rand_r(&state))/T(RAND_MAX) ) - 1.0;
703 normalsquared=normal1*normal1+normal2*normal2;
704 }
while ( normalsquared>=1.0 || normalsquared == 0.0);
706 polarsqrt=sqrt(-2.0*log(normalsquared)/normalsquared);
707 storedDerivation=normal1*polarsqrt;
709 return normal2*polarsqrt*sd + center_;
713 return storedDerivation*sd + center_;
718 template <
typename T,
typename lno_t,
typename gno_t>
738 T l_z, T r_z,
int wSize ) :
749 for(
int i = 0; i < this->
dimension; ++i){
761 throw "unsupported dimension";
769 T uniformDist(T a, T b,
unsigned int &state)
771 return (b-a)*(rand_r(&state) / double(RAND_MAX)) + a;
775 template <
typename T,
typename lno_t,
typename gno_t>
800 T l_x, T r_x, T l_y, T r_y, T l_z, T r_z ,
801 int myRank_,
int wSize) :
901 template <
typename scalar_t,
typename lno_t,
typename gno_t,
typename node_t>
906 int coordinate_dimension;
907 gno_t numGlobalCoords;
908 lno_t numLocalCoords;
909 float *loadDistributions;
911 bool distinctCoordSet;
913 int distributionCount;
918 int numWeightsPerCoord;
920 RCP<const Teuchos::Comm<int> > comm;
932 float perturbation_ratio;
934 typedef Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> tMVector_t;
935 typedef Tpetra::Map<lno_t, gno_t, node_t> tMap_t;
938 template <
typename tt>
939 tt getParamVal(
const Teuchos::ParameterEntry& pe,
const std::string ¶mname){
942 returnVal = Teuchos::getValue<tt>(pe);
950 int countChar (std::string inStr,
char cntChar){
952 for (
unsigned int i = 0; i < inStr.size(); ++i){
953 if (inStr[i] == cntChar) {
960 template <
typename tt>
961 tt fromString(std::string obj){
962 std::stringstream ss (std::stringstream::in | std::stringstream::out);
967 throw "Cannot convert string " + obj;
973 void splitString(std::string inStr,
char splitChar, std::string *outSplittedStr){
974 std::stringstream ss (std::stringstream::in | std::stringstream::out);
978 std::string tmp =
"";
979 std::getline(ss, tmp ,splitChar);
980 outSplittedStr[cnt++] = tmp;
1017 void getCoordinateDistributions(std::string coordinate_distributions){
1018 if(coordinate_distributions ==
""){
1019 throw "At least one distribution function must be provided to coordinate generator.";
1022 int argCnt = this->countChar(coordinate_distributions,
',') + 1;
1023 std::string *splittedStr =
new std::string[argCnt];
1024 splitString(coordinate_distributions,
',', splittedStr);
1026 for(
int i = 0; i < argCnt; ){
1029 std::string distName = splittedStr[i++];
1031 if(distName ==
"NORMAL"){
1033 if (this->coordinate_dimension == 3){
1036 if(i + reqArg > argCnt) {
1037 std::string tmp = Teuchos::toString<int>(reqArg);
1040 np_ = fromString<gno_t>(splittedStr[i++]);
1043 pp.
x = fromString<scalar_t>(splittedStr[i++]);
1044 pp.y = fromString<scalar_t>(splittedStr[i++]);
1046 if(this->coordinate_dimension == 3){
1047 pp.z = fromString<scalar_t>(splittedStr[i++]);
1050 scalar_t sd_x = fromString<scalar_t>(splittedStr[i++]);
1051 scalar_t sd_y = fromString<scalar_t>(splittedStr[i++]);
1053 if(this->coordinate_dimension == 3){
1054 sd_z = fromString<scalar_t>(splittedStr[i++]);
1058 }
else if(distName ==
"UNIFORM" ){
1060 if (this->coordinate_dimension == 3){
1063 if(i + reqArg > argCnt) {
1064 std::string tmp = Teuchos::toString<int>(reqArg);
1067 np_ = fromString<gno_t>(splittedStr[i++]);
1068 scalar_t l_x = fromString<scalar_t>(splittedStr[i++]);
1069 scalar_t r_x = fromString<scalar_t>(splittedStr[i++]);
1070 scalar_t l_y = fromString<scalar_t>(splittedStr[i++]);
1071 scalar_t r_y = fromString<scalar_t>(splittedStr[i++]);
1073 scalar_t l_z = 0, r_z = 0;
1075 if(this->coordinate_dimension == 3){
1076 l_z = fromString<scalar_t>(splittedStr[i++]);
1077 r_z = fromString<scalar_t>(splittedStr[i++]);
1080 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 );
1081 }
else if (distName ==
"GRID"){
1083 if(this->coordinate_dimension == 3){
1086 if(i + reqArg > argCnt) {
1087 std::string tmp = Teuchos::toString<int>(reqArg);
1091 gno_t np_x = fromString<gno_t>(splittedStr[i++]);
1092 gno_t np_y = fromString<gno_t>(splittedStr[i++]);
1096 if(this->coordinate_dimension == 3){
1097 np_z = fromString<gno_t>(splittedStr[i++]);
1100 np_ = np_x * np_y * np_z;
1101 scalar_t l_x = fromString<scalar_t>(splittedStr[i++]);
1102 scalar_t r_x = fromString<scalar_t>(splittedStr[i++]);
1103 scalar_t l_y = fromString<scalar_t>(splittedStr[i++]);
1104 scalar_t r_y = fromString<scalar_t>(splittedStr[i++]);
1106 scalar_t l_z = 0, r_z = 0;
1108 if(this->coordinate_dimension == 3){
1109 l_z = fromString<scalar_t>(splittedStr[i++]);
1110 r_z = fromString<scalar_t>(splittedStr[i++]);
1113 if(np_x < 1 || np_z < 1 || np_y < 1 ){
1114 throw "Provide at least 1 point along each dimension for grid test.";
1118 (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);
1122 std::string tmp = Teuchos::toString<int>(this->coordinate_dimension);
1125 this->numGlobalCoords += (gno_t) np_;
1127 delete []splittedStr;
1130 void getProcLoadDistributions(std::string proc_load_distributions){
1132 this->loadDistributions =
new float[this->worldSize];
1133 if(proc_load_distributions ==
""){
1134 float r = 1.0 / this->worldSize;
1135 for(
int i = 0; i < this->worldSize; ++i){
1136 this->loadDistributions[i] = r;
1141 int argCnt = this->countChar(proc_load_distributions,
',') + 1;
1142 if(argCnt != this->worldSize) {
1143 throw "Invalid parameter count load distributions. Given " + Teuchos::toString<int>(argCnt) +
" processor size is " + Teuchos::toString<int>(this->worldSize);
1145 std::string *splittedStr =
new std::string[argCnt];
1146 splitString(proc_load_distributions,
',', splittedStr);
1147 for(
int i = 0; i < argCnt; ++i){
1148 this->loadDistributions[i] = fromString<float>(splittedStr[i]);
1150 delete []splittedStr;
1154 for(
int i = 0; i < this->worldSize; ++i){
1155 sum += this->loadDistributions[i];
1158 throw "Processor load ratios do not sum to 1.0.";
1164 void getHoles(std::string holeDescription){
1165 if(holeDescription ==
""){
1169 int argCnt = this->countChar(holeDescription,
',') + 1;
1170 std::string *splittedStr =
new std::string[argCnt];
1171 splitString(holeDescription,
',', splittedStr);
1173 for(
int i = 0; i < argCnt; ){
1176 std::string shapeName = splittedStr[i++];
1177 if(shapeName ==
"SQUARE" && this->coordinate_dimension == 2){
1178 if(i + 3 > argCnt) {
1182 pp.
x = fromString<scalar_t>(splittedStr[i++]);
1183 pp.
y = fromString<scalar_t>(splittedStr[i++]);
1184 scalar_t edge = fromString<scalar_t>(splittedStr[i++]);
1186 }
else if(shapeName ==
"RECTANGLE" && this->coordinate_dimension == 2){
1187 if(i + 4 > argCnt) {
1191 pp.
x = fromString<scalar_t>(splittedStr[i++]);
1192 pp.
y = fromString<scalar_t>(splittedStr[i++]);
1193 scalar_t edgex = fromString<scalar_t>(splittedStr[i++]);
1194 scalar_t edgey = fromString<scalar_t>(splittedStr[i++]);
1197 }
else if(shapeName ==
"CIRCLE" && this->coordinate_dimension == 2){
1198 if(i + 3 > argCnt) {
1202 pp.
x = fromString<scalar_t>(splittedStr[i++]);
1203 pp.
y = fromString<scalar_t>(splittedStr[i++]);
1204 scalar_t r = fromString<scalar_t>(splittedStr[i++]);
1206 }
else if(shapeName ==
"CUBE" && this->coordinate_dimension == 3){
1207 if(i + 4 > argCnt) {
1211 pp.
x = fromString<scalar_t>(splittedStr[i++]);
1212 pp.
y = fromString<scalar_t>(splittedStr[i++]);
1213 pp.
z = fromString<scalar_t>(splittedStr[i++]);
1214 scalar_t edge = fromString<scalar_t>(splittedStr[i++]);
1216 }
else if(shapeName ==
"RECTANGULAR_PRISM" && this->coordinate_dimension == 3){
1217 if(i + 6 > argCnt) {
1221 pp.
x = fromString<scalar_t>(splittedStr[i++]);
1222 pp.
y = fromString<scalar_t>(splittedStr[i++]);
1223 pp.
z = fromString<scalar_t>(splittedStr[i++]);
1224 scalar_t edgex = fromString<scalar_t>(splittedStr[i++]);
1225 scalar_t edgey = fromString<scalar_t>(splittedStr[i++]);
1226 scalar_t edgez = fromString<scalar_t>(splittedStr[i++]);
1229 }
else if(shapeName ==
"SPHERE" && this->coordinate_dimension == 3){
1230 if(i + 4 > argCnt) {
1234 pp.
x = fromString<scalar_t>(splittedStr[i++]);
1235 pp.
y = fromString<scalar_t>(splittedStr[i++]);
1236 pp.
z = fromString<scalar_t>(splittedStr[i++]);
1237 scalar_t r = fromString<scalar_t>(splittedStr[i++]);
1240 std::string tmp = Teuchos::toString<int>(this->coordinate_dimension);
1244 delete [] splittedStr;
1247 void getWeightDistribution(std::string *weight_distribution_arr,
int wdimension){
1252 std::string weight_distribution = weight_distribution_arr[ii];
1253 if(weight_distribution ==
"")
continue;
1254 if(wcount == wdimension) {
1255 throw "Weight Dimension is provided as " + Teuchos::toString<int>(wdimension) +
". More weight distribution is provided.";
1258 int count = this->countChar(weight_distribution,
' ');
1259 std::string *splittedStr =
new string[count + 1];
1260 this->splitString(weight_distribution,
' ', splittedStr);
1263 scalar_t a1=0,a2=0,a3=0;
1264 scalar_t x1=0,y1=0,z1=0;
1265 scalar_t b1=1,b2=1,b3=1;
1266 scalar_t *steps = NULL;
1267 scalar_t *values= NULL;
1271 for (
int i = 1; i < count + 1; ++i){
1272 int assignmentCount = this->countChar(splittedStr[i],
'=');
1273 if (assignmentCount != 1){
1274 throw "Error at the argument " + splittedStr[i];
1276 std::string parameter_vs_val[2];
1277 this->splitString(splittedStr[i],
'=', parameter_vs_val);
1278 std::string parameter = parameter_vs_val[0];
1279 std::string value = parameter_vs_val[1];
1282 if (parameter ==
"a1"){
1283 a1 = this->fromString<scalar_t>(value);
1285 else if (parameter ==
"a2"){
1286 if(this->coordinate_dimension > 1){
1287 a2 = this->fromString<scalar_t>(value);
1290 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1294 else if (parameter ==
"a3"){
1295 if(this->coordinate_dimension > 2){
1296 a3 = this->fromString<scalar_t>(value);
1299 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1302 else if (parameter ==
"b1"){
1303 b1 = this->fromString<scalar_t>(value);
1305 else if (parameter ==
"b2"){
1306 if(this->coordinate_dimension > 1){
1307 b2 = this->fromString<scalar_t>(value);
1310 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1313 else if (parameter ==
"b3"){
1315 if(this->coordinate_dimension > 2){
1316 b3 = this->fromString<scalar_t>(value);
1319 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1322 else if (parameter ==
"c"){
1323 c = this->fromString<scalar_t>(value);
1325 else if (parameter ==
"x1"){
1326 x1 = this->fromString<scalar_t>(value);
1328 else if (parameter ==
"y1"){
1329 if(this->coordinate_dimension > 1){
1330 y1 = this->fromString<scalar_t>(value);
1333 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1336 else if (parameter ==
"z1"){
1337 if(this->coordinate_dimension > 2){
1338 z1 = this->fromString<scalar_t>(value);
1341 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1344 else if (parameter ==
"steps"){
1345 stepCount = this->countChar(value,
',') + 1;
1346 std::string *stepstr =
new std::string[stepCount];
1347 this->splitString(value,
',', stepstr);
1348 steps =
new scalar_t[stepCount];
1349 for (
int j = 0; j < stepCount; ++j){
1350 steps[j] = this->fromString<scalar_t>(stepstr[j]);
1354 else if (parameter ==
"values"){
1355 valueCount = this->countChar(value,
',') + 1;
1356 std::string *stepstr =
new std::string[valueCount];
1357 this->splitString(value,
',', stepstr);
1358 values =
new scalar_t[valueCount];
1359 for (
int j = 0; j < valueCount; ++j){
1360 values[j] = this->fromString<scalar_t>(stepstr[j]);
1365 throw "Invalid parameter name at " + splittedStr[i];
1369 delete []splittedStr;
1370 if(stepCount + 1!= valueCount){
1371 throw "Step count: " + Teuchos::toString<int>(stepCount) +
" must be 1 less than value count: " + Teuchos::toString<int>(valueCount);
1375 this->wd[wcount++] =
new SteppedEquation<scalar_t,scalar_t>(a1, a2, a3, b1, b2, b3, c, x1, y1, z1, steps, values, stepCount);
1383 if(wcount != this->numWeightsPerCoord){
1384 throw "Weight Dimension is provided as " + Teuchos::toString<int>(wdimension) +
". But " + Teuchos::toString<int>(wcount)+
" weight distributions are provided.";
1388 void parseParams(
const Teuchos::ParameterList & params){
1390 std::string holeDescription =
"";
1391 std::string proc_load_distributions =
"";
1392 std::string distinctDescription =
"";
1393 std::string coordinate_distributions =
"";
1396 numWeightsPerCoord_parameters[i] =
"";
1400 for (Teuchos::ParameterList::ConstIterator pit = params.begin(); pit != params.end(); ++pit ){
1401 const std::string &
paramName = params.name(pit);
1403 const Teuchos::ParameterEntry &pe = params.entry(pit);
1405 if(paramName.find(
"hole-") == 0){
1406 if(holeDescription ==
""){
1407 holeDescription = getParamVal<std::string>(pe,
paramName);
1410 holeDescription +=
","+getParamVal<std::string>(pe,
paramName);
1413 else if(paramName.find(
"distribution-") == 0){
1414 if(coordinate_distributions ==
"")
1415 coordinate_distributions = getParamVal<std::string>(pe,
paramName);
1417 coordinate_distributions +=
","+getParamVal<std::string>(pe,
paramName);
1424 int dash_pos = weight_dist_param.find(
"-");
1425 std::string distribution_index_string = weight_dist_param.substr(0, dash_pos);
1426 int distribution_index = fromString<int>(distribution_index_string);
1428 if(distribution_index >= MAX_WEIGHT_DIM){
1429 throw "Given distribution index:" + distribution_index_string +
" larger than maximum allowed number of weights:" + Teuchos::toString<int>(
MAX_WEIGHT_DIM);
1431 numWeightsPerCoord_parameters[distribution_index] +=
" " + weight_dist_param.substr(dash_pos + 1)+
"="+ getParamVal<std::string>(pe,
paramName);
1433 else if(paramName ==
"dim"){
1434 int dim = fromString<int>(getParamVal<std::string>(pe,
paramName));
1435 if(dim < 2 && dim > 3){
1438 this->coordinate_dimension = dim;
1441 else if(paramName ==
"wdim"){
1442 int dim = fromString<int>(getParamVal<std::string>(pe,
paramName));
1443 if(dim < 1 && dim > MAX_WEIGHT_DIM){
1446 this->numWeightsPerCoord = dim;
1449 else if(paramName ==
"predistribution"){
1450 int pre_distribution = fromString<int>(getParamVal<std::string>(pe,
paramName));
1451 if(pre_distribution < 0 && pre_distribution > 3){
1454 this->predistribution = pre_distribution;
1457 else if(paramName ==
"perturbation_ratio"){
1458 float perturbation = fromString<float>(getParamVal<std::string>(pe,
paramName));
1459 if(perturbation < 0 && perturbation > 1){
1462 this->perturbation_ratio = perturbation;
1467 else if(paramName ==
"proc_load_distributions"){
1468 proc_load_distributions = getParamVal<std::string>(pe,
paramName);
1469 this->loadDistSet =
true;
1472 else if(paramName ==
"distinct_coordinates"){
1473 distinctDescription = getParamVal<std::string>(pe,
paramName);
1474 if(distinctDescription ==
"T"){
1475 this->distinctCoordSet =
true;
1476 }
else if(distinctDescription ==
"F"){
1477 this->distinctCoordSet =
true;
1479 throw "Invalid parameter for distinct_coordinates: " + distinctDescription +
". Candidates: T or F." ;
1483 else if(paramName ==
"out_file"){
1484 this->outfile = getParamVal<std::string>(pe,
paramName);
1493 if(this->coordinate_dimension == 0){
1494 throw "Dimension must be provided to coordinate generator.";
1513 if (this->loadDistSet && this->distinctCoordSet){
1514 throw "distinct_coordinates and proc_load_distributions parameters cannot be satisfied together.";
1516 this->getHoles(holeDescription);
1518 this->getProcLoadDistributions(proc_load_distributions);
1519 this->getCoordinateDistributions(coordinate_distributions);
1520 this->getWeightDistribution(numWeightsPerCoord_parameters, this->numWeightsPerCoord);
1527 catch(std::string s){
1540 for (
int i = 0; i < this->holeCount; ++i){
1541 delete this->holes[i];
1547 delete []loadDistributions;
1549 if(coordinateDistributions){
1551 for (
int i = 0; i < this->distributionCount; ++i){
1552 delete this->coordinateDistributions[i];
1554 free (this->coordinateDistributions);
1557 for (
int i = 0; i < this->numWeightsPerCoord; ++i){
1563 if(this->numWeightsPerCoord){
1564 for(
int i = 0; i < this->numWeightsPerCoord; ++i)
1565 delete [] this->wghts[i];
1566 delete []this->wghts;
1568 if(this->coordinate_dimension){
1569 for(
int i = 0; i < this->coordinate_dimension; ++i)
1570 delete [] this->coords[i];
1571 delete [] this->coords;
1577 std::cout <<
"\nGeometric Generator Parameter File Format:" << std::endl;
1578 std::cout <<
"- dim=Coordinate Dimension: 2 or 3" << std::endl;
1579 std::cout <<
"- Available distributions:" << std::endl;
1580 std::cout <<
"\tUNIFORM: -> distribution-1=UNIFORM,NUMCOORDINATES,XMIN,XMAX,YMIN,YMAX{,ZMIN,ZMAX}" << std::endl;
1581 std::cout <<
"\tGRID: -> distribution-2=GRID,XLENGTH,YLENGTH{,ZLENGTH},XMIN,XMAX,YMIN,YMAX{,ZMIN,ZMAX}" << std::endl;
1582 std::cout <<
"\tNORMAL: -> distribution-3=NORMAL,XCENTER,YCENTER{,ZCENTER},XSD,YSD,{,ZSD}" << std::endl;
1583 std::cout <<
"- wdim=numWeightsPerCoord: There should be as many weight function as number of weights per coord." << std::endl;
1584 std::cout <<
"- Weight Equation: w = (a1 * (x - x1)^b1) + (a2 * (y - y1)^b2) + (a3 * (z - z1)^b3) + c" << std::endl;
1585 std::cout <<
"Parameter settings:" << std::endl;
1586 std::cout <<
"\tWeightDistribution-1-a1=a1 " << std::endl;
1587 std::cout <<
"\tWeightDistribution-1-a2=a2 " << std::endl;
1588 std::cout <<
"\tWeightDistribution-1-a3=a3 " << std::endl;
1589 std::cout <<
"\tWeightDistribution-1-b1=b1 " << std::endl;
1590 std::cout <<
"\tWeightDistribution-1-b2=b2 " << std::endl;
1591 std::cout <<
"\tWeightDistribution-1-b3=b3 " << std::endl;
1592 std::cout <<
"\tWeightDistribution-1-x1=x1 " << std::endl;
1593 std::cout <<
"\tWeightDistribution-1-y1=y1 " << std::endl;
1594 std::cout <<
"\tWeightDistribution-1-z1=z1 " << std::endl;
1595 std::cout <<
"\tWeightDistribution-1-c=c " << std::endl;
1596 std::cout <<
"\tIt is possible to set step function to the result of weight equation." << std::endl;
1597 std::cout <<
"\tWeightDistribution-1-steps=step1,step2,step3:increasing order" << std::endl;
1598 std::cout <<
"\tWeightDistribution-1-values=val1,val2,val3,val4." << std::endl;
1599 std::cout <<
"\t\tIf w < step1 -> w = val1" << std::endl;
1600 std::cout <<
"\t\tElse if w < step2 -> w = val2" << std::endl;
1601 std::cout <<
"\t\tElse if w < step3 -> w = val3" << std::endl;
1602 std::cout <<
"\t\tElse -> w = val4" << std::endl;
1603 std::cout <<
"- Holes:" << std::endl;
1604 std::cout <<
"\thole-1:SPHERE,XCENTER,YCENTER,ZCENTER,RADIUS (only for dim=3)" << std::endl;
1605 std::cout <<
"\thole-2:CUBE,XCENTER,YCENTER,ZCENTER,EDGE (only for dim=3)" << std::endl;
1606 std::cout <<
"\thole-3:RECTANGULAR_PRISM,XCENTER,YCENTER,ZCENTER,XEDGE,YEDGE,ZEDGE (only for dim=3)" << std::endl;
1607 std::cout <<
"\thole-4:SQUARE,XCENTER,YCENTER,EDGE (only for dim=2)" << std::endl;
1608 std::cout <<
"\thole-5:RECTANGLE,XCENTER,YCENTER,XEDGE,YEDGE (only for dim=2)" << std::endl;
1609 std::cout <<
"\thole-6:CIRCLE,XCENTER,YCENTER,RADIUS (only for dim=2)" << std::endl;
1610 std::cout <<
"- out_file:out_file_path : if provided output will be written to files." << std::endl;
1611 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;
1612 std::cout <<
"- predistribution:distribution_option. Predistribution of the coordinates to the processors. 0 for NONE, 1 RCB, 2 MJ, 3 BLOCK." << std::endl;
1613 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;
1620 this->coordinate_dimension = 0;
1621 this->numWeightsPerCoord = 0;
1622 this->worldSize = comm_->getSize();
1623 this->numGlobalCoords = 0;
1624 this->loadDistributions = NULL;
1626 this->coordinateDistributions = NULL;
1627 this->holeCount = 0;
1628 this->distributionCount = 0;
1630 this->predistribution = 0;
1631 this->perturbation_ratio = 0;
1642 this->loadDistSet =
false;
1643 this->distinctCoordSet =
false;
1644 this->myRank = comm_->getRank();
1647 this->parseParams(params);
1649 catch(std::string s){
1659 lno_t myPointCount = 0;
1660 this->numGlobalCoords = 0;
1662 gno_t prefixSum = 0;
1663 for(
int i = 0; i < this->distributionCount; ++i){
1664 for(
int ii = 0; ii < this->worldSize; ++ii){
1665 lno_t increment = lno_t (this->coordinateDistributions[i]->numPoints * this->loadDistributions[ii]);
1666 if (gno_t(ii) < this->coordinateDistributions[i]->numPoints % this->worldSize){
1669 this->numGlobalCoords += increment;
1671 prefixSum += increment;
1674 myPointCount += lno_t(this->coordinateDistributions[i]->numPoints * this->loadDistributions[myRank]);
1675 if (gno_t(myRank) < this->coordinateDistributions[i]->numPoints % this->worldSize){
1680 this->coords =
new scalar_t *[this->coordinate_dimension];
1681 for(
int i = 0; i < this->coordinate_dimension; ++i){
1682 this->coords[i] =
new scalar_t[myPointCount];
1685 for (
int ii = 0; ii < this->coordinate_dimension; ++ii){
1686 #ifdef HAVE_ZOLTAN2_OMP
1687 #pragma omp parallel for
1689 for(lno_t i = 0; i < myPointCount; ++i){
1690 this->coords[ii][i] = 0;
1694 this->numLocalCoords = 0;
1695 srand ((myRank + 1) * this->numLocalCoords);
1696 for (
int i = 0; i < distributionCount; ++i){
1698 lno_t requestedPointCount = lno_t(this->coordinateDistributions[i]->numPoints * this->loadDistributions[myRank]);
1699 if (gno_t(myRank) < this->coordinateDistributions[i]->numPoints % this->worldSize){
1700 requestedPointCount += 1;
1704 this->coordinateDistributions[i]->
GetPoints(requestedPointCount,this->coords, this->numLocalCoords, this->holes, this->holeCount, this->loadDistributions, myRank);
1705 this->numLocalCoords += requestedPointCount;
1727 if (this->predistribution){
1734 if (this->perturbation_ratio > 0){
1756 if (this->distinctCoordSet){
1760 if(this->outfile !=
""){
1762 std::ofstream myfile;
1763 myfile.open ((this->outfile + Teuchos::toString<int>(myRank)).c_str());
1764 for(lno_t i = 0; i < this->numLocalCoords; ++i){
1766 myfile << this->coords[0][i];
1767 if(this->coordinate_dimension > 1){
1768 myfile <<
" " << this->coords[1][i];
1770 if(this->coordinate_dimension > 2){
1771 myfile <<
" " << this->coords[2][i];
1773 myfile << std::endl;
1777 if (this->myRank == 0){
1778 std::ofstream gnuplotfile(
"gnu.gnuplot");
1779 for(
int i = 0; i < this->worldSize; ++i){
1781 if (this->coordinate_dimension == 2){
1787 gnuplotfile << s <<
" \"" << (this->outfile + Teuchos::toString<int>(i)) <<
"\"" << std::endl;
1789 gnuplotfile <<
"pause -1" << std::endl;
1790 gnuplotfile.close();
1803 if (this->numWeightsPerCoord > 0){
1804 this->wghts =
new scalar_t *[this->numWeightsPerCoord];
1805 for(
int i = 0; i < this->numWeightsPerCoord; ++i){
1806 this->wghts[i] =
new scalar_t[this->numLocalCoords];
1810 for(
int ii = 0; ii < this->numWeightsPerCoord; ++ii){
1811 switch(this->coordinate_dimension){
1814 #ifdef HAVE_ZOLTAN2_OMP
1815 #pragma omp parallel for
1817 for (lno_t i = 0; i < this->numLocalCoords; ++i){
1818 this->wghts[ii][i] = this->wd[ii]->
get1DWeight(this->coords[0][i]);
1824 #ifdef HAVE_ZOLTAN2_OMP
1825 #pragma omp parallel for
1827 for (lno_t i = 0; i < this->numLocalCoords; ++i){
1828 this->wghts[ii][i] = this->wd[ii]->
get2DWeight(this->coords[0][i], this->coords[1][i]);
1834 #ifdef HAVE_ZOLTAN2_OMP
1835 #pragma omp parallel for
1837 for (lno_t i = 0; i < this->numLocalCoords; ++i){
1838 this->wghts[ii][i] = this->wd[ii]->
get3DWeight(this->coords[0][i], this->coords[1][i], this->coords[2][i]);
1850 scalar_t *maxCoords=
new scalar_t [this->coordinate_dimension];
1851 scalar_t *minCoords=
new scalar_t [this->coordinate_dimension];
1852 for (
int dim = 0; dim < this->coordinate_dimension; ++dim){
1853 minCoords[dim] = maxCoords[dim] = this->coords[dim][0];
1854 for (lno_t i = 1; i < this->numLocalCoords; ++i){
1855 if (minCoords[dim] > this->coords[dim][i]){
1856 minCoords[dim] = this->coords[dim][i];
1859 if (maxCoords[dim] < this->coords[dim][i]){
1860 maxCoords[dim] = this->coords[dim][i];
1867 scalar_t center = (maxCoords[dim] + minCoords[dim]) / 2;
1869 minCoords[dim] = center - (center - minCoords[dim]) * scale;
1870 maxCoords[dim] = (maxCoords[dim] - center) * scale + center;
1874 gno_t numLocalToPerturb = gno_t(this->numLocalCoords*used_perturbation_ratio);
1876 for (
int dim = 0; dim < this->coordinate_dimension; ++dim){
1877 scalar_t range = maxCoords[dim] - minCoords[dim];
1878 for (gno_t i = 0; i < numLocalToPerturb; ++i){
1879 this->coords[dim][i] = (rand() / double (RAND_MAX)) * (range) + minCoords[dim];
1892 void getBestSurface (
int remaining,
int *dimProcs,
int dim,
int currentDim,
int &bestSurface,
int *bestDimProcs){
1894 if (currentDim < dim - 1){
1896 while(ipx <= remaining) {
1897 if(remaining % ipx == 0) {
1898 int nremain = remaining / ipx;
1899 dimProcs[currentDim] = ipx;
1900 getBestSurface (nremain, dimProcs, dim, currentDim + 1, bestSurface, bestDimProcs);
1906 dimProcs[currentDim] = remaining;
1908 for (
int i = 0; i < dim; ++i) surface += dimProcs[i];
1909 if (surface < bestSurface){
1910 bestSurface = surface;
1911 for (
int i = 0; i < dim; ++i) bestDimProcs[i] = dimProcs[i];
1919 scalar_t *maxCoords=
new scalar_t [this->coordinate_dimension];
1920 scalar_t *minCoords=
new scalar_t [this->coordinate_dimension];
1921 for (
int dim = 0; dim < this->coordinate_dimension; ++dim){
1922 minCoords[dim] = maxCoords[dim] = this->coords[dim][0];
1923 for (lno_t i = 1; i < this->numLocalCoords; ++i){
1924 if (minCoords[dim] > this->coords[dim][i]){
1925 minCoords[dim] = this->coords[dim][i];
1928 if (maxCoords[dim] < this->coords[dim][i]){
1929 maxCoords[dim] = this->coords[dim][i];
1934 reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MAX,
1935 this->coordinate_dimension,
1940 reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MIN,
1941 this->coordinate_dimension,
1955 typedef SSIZE_T ssize_t;
1962 scalar_t *maxCoords=
new scalar_t [this->coordinate_dimension];
1963 scalar_t *minCoords=
new scalar_t [this->coordinate_dimension];
1971 int remaining = this->worldSize;
1972 int coord_dim = this->coordinate_dimension;
1973 int *dimProcs =
new int[coord_dim];
1974 int *bestDimProcs =
new int[coord_dim];
1977 int bestSurface = 0;
1978 dimProcs[0] = remaining;
1979 for (
int i = 1; i < coord_dim; ++i) dimProcs[i] = 1;
1980 for (
int i = 0; i < coord_dim; ++i) bestSurface += dimProcs[i];
1981 for (
int i = 0; i < coord_dim; ++i) bestDimProcs[i] = dimProcs[i];
1983 getBestSurface ( remaining, dimProcs, coord_dim, currentDim, bestSurface, bestDimProcs);
1991 int *shiftProcCount =
new int[coord_dim];
1995 int remainingProc = this->worldSize;
1996 for (
int dim = 0; dim < coord_dim; ++dim){
1997 remainingProc = remainingProc / bestDimProcs[dim];
1998 shiftProcCount[dim] = remainingProc;
2001 scalar_t *dim_slices =
new scalar_t[coord_dim];
2002 for (
int dim = 0; dim < coord_dim; ++dim){
2003 scalar_t dim_range = maxCoords[dim] - minCoords[dim];
2004 scalar_t slice = dim_range / bestDimProcs[dim];
2005 dim_slices[dim] = slice;
2012 gno_t *numPointsInParts =
new gno_t[this->worldSize];
2013 gno_t *numGlobalPointsInParts =
new gno_t[this->worldSize];
2014 gno_t *numPointsInPartsInclusiveUptoMyIndex =
new gno_t[this->worldSize];
2016 gno_t *partBegins =
new gno_t [this->worldSize];
2017 gno_t *partNext =
new gno_t[this->numLocalCoords];
2020 for (lno_t i = 0; i < this->numLocalCoords; ++i){
2023 for (
int i = 0; i < this->worldSize; ++i) {
2027 for (
int i = 0; i < this->worldSize; ++i)
2028 numPointsInParts[i] = 0;
2030 for (lno_t i = 0; i < this->numLocalCoords; ++i){
2032 for (
int dim = 0; dim < coord_dim; ++dim){
2033 int shift = int ((this->coords[dim][i] - minCoords[dim]) / dim_slices[dim]);
2034 if (shift >= bestDimProcs[dim]){
2035 shift = bestDimProcs[dim] - 1;
2037 shift = shift * shiftProcCount[dim];
2040 numPointsInParts[partIndex] += 1;
2041 coordinate_grid_parts[i] = partIndex;
2043 partNext[i] = partBegins[partIndex];
2044 partBegins[partIndex] = i;
2051 reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
2054 numGlobalPointsInParts);
2057 Teuchos::scan<int,gno_t>(
2058 *(this->comm), Teuchos::REDUCE_SUM,
2061 numPointsInPartsInclusiveUptoMyIndex
2080 gno_t optimal_num = gno_t(this->numGlobalCoords/
double(this->worldSize)+0.5);
2082 if (this->myRank == 0){
2083 gno_t totalSize = 0;
2084 for (
int i = 0; i < this->worldSize; ++i){
2085 std::cout <<
"me:" << this->myRank <<
" NumPoints in part:" << i <<
" is: " << numGlobalPointsInParts[i] << std::endl;
2086 totalSize += numGlobalPointsInParts[i];
2088 std::cout <<
"Total:" << totalSize <<
" ng:" << this->numGlobalCoords << std::endl;
2089 std::cout <<
"optimal_num:" << optimal_num << std::endl;
2092 ssize_t *extraInPart =
new ssize_t [this->worldSize];
2094 ssize_t extraExchange = 0;
2095 for (
int i = 0; i < this->worldSize; ++i){
2096 extraInPart[i] = numGlobalPointsInParts[i] - optimal_num;
2097 extraExchange += extraInPart[i];
2099 if (extraExchange != 0){
2101 if (extraExchange < 0) addition = 1;
2102 for (ssize_t i = 0; i < extraExchange; ++i){
2103 extraInPart[i % this->worldSize] += addition;
2111 int overloadedPartCount = 0;
2112 int *overloadedPartIndices =
new int [this->worldSize];
2115 int underloadedPartCount = 0;
2116 int *underloadedPartIndices =
new int [this->worldSize];
2118 for (
int i = 0; i < this->worldSize; ++i){
2119 if(extraInPart[i] > 0){
2120 overloadedPartIndices[overloadedPartCount++] = i;
2122 else if(extraInPart[i] < 0){
2123 underloadedPartIndices[underloadedPartCount++] = i;
2127 int underloadpartindex = underloadedPartCount - 1;
2130 int numPartsISendFrom = 0;
2131 int *mySendFromParts =
new int[this->worldSize * 2];
2132 gno_t *mySendFromPartsCounts =
new gno_t[this->worldSize * 2];
2134 int numPartsISendTo = 0;
2135 int *mySendParts =
new int[this->worldSize * 2];
2136 gno_t *mySendCountsToParts =
new gno_t[this->worldSize * 2];
2145 for (
int i = overloadedPartCount - 1; i >= 0; --i){
2148 int overloadPart = overloadedPartIndices[i];
2149 gno_t overload = extraInPart[overloadPart];
2150 gno_t myload = numPointsInParts[overloadPart];
2154 gno_t inclusiveLoadUpToMe = numPointsInPartsInclusiveUptoMyIndex[overloadPart];
2157 gno_t exclusiveLoadUptoMe = inclusiveLoadUpToMe - myload;
2160 if (exclusiveLoadUptoMe >= overload){
2164 overloadedPartIndices[i] = -1;
2165 extraInPart[overloadPart] = 0;
2167 while (overload > 0){
2168 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2169 ssize_t underload = extraInPart[nextUnderLoadedPart];
2170 ssize_t left = overload + underload;
2173 extraInPart[nextUnderLoadedPart] = 0;
2174 underloadedPartIndices[underloadpartindex--] = -1;
2177 extraInPart[nextUnderLoadedPart] = left;
2182 else if (exclusiveLoadUptoMe < overload){
2185 gno_t mySendCount = overload - exclusiveLoadUptoMe;
2187 gno_t sendAfterMe = 0;
2190 if (mySendCount > myload){
2191 sendAfterMe = mySendCount - myload;
2192 mySendCount = myload;
2198 mySendFromParts[numPartsISendFrom] = overloadPart;
2199 mySendFromPartsCounts[numPartsISendFrom++] = mySendCount;
2202 while (exclusiveLoadUptoMe > 0){
2203 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2204 ssize_t underload = extraInPart[nextUnderLoadedPart];
2205 ssize_t left = exclusiveLoadUptoMe + underload;
2208 extraInPart[nextUnderLoadedPart] = 0;
2209 underloadedPartIndices[underloadpartindex--] = -1;
2212 extraInPart[nextUnderLoadedPart] = left;
2214 exclusiveLoadUptoMe = left;
2218 while (mySendCount > 0){
2219 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2220 ssize_t underload = extraInPart[nextUnderLoadedPart];
2221 ssize_t left = mySendCount + underload;
2224 mySendParts[numPartsISendTo] = nextUnderLoadedPart;
2225 mySendCountsToParts[numPartsISendTo++] = -underload;
2227 extraInPart[nextUnderLoadedPart] = 0;
2228 underloadedPartIndices[underloadpartindex--] = -1;
2231 extraInPart[nextUnderLoadedPart] = left;
2233 mySendParts[numPartsISendTo] = nextUnderLoadedPart;
2234 mySendCountsToParts[numPartsISendTo++] = mySendCount;
2240 while (sendAfterMe > 0){
2241 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2242 ssize_t underload = extraInPart[nextUnderLoadedPart];
2243 ssize_t left = sendAfterMe + underload;
2246 extraInPart[nextUnderLoadedPart] = 0;
2247 underloadedPartIndices[underloadpartindex--] = -1;
2250 extraInPart[nextUnderLoadedPart] = left;
2261 for (
int i = 0 ; i < numPartsISendFrom; ++i){
2264 int sendFromPart = mySendFromParts[i];
2265 ssize_t sendCount = mySendFromPartsCounts[i];
2266 while(sendCount > 0){
2267 int partToSendIndex = numPartsISendTo - 1;
2268 int partToSend = mySendParts[partToSendIndex];
2270 int sendCountToThisPart = mySendCountsToParts[partToSendIndex];
2274 if (sendCountToThisPart <= sendCount){
2275 mySendParts[partToSendIndex] = 0;
2276 mySendCountsToParts[partToSendIndex] = 0;
2278 sendCount -= sendCountToThisPart;
2281 mySendCountsToParts[partToSendIndex] = sendCountToThisPart - sendCount;
2282 sendCountToThisPart = sendCount;
2287 gno_t toChange = partBegins[sendFromPart];
2288 gno_t previous_begin = partBegins[partToSend];
2291 for (
int k = 0; k < sendCountToThisPart - 1; ++k){
2292 coordinate_grid_parts[toChange] = partToSend;
2293 toChange = partNext[toChange];
2295 coordinate_grid_parts[toChange] = partToSend;
2297 gno_t newBegin = partNext[toChange];
2298 partNext[toChange] = previous_begin;
2299 partBegins[partToSend] = partBegins[sendFromPart];
2300 partBegins[sendFromPart] = newBegin;
2309 for (
int i = 0; i < this->worldSize; ++i) numPointsInParts[i] = 0;
2311 for (
int i = 0; i < this->numLocalCoords; ++i){
2312 numPointsInParts[coordinate_grid_parts[i]] += 1;
2315 reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
2318 numGlobalPointsInParts);
2319 if (this->myRank == 0){
2320 std::cout <<
"reassigning" << std::endl;
2321 gno_t totalSize = 0;
2322 for (
int i = 0; i < this->worldSize; ++i){
2323 std::cout <<
"me:" << this->myRank <<
" NumPoints in part:" << i <<
" is: " << numGlobalPointsInParts[i] << std::endl;
2324 totalSize += numGlobalPointsInParts[i];
2326 std::cout <<
"Total:" << totalSize <<
" ng:" << this->numGlobalCoords << std::endl;
2329 delete []mySendCountsToParts;
2330 delete []mySendParts;
2331 delete []mySendFromPartsCounts;
2332 delete []mySendFromParts;
2333 delete []underloadedPartIndices;
2334 delete []overloadedPartIndices;
2335 delete []extraInPart;
2337 delete []partBegins;
2338 delete []numPointsInPartsInclusiveUptoMyIndex;
2339 delete []numPointsInParts;
2340 delete []numGlobalPointsInParts;
2342 delete []shiftProcCount;
2343 delete []bestDimProcs;
2344 delete []dim_slices;
2353 Tpetra::Distributor distributor(comm);
2354 ArrayView<const int> pIds( coordinate_grid_parts, this->numLocalCoords);
2360 gno_t numMyNewGnos = distributor.createFromSends(pIds);
2364 this->numLocalCoords = numMyNewGnos;
2367 ArrayRCP<scalar_t> recvBuf2(distributor.getTotalReceiveLength());
2369 for (
int i = 0; i < this->coordinate_dimension; ++i){
2370 ArrayView<scalar_t> s(this->coords[i], this->numLocalCoords);
2371 distributor.doPostsAndWaits<scalar_t>(s, 1, recvBuf2());
2372 delete [] this->coords[i];
2373 this->coords[i] =
new scalar_t[this->numLocalCoords];
2374 for (lno_t j = 0; j < this->numLocalCoords; ++j){
2375 this->coords[i][j] = recvBuf2[j];
2383 int coord_dim = this->coordinate_dimension;
2385 lno_t numLocalPoints = this->numLocalCoords;
2386 gno_t numGlobalPoints = this->numGlobalCoords;
2391 RCP<Tpetra::Map<lno_t, gno_t, node_t> > mp = rcp(
2392 new Tpetra::Map<lno_t, gno_t, node_t> (numGlobalPoints, numLocalPoints, 0, comm));
2394 Teuchos::Array<Teuchos::ArrayView<const scalar_t> > coordView(coord_dim);
2398 for (
int i=0; i < coord_dim; i++){
2399 if(numLocalPoints > 0){
2400 Teuchos::ArrayView<const scalar_t> a(coords[i], numLocalPoints);
2403 Teuchos::ArrayView<const scalar_t> a;
2408 RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >tmVector = RCP< Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t> >(
2409 new Tpetra::MultiVector<scalar_t, lno_t, gno_t, node_t>( mp, coordView.view(0, coord_dim), coord_dim));
2412 RCP<const tMVector_t> coordsConst = Teuchos::rcp_const_cast<
const tMVector_t>(tmVector);
2413 std::vector<const scalar_t *>
weights;
2414 std::vector <int> stride;
2418 inputAdapter_t ia(coordsConst,weights, stride);
2420 Teuchos::RCP <Teuchos::ParameterList> params ;
2421 params =RCP <Teuchos::ParameterList> (
new Teuchos::ParameterList,
true);
2424 params->set(
"algorithm",
"multijagged");
2425 params->set(
"num_global_parts", this->worldSize);
2437 #ifdef HAVE_ZOLTAN2_MPI
2453 for (lno_t i = 0; i < this->numLocalCoords;++i){
2454 coordinate_grid_parts[i] = partIds[i];
2463 int rank = this->myRank;
2464 int nprocs = this->worldSize;
2467 MEMORY_CHECK(rank==0 || rank==nprocs-1,
"After initializing MPI");
2472 string memoryOn(
"memoryOn");
2473 string memoryOff(
"memoryOff");
2474 bool doMemory=
false;
2475 int numGlobalParts = nprocs;
2479 string balanceCount(
"balance_object_count");
2480 string balanceWeight(
"balance_object_weight");
2481 string mcnorm1(
"multicriteria_minimize_total_weight");
2482 string mcnorm2(
"multicriteria_balance_total_maximum");
2483 string mcnorm3(
"multicriteria_minimize_maximum_weight");
2484 string objective(balanceWeight);
2487 CommandLineProcessor commandLine(
false,
true);
2490 int input_option = 0;
2491 commandLine.setOption(
"input_option", &input_option,
2492 "whether to use mesh creation, geometric generator, or file input");
2493 string inputFile =
"";
2495 commandLine.setOption(
"input_file", &inputFile,
2496 "the input file for geometric generator or file input");
2499 commandLine.setOption(
"size", &numGlobalCoords,
2500 "Approximate number of global coordinates.");
2501 commandLine.setOption(
"numParts", &numGlobalParts,
2502 "Number of parts (default is one per proc).");
2503 commandLine.setOption(
"nWeights", &nWeights,
2504 "Number of weights per coordinate, zero implies uniform weights.");
2505 commandLine.setOption(
"debug", &debugLevel,
"Zoltan1 debug level");
2506 commandLine.setOption(
"remap",
"no-remap", &remap,
2507 "Zoltan1 REMAP parameter; disabled by default for scalability testing");
2508 commandLine.setOption(
"timers", &dummyTimer,
"ignored");
2509 commandLine.setOption(memoryOn.c_str(), memoryOff.c_str(), &doMemory,
2510 "do memory profiling");
2512 string doc(balanceCount);
2513 doc.append(
": ignore weights\n");
2514 doc.append(balanceWeight);
2515 doc.append(
": balance on first weight\n");
2516 doc.append(mcnorm1);
2517 doc.append(
": given multiple weights, balance their total.\n");
2518 doc.append(mcnorm3);
2519 doc.append(
": given multiple weights, "
2520 "balance the maximum for each coordinate.\n");
2521 doc.append(mcnorm2);
2522 doc.append(
": given multiple weights, balance the L2 norm of the weights.\n");
2523 commandLine.setOption(
"objective", &objective, doc.c_str());
2525 CommandLineProcessor::EParseCommandLineReturn rc =
2526 commandLine.parse(0, NULL);
2530 if (rc != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
2531 if (rc == Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED) {
2532 if (rank==0) std::cout <<
"PASS" << std::endl;
2536 if (rank==0) std::cout <<
"FAIL" << std::endl;
2545 int coord_dim = this->coordinate_dimension;
2548 RCP<Tpetra::Map<lno_t, gno_t, node_t> > mp = rcp(
2549 new Tpetra::Map<lno_t, gno_t, node_t> (this->numGlobalCoords, this->numLocalCoords, 0, this->comm));
2551 Teuchos::Array<Teuchos::ArrayView<const scalar_t> > coordView(coord_dim);
2552 for (
int i=0; i < coord_dim; i++){
2553 if(numLocalCoords > 0){
2554 Teuchos::ArrayView<const scalar_t> a(coords[i], numLocalCoords);
2557 Teuchos::ArrayView<const scalar_t> a;
2562 tMVector_t *tmVector =
new tMVector_t( mp, coordView.view(0, coord_dim), coord_dim);
2565 dots_.
weights.resize(nWeights);
2568 MEMORY_CHECK(doMemory && rank==0,
"After creating input");
2573 int aok = Zoltan_Initialize(0,NULL, &ver);
2576 printf(
"Zoltan_Initialize failed\n");
2580 struct Zoltan_Struct *zz;
2581 zz = Zoltan_Create(MPI_COMM_WORLD);
2583 Zoltan_Set_Param(zz,
"LB_METHOD",
"RCB");
2584 Zoltan_Set_Param(zz,
"LB_APPROACH",
"PARTITION");
2585 Zoltan_Set_Param(zz,
"CHECK_GEOM",
"0");
2586 Zoltan_Set_Param(zz,
"NUM_GID_ENTRIES",
"1");
2587 Zoltan_Set_Param(zz,
"NUM_LID_ENTRIES",
"0");
2588 Zoltan_Set_Param(zz,
"RETURN_LISTS",
"PART");
2589 std::ostringstream oss;
2590 oss << numGlobalParts;
2591 Zoltan_Set_Param(zz,
"NUM_GLOBAL_PARTS", oss.str().c_str());
2594 Zoltan_Set_Param(zz,
"DEBUG_LEVEL", oss.str().c_str());
2597 Zoltan_Set_Param(zz,
"REMAP",
"1");
2599 Zoltan_Set_Param(zz,
"REMAP",
"0");
2601 if (objective != balanceCount){
2604 Zoltan_Set_Param(zz,
"OBJ_WEIGHT_DIM", oss.str().c_str());
2606 if (objective == mcnorm1)
2607 Zoltan_Set_Param(zz,
"RCB_MULTICRITERIA_NORM",
"1");
2608 else if (objective == mcnorm2)
2609 Zoltan_Set_Param(zz,
"RCB_MULTICRITERIA_NORM",
"2");
2610 else if (objective == mcnorm3)
2611 Zoltan_Set_Param(zz,
"RCB_MULTICRITERIA_NORM",
"3");
2614 Zoltan_Set_Param(zz,
"OBJ_WEIGHT_DIM",
"0");
2617 Zoltan_Set_Num_Obj_Fn(zz, getNumObj<tMVector_t>, &dots_);
2618 Zoltan_Set_Obj_List_Fn(zz, getObjList<tMVector_t>, &dots_);
2619 Zoltan_Set_Num_Geom_Fn(zz, getDim<tMVector_t>, &dots_);
2620 Zoltan_Set_Geom_Multi_Fn(zz, getCoords<tMVector_t>, &dots_);
2622 int changes, numGidEntries, numLidEntries, numImport, numExport;
2623 ZOLTAN_ID_PTR importGlobalGids, importLocalGids;
2624 ZOLTAN_ID_PTR exportGlobalGids, exportLocalGids;
2625 int *importProcs, *importToPart, *exportProcs, *exportToPart;
2627 MEMORY_CHECK(doMemory && rank==0,
"Before Zoltan_LB_Partition");
2630 aok = Zoltan_LB_Partition(zz, &changes, &numGidEntries, &numLidEntries,
2631 &numImport, &importGlobalGids, &importLocalGids,
2632 &importProcs, &importToPart,
2633 &numExport, &exportGlobalGids, &exportLocalGids,
2634 &exportProcs, &exportToPart);
2637 MEMORY_CHECK(doMemory && rank==0,
"After Zoltan_LB_Partition");
2639 for (lno_t i = 0; i < numLocalCoords; i++)
2640 coordinate_grid_parts[i] = exportToPart[i];
2641 Zoltan_Destroy(&zz);
2642 MEMORY_CHECK(doMemory && rank==0,
"After Zoltan_Destroy");
2648 int *coordinate_grid_parts =
new int[this->numLocalCoords];
2649 switch (this->predistribution){
2664 delete []coordinate_grid_parts;
2675 return this->numWeightsPerCoord;
2678 return this->coordinate_dimension;
2681 return this->numLocalCoords;
2684 return this->numGlobalCoords;
2688 return this->coords;
2696 for(
int ii = 0; ii < this->coordinate_dimension; ++ii){
2697 #ifdef HAVE_ZOLTAN2_OMP
2698 #pragma omp parallel for
2700 for (lno_t i = 0; i < this->numLocalCoords; ++i){
2701 c[ii][i] = this->coords[ii][i];
2707 for(
int ii = 0; ii < this->numWeightsPerCoord; ++ii){
2708 #ifdef HAVE_ZOLTAN2_OMP
2709 #pragma omp parallel for
2711 for (lno_t i = 0; i < this->numLocalCoords; ++i){
2712 w[ii][i] = this->wghts[ii][i];
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)
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
void print(T x, T y, T z)
virtual ~CoordinateDistribution()
void getLocalCoordinatesCopy(scalar_t **c)
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)
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_)
scalar_t ** getLocalWeightsView()
SphereHole(CoordinatePoint< T > center_, T edge_)
CircleHole(CoordinatePoint< T > center_, T edge_)
int getCoordinateDimension()
virtual ~RectangularPrismHole()
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)
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[]
scalar_t ** getLocalCoordinatesView()
virtual weighttype getWeight(CoordinatePoint< T > p)
int getDim(void *data, int *ierr)
virtual ~SteppedEquation()
void getObjList(void *data, int numGid, int numLid, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int num_wgts, float *obj_wgts, int *ierr)
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.
CoordinatePoint< T > center
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.
virtual ~WeightDistribution()
PartitioningProblem sets up partitioning problems for the user.
GeometricGenerator(Teuchos::ParameterList ¶ms, const RCP< const Teuchos::Comm< int > > &comm_)
int getNumWeights()
##END Predistribution functions######################//
CoordinatePoint< T > center
#define INVALID_SHAPE_ARG(SHAPE, REQUIRED)
lno_t getNumLocalCoords()
virtual ~CoordinateNormalDistribution()
#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)
virtual ~CoordinateGridDistribution()
gno_t getNumGlobalCoords()
SquareHole(CoordinatePoint< T > center_, T edge_)
void solve(bool updateInputData=true)
Direct the problem to create a solution.
CubeHole(CoordinatePoint< T > center_, T edge_)
void getLocalWeightsCopy(scalar_t **w)
virtual bool isInArea(CoordinatePoint< T > dot)
void getMinMaxCoords(scalar_t *globalMaxCoords, scalar_t *globalMinCoords)
#define MEMORY_CHECK(iPrint, msg)