10 #ifndef GEOMETRICGENERATOR
11 #define GEOMETRICGENERATOR
13 #include <Teuchos_Comm.hpp>
14 #include <Teuchos_ParameterList.hpp>
15 #include <Teuchos_FilteredIterator.hpp>
16 #include <Teuchos_ParameterEntry.hpp>
25 #include <Tpetra_MultiVector_decl.hpp>
28 #include <Teuchos_ArrayViewDecl.hpp>
29 #include <Teuchos_RCP.hpp>
30 #include <Tpetra_Distributor.hpp>
41 using Teuchos::CommandLineProcessor;
42 using Teuchos::ArrayView;
44 using Teuchos::ArrayRCP;
46 namespace GeometricGen{
47 #define CATCH_EXCEPTIONS(pp) \
48 catch (std::runtime_error &e) { \
49 std::cout << "Runtime exception returned from " << pp << ": " \
50 << e.what() << " FAIL" << std::endl; \
53 catch (std::logic_error &e) { \
54 std::cout << "Logic exception returned from " << pp << ": " \
55 << e.what() << " FAIL" << std::endl; \
58 catch (std::bad_alloc &e) { \
59 std::cout << "Bad_alloc exception returned from " << pp << ": " \
60 << e.what() << " FAIL" << std::endl; \
63 catch (std::exception &e) { \
64 std::cout << "Unknown exception returned from " << pp << ": " \
65 << e.what() << " FAIL" << std::endl; \
72 template <
typename tMVector_t>
79 template <
typename tMVector_t>
87 template <
typename tMVector_t>
89 int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
90 int dim,
double *coords_,
int *ierr)
92 typedef typename tMVector_t::scalar_type scalar_t;
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]);
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]);
121 template <
typename tMVector_t>
132 template <
typename tMVector_t>
134 ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
135 int num_wgts,
float *obj_wgts,
int *ierr)
137 typedef typename tMVector_t::global_ordinal_type
gno_t;
142 size_t localLen = dots_->
coordinates->getLocalLength();
144 dots_->
coordinates->getMap()->getLocalElementList().getRawPtr();
146 if (
sizeof(ZOLTAN_ID_TYPE) ==
sizeof(gno_t))
147 memcpy(gids, ids,
sizeof(ZOLTAN_ID_TYPE) * localLen);
149 for (
size_t i=0; i < localLen; i++)
150 gids[i] = static_cast<ZOLTAN_ID_TYPE>(ids[i]);
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];
162 const std::string
shapes[] = {
"SQUARE",
"RECTANGLE",
"CIRCLE",
"CUBE",
"RECTANGULAR_PRISM",
"SPHERE"};
163 #define SHAPE_COUNT 6
167 #define DISTRIBUTION_COUNT 2
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"
174 #define INVALID_SHAPE_ARG(SHAPE, REQUIRED) "Invalid argument count for shape " + SHAPE + ". Requires " + REQUIRED + " argument(s)."
175 #define MAX_ITER_ALLOWED 500
179 template <
typename T>
212 template <
typename T>
221 this->
edge1 = edge1_;
222 this->
edge2 = edge2_;
223 this->
edge3 = edge3_;
229 template <
typename T>
235 return fabs(dot.
x - this->center.x) < this->
edge1 / 2 && fabs(dot.
y - this->center.y) < this->
edge1 / 2;
239 template <
typename T>
244 return fabs(dot.
x - this->center.x) < this->
edge1 / 2 && fabs(dot.
y - this->center.y) < this->
edge2 / 2;
249 template <
typename T>
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;
259 template <
typename T>
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;
269 template <
typename T>
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;
279 template <
typename T>
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))
293 template <
typename T,
typename weighttype>
322 template <
typename T,
typename weighttype>
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>(){
346 this->stepCount = stepCount_;
347 if(this->stepCount > 0){
348 this->steps =
new T[this->stepCount];
349 this->values =
new T[this->stepCount + 1];
351 for (
int i = 0; i < this->stepCount; ++i){
352 this->steps[i] = steps_[i];
353 this->values[i] = values_[i];
355 this->values[this->stepCount] = values_[this->stepCount];
361 if(this->stepCount > 0){
362 delete [] this->steps;
363 delete [] this->values;
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];
374 return this->values[this->stepCount];
377 return weighttype(expressionRes);
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];
387 return this->values[this->stepCount];
390 return weighttype(expressionRes);
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;
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;
405 if(this->stepCount > 0){
406 for (
int i = 0; i < this->stepCount; ++i){
407 if (expressionRes < this->steps[i]) {
409 return this->values[i];
414 return this->values[this->stepCount];
417 return weighttype(expressionRes);
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];
427 return this->values[this->stepCount];
430 return weighttype(expressionRes);
435 template <
typename T,
typename lno_t,
typename gno_t>
455 float *sharedRatios_,
int myRank){
457 for (
int i = 0; i < myRank; ++i){
460 if (i < this->numPoints % this->
worldSize){
467 unsigned int slice = UINT_MAX/(this->
worldSize);
468 unsigned int stateBegin = myRank * slice;
473 #ifdef HAVE_ZOLTAN2_OMP
479 #ifdef HAVE_ZOLTAN2_OMP
480 me = omp_get_thread_num();
481 tsize = omp_get_num_threads();
483 unsigned int state = stateBegin + me * slice/(tsize);
485 #ifdef HAVE_ZOLTAN2_OMP
488 for(
lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
492 throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
496 bool isInHole =
false;
497 for(
lno_t i = 0; i < holeCount; ++i){
498 if(holes[i][0].isInArea(p)){
503 if(isInHole)
continue;
544 float *sharedRatios_,
int myRank){
546 for (
int i = 0; i < myRank; ++i){
556 unsigned int slice = UINT_MAX/(this->
worldSize);
557 unsigned int stateBegin = myRank * slice;
558 #ifdef HAVE_ZOLTAN2_OMP
564 #ifdef HAVE_ZOLTAN2_OMP
565 me = omp_get_thread_num();
566 tsize = omp_get_num_threads();
568 unsigned int state = stateBegin + me * (slice/(tsize));
576 #ifdef HAVE_ZOLTAN2_OMP
579 for(
lno_t cnt = 0; cnt < requestedPointcount; ++cnt){
583 throw "Max number of Iteration is reached for point creation. Check the area criteria or hole coordinates.";
587 bool isInHole =
false;
588 for(
lno_t i = 0; i < holeCount; ++i){
589 if(holes[i][0].isInArea(p)){
594 if(isInHole)
continue;
595 coords[0][cnt + tindex] = p.
x;
597 coords[1][cnt + tindex] = p.
y;
599 coords[2][cnt + tindex] = p.
z;
609 template <
typename T,
typename lno_t,
typename gno_t>
626 T sd_x, T sd_y, T sd_z,
int wSize) :
640 for(
int i = 0; i < this->
dimension; ++i){
643 p.
x = normalDist(this->
center.x, this->standartDevx, state);
646 p.
y = normalDist(this->
center.y, this->standartDevy, state);
649 p.
z = normalDist(this->
center.z, this->standartDevz, state);
652 throw "unsupported dimension";
660 T normalDist(T center_, T sd,
unsigned int &state) {
661 T polarsqrt, normalsquared, normal1, normal2;
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);
668 polarsqrt=sqrt(-2.0*log(normalsquared)/normalsquared);
669 return normal2*polarsqrt*sd + center_;
673 template <
typename T,
typename lno_t,
typename gno_t>
693 T l_z, T r_z,
int wSize ) :
704 for(
int i = 0; i < this->
dimension; ++i){
716 throw "unsupported dimension";
724 T uniformDist(T a, T b,
unsigned int &state)
726 return (b-a)*(rand_r(&state) / double(RAND_MAX)) + a;
730 template <
typename T,
typename lno_t,
typename gno_t>
755 T l_x, T r_x, T l_y, T r_y, T l_z, T r_z ,
756 int myRank_,
int wSize) :
856 template <
typename scalar_t,
typename lno_t,
typename gno_t,
typename node_t>
861 int coordinate_dimension;
862 gno_t numGlobalCoords;
863 lno_t numLocalCoords;
864 float *loadDistributions;
866 bool distinctCoordSet;
868 int distributionCount;
873 int numWeightsPerCoord;
875 RCP<const Teuchos::Comm<int> > comm;
887 float perturbation_ratio;
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;
893 template <
typename tt>
894 tt getParamVal(
const Teuchos::ParameterEntry& pe,
const std::string ¶mname){
897 returnVal = Teuchos::getValue<tt>(pe);
905 int countChar (std::string inStr,
char cntChar){
907 for (
unsigned int i = 0; i < inStr.size(); ++i){
908 if (inStr[i] == cntChar) {
915 template <
typename tt>
916 tt fromString(std::string obj){
917 std::stringstream ss (std::stringstream::in | std::stringstream::out);
922 throw "Cannot convert string " + obj;
928 void splitString(std::string inStr,
char splitChar, std::string *outSplittedStr){
929 std::stringstream ss (std::stringstream::in | std::stringstream::out);
933 std::string tmp =
"";
934 std::getline(ss, tmp ,splitChar);
935 outSplittedStr[cnt++] = tmp;
972 void getCoordinateDistributions(std::string coordinate_distributions){
973 if(coordinate_distributions ==
""){
974 throw "At least one distribution function must be provided to coordinate generator.";
977 int argCnt = this->countChar(coordinate_distributions,
',') + 1;
978 std::string *splittedStr =
new std::string[argCnt];
979 splitString(coordinate_distributions,
',', splittedStr);
981 for(
int i = 0; i < argCnt; ){
984 std::string distName = splittedStr[i++];
986 if(distName ==
"NORMAL"){
988 if (this->coordinate_dimension == 3){
991 if(i + reqArg > argCnt) {
992 std::string tmp = Teuchos::toString<int>(reqArg);
995 np_ = fromString<gno_t>(splittedStr[i++]);
998 pp.
x = fromString<scalar_t>(splittedStr[i++]);
999 pp.y = fromString<scalar_t>(splittedStr[i++]);
1001 if(this->coordinate_dimension == 3){
1002 pp.z = fromString<scalar_t>(splittedStr[i++]);
1005 scalar_t sd_x = fromString<scalar_t>(splittedStr[i++]);
1006 scalar_t sd_y = fromString<scalar_t>(splittedStr[i++]);
1008 if(this->coordinate_dimension == 3){
1009 sd_z = fromString<scalar_t>(splittedStr[i++]);
1013 }
else if(distName ==
"UNIFORM" ){
1015 if (this->coordinate_dimension == 3){
1018 if(i + reqArg > argCnt) {
1019 std::string tmp = Teuchos::toString<int>(reqArg);
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++]);
1028 scalar_t l_z = 0, r_z = 0;
1030 if(this->coordinate_dimension == 3){
1031 l_z = fromString<scalar_t>(splittedStr[i++]);
1032 r_z = fromString<scalar_t>(splittedStr[i++]);
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"){
1038 if(this->coordinate_dimension == 3){
1041 if(i + reqArg > argCnt) {
1042 std::string tmp = Teuchos::toString<int>(reqArg);
1046 gno_t np_x = fromString<gno_t>(splittedStr[i++]);
1047 gno_t np_y = fromString<gno_t>(splittedStr[i++]);
1051 if(this->coordinate_dimension == 3){
1052 np_z = fromString<gno_t>(splittedStr[i++]);
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++]);
1061 scalar_t l_z = 0, r_z = 0;
1063 if(this->coordinate_dimension == 3){
1064 l_z = fromString<scalar_t>(splittedStr[i++]);
1065 r_z = fromString<scalar_t>(splittedStr[i++]);
1068 if(np_x < 1 || np_z < 1 || np_y < 1 ){
1069 throw "Provide at least 1 point along each dimension for grid test.";
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);
1077 std::string tmp = Teuchos::toString<int>(this->coordinate_dimension);
1080 this->numGlobalCoords += (
gno_t) np_;
1082 delete []splittedStr;
1085 void getProcLoadDistributions(std::string proc_load_distributions){
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;
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);
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]);
1105 delete []splittedStr;
1109 for(
int i = 0; i < this->worldSize; ++i){
1110 sum += this->loadDistributions[i];
1113 throw "Processor load ratios do not sum to 1.0.";
1119 void getHoles(std::string holeDescription){
1120 if(holeDescription ==
""){
1124 int argCnt = this->countChar(holeDescription,
',') + 1;
1125 std::string *splittedStr =
new std::string[argCnt];
1126 splitString(holeDescription,
',', splittedStr);
1128 for(
int i = 0; i < argCnt; ){
1131 std::string shapeName = splittedStr[i++];
1132 if(shapeName ==
"SQUARE" && this->coordinate_dimension == 2){
1133 if(i + 3 > argCnt) {
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++]);
1141 }
else if(shapeName ==
"RECTANGLE" && this->coordinate_dimension == 2){
1142 if(i + 4 > argCnt) {
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++]);
1152 }
else if(shapeName ==
"CIRCLE" && this->coordinate_dimension == 2){
1153 if(i + 3 > argCnt) {
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++]);
1161 }
else if(shapeName ==
"CUBE" && this->coordinate_dimension == 3){
1162 if(i + 4 > argCnt) {
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++]);
1171 }
else if(shapeName ==
"RECTANGULAR_PRISM" && this->coordinate_dimension == 3){
1172 if(i + 6 > argCnt) {
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++]);
1184 }
else if(shapeName ==
"SPHERE" && this->coordinate_dimension == 3){
1185 if(i + 4 > argCnt) {
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++]);
1195 std::string tmp = Teuchos::toString<int>(this->coordinate_dimension);
1199 delete [] splittedStr;
1202 void getWeightDistribution(std::string *weight_distribution_arr,
int wdimension){
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.";
1213 int count = this->countChar(weight_distribution,
' ');
1214 std::string *splittedStr =
new string[count + 1];
1215 this->splitString(weight_distribution,
' ', splittedStr);
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;
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];
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];
1237 if (parameter ==
"a1"){
1238 a1 = this->fromString<scalar_t>(value);
1240 else if (parameter ==
"a2"){
1241 if(this->coordinate_dimension > 1){
1242 a2 = this->fromString<scalar_t>(value);
1245 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1249 else if (parameter ==
"a3"){
1250 if(this->coordinate_dimension > 2){
1251 a3 = this->fromString<scalar_t>(value);
1254 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1257 else if (parameter ==
"b1"){
1258 b1 = this->fromString<scalar_t>(value);
1260 else if (parameter ==
"b2"){
1261 if(this->coordinate_dimension > 1){
1262 b2 = this->fromString<scalar_t>(value);
1265 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1268 else if (parameter ==
"b3"){
1270 if(this->coordinate_dimension > 2){
1271 b3 = this->fromString<scalar_t>(value);
1274 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1277 else if (parameter ==
"c"){
1278 c = this->fromString<scalar_t>(value);
1280 else if (parameter ==
"x1"){
1281 x1 = this->fromString<scalar_t>(value);
1283 else if (parameter ==
"y1"){
1284 if(this->coordinate_dimension > 1){
1285 y1 = this->fromString<scalar_t>(value);
1288 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
1291 else if (parameter ==
"z1"){
1292 if(this->coordinate_dimension > 2){
1293 z1 = this->fromString<scalar_t>(value);
1296 throw parameter+
" argument is not valid when dimension is " + Teuchos::toString<int>(this->coordinate_dimension);
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]);
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]);
1320 throw "Invalid parameter name at " + splittedStr[i];
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);
1330 this->wd[wcount++] =
new SteppedEquation<scalar_t,scalar_t>(a1, a2, a3, b1, b2, b3, c, x1, y1, z1, steps, values, stepCount);
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.";
1343 void parseParams(
const Teuchos::ParameterList & params){
1345 std::string holeDescription =
"";
1346 std::string proc_load_distributions =
"";
1347 std::string distinctDescription =
"";
1348 std::string coordinate_distributions =
"";
1351 numWeightsPerCoord_parameters[i] =
"";
1355 for (Teuchos::ParameterList::ConstIterator pit = params.begin(); pit != params.end(); ++pit ){
1356 const std::string ¶mName = params.name(pit);
1358 const Teuchos::ParameterEntry &pe = params.entry(pit);
1360 if(paramName.find(
"hole-") == 0){
1361 if(holeDescription ==
""){
1362 holeDescription = getParamVal<std::string>(pe, paramName);
1365 holeDescription +=
","+getParamVal<std::string>(pe, paramName);
1368 else if(paramName.find(
"distribution-") == 0){
1369 if(coordinate_distributions ==
"")
1370 coordinate_distributions = getParamVal<std::string>(pe, paramName);
1372 coordinate_distributions +=
","+getParamVal<std::string>(pe, paramName);
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);
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);
1386 numWeightsPerCoord_parameters[distribution_index] +=
" " + weight_dist_param.substr(dash_pos + 1)+
"="+ getParamVal<std::string>(pe, paramName);
1388 else if(paramName ==
"dim"){
1389 int dim = fromString<int>(getParamVal<std::string>(pe, paramName));
1390 if(dim < 2 || dim > 3){
1393 this->coordinate_dimension = dim;
1396 else if(paramName ==
"wdim"){
1397 int dim = fromString<int>(getParamVal<std::string>(pe, paramName));
1398 if(dim < 1 && dim > MAX_WEIGHT_DIM){
1401 this->numWeightsPerCoord = dim;
1404 else if(paramName ==
"predistribution"){
1405 int pre_distribution = fromString<int>(getParamVal<std::string>(pe, paramName));
1406 if(pre_distribution < 0 || pre_distribution > 3){
1409 this->predistribution = pre_distribution;
1412 else if(paramName ==
"perturbation_ratio"){
1413 float perturbation = fromString<float>(getParamVal<std::string>(pe, paramName));
1414 if(perturbation < 0 && perturbation > 1){
1417 this->perturbation_ratio = perturbation;
1422 else if(paramName ==
"proc_load_distributions"){
1423 proc_load_distributions = getParamVal<std::string>(pe, paramName);
1424 this->loadDistSet =
true;
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;
1434 throw "Invalid parameter for distinct_coordinates: " + distinctDescription +
". Candidates: T or F." ;
1438 else if(paramName ==
"out_file"){
1439 this->outfile = getParamVal<std::string>(pe, paramName);
1448 if(this->coordinate_dimension == 0){
1449 throw "Dimension must be provided to coordinate generator.";
1468 if (this->loadDistSet && this->distinctCoordSet){
1469 throw "distinct_coordinates and proc_load_distributions parameters cannot be satisfied together.";
1471 this->getHoles(holeDescription);
1473 this->getProcLoadDistributions(proc_load_distributions);
1474 this->getCoordinateDistributions(coordinate_distributions);
1475 this->getWeightDistribution(numWeightsPerCoord_parameters, this->numWeightsPerCoord);
1482 catch(std::string &s){
1483 throw std::runtime_error(s);
1486 catch(
const char *s){
1487 throw std::runtime_error(s);
1494 for (
int i = 0; i < this->holeCount; ++i){
1495 delete this->holes[i];
1501 delete []loadDistributions;
1503 if(coordinateDistributions){
1505 for (
int i = 0; i < this->distributionCount; ++i){
1506 delete this->coordinateDistributions[i];
1508 free (this->coordinateDistributions);
1511 for (
int i = 0; i < this->numWeightsPerCoord; ++i){
1517 if(this->numWeightsPerCoord){
1518 for(
int i = 0; i < this->numWeightsPerCoord; ++i)
1519 delete [] this->wghts[i];
1520 delete []this->wghts;
1522 if(this->coordinate_dimension){
1523 for(
int i = 0; i < this->coordinate_dimension; ++i)
1524 delete [] this->coords[i];
1525 delete [] this->coords;
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;
1574 this->coordinate_dimension = 0;
1575 this->numWeightsPerCoord = 0;
1576 this->worldSize = comm_->getSize();
1577 this->numGlobalCoords = 0;
1578 this->loadDistributions = NULL;
1580 this->coordinateDistributions = NULL;
1581 this->holeCount = 0;
1582 this->distributionCount = 0;
1584 this->predistribution = 0;
1585 this->perturbation_ratio = 0;
1596 this->loadDistSet =
false;
1597 this->distinctCoordSet =
false;
1598 this->myRank = comm_->getRank();
1601 this->parseParams(params);
1603 catch(std::string &s){
1607 throw std::runtime_error(s);
1610 catch(
const char *s){
1614 throw std::runtime_error(s);
1618 lno_t myPointCount = 0;
1619 this->numGlobalCoords = 0;
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){
1628 this->numGlobalCoords += increment;
1630 prefixSum += increment;
1633 myPointCount +=
lno_t(this->coordinateDistributions[i]->numPoints * this->loadDistributions[myRank]);
1634 if (
gno_t(myRank) < this->coordinateDistributions[i]->numPoints % this->worldSize){
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];
1644 for (
int ii = 0; ii < this->coordinate_dimension; ++ii){
1645 #ifdef HAVE_ZOLTAN2_OMP
1646 #pragma omp parallel for
1648 for(
lno_t i = 0; i < myPointCount; ++i){
1649 this->coords[ii][i] = 0;
1653 this->numLocalCoords = 0;
1654 srand ((myRank + 1) * this->numLocalCoords);
1655 for (
int i = 0; i < distributionCount; ++i){
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;
1663 this->coordinateDistributions[i]->
GetPoints(requestedPointCount,this->coords, this->numLocalCoords, this->holes, this->holeCount, this->loadDistributions, myRank);
1664 this->numLocalCoords += requestedPointCount;
1686 if (this->predistribution){
1693 if (this->perturbation_ratio > 0){
1715 if (this->distinctCoordSet){
1719 if(this->outfile !=
""){
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){
1725 myfile << this->coords[0][i];
1726 if(this->coordinate_dimension > 1){
1727 myfile <<
" " << this->coords[1][i];
1729 if(this->coordinate_dimension > 2){
1730 myfile <<
" " << this->coords[2][i];
1732 myfile << std::endl;
1736 if (this->myRank == 0){
1737 std::ofstream gnuplotfile(
"gnu.gnuplot");
1738 for(
int i = 0; i < this->worldSize; ++i){
1740 if (this->coordinate_dimension == 2){
1746 gnuplotfile << s <<
" \"" << (this->outfile + Teuchos::toString<int>(i)) <<
"\"" << std::endl;
1748 gnuplotfile <<
"pause -1" << std::endl;
1749 gnuplotfile.close();
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];
1769 for(
int ii = 0; ii < this->numWeightsPerCoord; ++ii){
1770 switch(this->coordinate_dimension){
1773 #ifdef HAVE_ZOLTAN2_OMP
1774 #pragma omp parallel for
1776 for (
lno_t i = 0; i < this->numLocalCoords; ++i){
1777 this->wghts[ii][i] = this->wd[ii]->
get1DWeight(this->coords[0][i]);
1783 #ifdef HAVE_ZOLTAN2_OMP
1784 #pragma omp parallel for
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]);
1793 #ifdef HAVE_ZOLTAN2_OMP
1794 #pragma omp parallel for
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]);
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];
1818 if (maxCoords[dim] < this->coords[dim][i]){
1819 maxCoords[dim] = this->coords[dim][i];
1826 scalar_t center = (maxCoords[dim] + minCoords[dim]) / 2;
1828 minCoords[dim] = center - (center - minCoords[dim]) * scale;
1829 maxCoords[dim] = (maxCoords[dim] - center) * scale + center;
1833 gno_t numLocalToPerturb =
gno_t(this->numLocalCoords*used_perturbation_ratio);
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];
1851 void getBestSurface (
int remaining,
int *dimProcs,
int dim,
int currentDim,
int &bestSurface,
int *bestDimProcs){
1853 if (currentDim < dim - 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);
1865 dimProcs[currentDim] = remaining;
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];
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];
1887 if (maxCoords[dim] < this->coords[dim][i]){
1888 maxCoords[dim] = this->coords[dim][i];
1893 reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MAX,
1894 this->coordinate_dimension,
1899 reduceAll<int, scalar_t>( *(this->comm), Teuchos::REDUCE_MIN,
1900 this->coordinate_dimension,
1914 typedef SSIZE_T ssize_t;
1921 scalar_t *maxCoords=
new scalar_t [this->coordinate_dimension];
1922 scalar_t *minCoords=
new scalar_t [this->coordinate_dimension];
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];
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];
1942 getBestSurface ( remaining, dimProcs, coord_dim, currentDim, bestSurface, bestDimProcs);
1950 int *shiftProcCount =
new int[coord_dim];
1954 int remainingProc = this->worldSize;
1955 for (
int dim = 0; dim < coord_dim; ++dim){
1956 remainingProc = remainingProc / bestDimProcs[dim];
1957 shiftProcCount[dim] = remainingProc;
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;
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];
1975 gno_t *partBegins =
new gno_t [this->worldSize];
1976 gno_t *partNext =
new gno_t[this->numLocalCoords];
1979 for (
lno_t i = 0; i < this->numLocalCoords; ++i){
1982 for (
int i = 0; i < this->worldSize; ++i) {
1986 for (
int i = 0; i < this->worldSize; ++i)
1987 numPointsInParts[i] = 0;
1989 for (
lno_t i = 0; i < this->numLocalCoords; ++i){
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;
1996 shift = shift * shiftProcCount[dim];
1999 numPointsInParts[partIndex] += 1;
2000 coordinate_grid_parts[i] = partIndex;
2002 partNext[i] = partBegins[partIndex];
2003 partBegins[partIndex] = i;
2010 reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
2013 numGlobalPointsInParts);
2016 Teuchos::scan<int,gno_t>(
2017 *(this->comm), Teuchos::REDUCE_SUM,
2020 numPointsInPartsInclusiveUptoMyIndex
2039 gno_t optimal_num =
gno_t(this->numGlobalCoords/
double(this->worldSize)+0.5);
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];
2047 std::cout <<
"Total:" << totalSize <<
" ng:" << this->numGlobalCoords << std::endl;
2048 std::cout <<
"optimal_num:" << optimal_num << std::endl;
2051 ssize_t *extraInPart =
new ssize_t [this->worldSize];
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];
2058 if (extraExchange != 0){
2060 if (extraExchange < 0) addition = 1;
2061 for (ssize_t i = 0; i < extraExchange; ++i){
2062 extraInPart[i % this->worldSize] += addition;
2070 int overloadedPartCount = 0;
2071 int *overloadedPartIndices =
new int [this->worldSize];
2074 int underloadedPartCount = 0;
2075 int *underloadedPartIndices =
new int [this->worldSize];
2077 for (
int i = 0; i < this->worldSize; ++i){
2078 if(extraInPart[i] > 0){
2079 overloadedPartIndices[overloadedPartCount++] = i;
2081 else if(extraInPart[i] < 0){
2082 underloadedPartIndices[underloadedPartCount++] = i;
2086 int underloadpartindex = underloadedPartCount - 1;
2089 int numPartsISendFrom = 0;
2090 int *mySendFromParts =
new int[this->worldSize * 2];
2091 gno_t *mySendFromPartsCounts =
new gno_t[this->worldSize * 2];
2093 int numPartsISendTo = 0;
2094 int *mySendParts =
new int[this->worldSize * 2];
2095 gno_t *mySendCountsToParts =
new gno_t[this->worldSize * 2];
2104 for (
int i = overloadedPartCount - 1; i >= 0; --i){
2107 int overloadPart = overloadedPartIndices[i];
2108 gno_t overload = extraInPart[overloadPart];
2109 gno_t myload = numPointsInParts[overloadPart];
2113 gno_t inclusiveLoadUpToMe = numPointsInPartsInclusiveUptoMyIndex[overloadPart];
2116 gno_t exclusiveLoadUptoMe = inclusiveLoadUpToMe - myload;
2119 if (exclusiveLoadUptoMe >= overload){
2123 overloadedPartIndices[i] = -1;
2124 extraInPart[overloadPart] = 0;
2126 while (overload > 0){
2127 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2128 ssize_t underload = extraInPart[nextUnderLoadedPart];
2129 ssize_t left = overload + underload;
2132 extraInPart[nextUnderLoadedPart] = 0;
2133 underloadedPartIndices[underloadpartindex--] = -1;
2136 extraInPart[nextUnderLoadedPart] = left;
2141 else if (exclusiveLoadUptoMe < overload){
2144 gno_t mySendCount = overload - exclusiveLoadUptoMe;
2146 gno_t sendAfterMe = 0;
2149 if (mySendCount > myload){
2150 sendAfterMe = mySendCount - myload;
2151 mySendCount = myload;
2157 mySendFromParts[numPartsISendFrom] = overloadPart;
2158 mySendFromPartsCounts[numPartsISendFrom++] = mySendCount;
2161 while (exclusiveLoadUptoMe > 0){
2162 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2163 ssize_t underload = extraInPart[nextUnderLoadedPart];
2164 ssize_t left = exclusiveLoadUptoMe + underload;
2167 extraInPart[nextUnderLoadedPart] = 0;
2168 underloadedPartIndices[underloadpartindex--] = -1;
2171 extraInPart[nextUnderLoadedPart] = left;
2173 exclusiveLoadUptoMe = left;
2177 while (mySendCount > 0){
2178 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2179 ssize_t underload = extraInPart[nextUnderLoadedPart];
2180 ssize_t left = mySendCount + underload;
2183 mySendParts[numPartsISendTo] = nextUnderLoadedPart;
2184 mySendCountsToParts[numPartsISendTo++] = -underload;
2186 extraInPart[nextUnderLoadedPart] = 0;
2187 underloadedPartIndices[underloadpartindex--] = -1;
2190 extraInPart[nextUnderLoadedPart] = left;
2192 mySendParts[numPartsISendTo] = nextUnderLoadedPart;
2193 mySendCountsToParts[numPartsISendTo++] = mySendCount;
2199 while (sendAfterMe > 0){
2200 int nextUnderLoadedPart = underloadedPartIndices[underloadpartindex];
2201 ssize_t underload = extraInPart[nextUnderLoadedPart];
2202 ssize_t left = sendAfterMe + underload;
2205 extraInPart[nextUnderLoadedPart] = 0;
2206 underloadedPartIndices[underloadpartindex--] = -1;
2209 extraInPart[nextUnderLoadedPart] = left;
2220 for (
int i = 0 ; i < numPartsISendFrom; ++i){
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];
2229 int sendCountToThisPart = mySendCountsToParts[partToSendIndex];
2233 if (sendCountToThisPart <= sendCount){
2234 mySendParts[partToSendIndex] = 0;
2235 mySendCountsToParts[partToSendIndex] = 0;
2237 sendCount -= sendCountToThisPart;
2240 mySendCountsToParts[partToSendIndex] = sendCountToThisPart - sendCount;
2241 sendCountToThisPart = sendCount;
2246 gno_t toChange = partBegins[sendFromPart];
2247 gno_t previous_begin = partBegins[partToSend];
2250 for (
int k = 0; k < sendCountToThisPart - 1; ++k){
2251 coordinate_grid_parts[toChange] = partToSend;
2252 toChange = partNext[toChange];
2254 coordinate_grid_parts[toChange] = partToSend;
2256 gno_t newBegin = partNext[toChange];
2257 partNext[toChange] = previous_begin;
2258 partBegins[partToSend] = partBegins[sendFromPart];
2259 partBegins[sendFromPart] = newBegin;
2268 for (
int i = 0; i < this->worldSize; ++i) numPointsInParts[i] = 0;
2270 for (
int i = 0; i < this->numLocalCoords; ++i){
2271 numPointsInParts[coordinate_grid_parts[i]] += 1;
2274 reduceAll<int, gno_t>( *(this->comm), Teuchos::REDUCE_SUM,
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];
2285 std::cout <<
"Total:" << totalSize <<
" ng:" << this->numGlobalCoords << std::endl;
2288 delete []mySendCountsToParts;
2289 delete []mySendParts;
2290 delete []mySendFromPartsCounts;
2291 delete []mySendFromParts;
2292 delete []underloadedPartIndices;
2293 delete []overloadedPartIndices;
2294 delete []extraInPart;
2296 delete []partBegins;
2297 delete []numPointsInPartsInclusiveUptoMyIndex;
2298 delete []numPointsInParts;
2299 delete []numGlobalPointsInParts;
2301 delete []shiftProcCount;
2302 delete []bestDimProcs;
2303 delete []dim_slices;
2312 Tpetra::Distributor distributor(comm);
2313 ArrayView<const int> pIds( coordinate_grid_parts, this->numLocalCoords);
2314 gno_t numMyNewGnos = distributor.createFromSends(pIds);
2317 Kokkos::View<scalar_t*, Kokkos::HostSpace> recvBuf2(
2318 Kokkos::ViewAllocateWithoutInitializing(
"recvBuf2"),
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);
2327 distributor.doPostsAndWaits(s, 1, recvBuf2);
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];
2336 this->numLocalCoords = numMyNewGnos;
2341 int coord_dim = this->coordinate_dimension;
2343 lno_t numLocalPoints = this->numLocalCoords;
2344 gno_t numGlobalPoints = this->numGlobalCoords;
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));
2352 Teuchos::Array<Teuchos::ArrayView<const scalar_t> > coordView(coord_dim);
2356 for (
int i=0; i < coord_dim; i++){
2357 if(numLocalPoints > 0){
2358 Teuchos::ArrayView<const scalar_t> a(coords[i], numLocalPoints);
2361 Teuchos::ArrayView<const scalar_t> a;
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));
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;
2376 inputAdapter_t ia(coordsConst,weights, stride);
2378 Teuchos::RCP <Teuchos::ParameterList> params ;
2379 params =RCP <Teuchos::ParameterList> (
new Teuchos::ParameterList,
true);
2382 params->set(
"algorithm",
"multijagged");
2383 params->set(
"num_global_parts", this->worldSize);
2395 #ifdef HAVE_ZOLTAN2_MPI
2411 for (
lno_t i = 0; i < this->numLocalCoords;++i){
2412 coordinate_grid_parts[i] = partIds[i];
2421 int rank = this->myRank;
2422 int nprocs = this->worldSize;
2425 MEMORY_CHECK(rank==0 || rank==nprocs-1,
"After initializing MPI");
2430 string memoryOn(
"memoryOn");
2431 string memoryOff(
"memoryOff");
2432 bool doMemory=
false;
2433 int numGlobalParts = nprocs;
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);
2445 CommandLineProcessor commandLine(
false,
true);
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 =
"";
2453 commandLine.setOption(
"input_file", &inputFile,
2454 "the input file for geometric generator or file input");
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");
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());
2483 CommandLineProcessor::EParseCommandLineReturn rc =
2484 commandLine.parse(0, NULL);
2488 if (rc != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
2489 if (rc == Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED) {
2490 if (rank==0) std::cout <<
"PASS" << std::endl;
2494 if (rank==0) std::cout <<
"FAIL" << std::endl;
2503 int coord_dim = this->coordinate_dimension;
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));
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);
2515 Teuchos::ArrayView<const scalar_t> a;
2520 tMVector_t *tmVector =
new tMVector_t( mp, coordView.view(0, coord_dim), coord_dim);
2523 dots_.
weights.resize(nWeights);
2526 MEMORY_CHECK(doMemory && rank==0,
"After creating input");
2531 int aok = Zoltan_Initialize(0,NULL, &ver);
2534 printf(
"Zoltan_Initialize failed\n");
2538 struct Zoltan_Struct *zz;
2539 zz = Zoltan_Create(MPI_COMM_WORLD);
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());
2552 Zoltan_Set_Param(zz,
"DEBUG_LEVEL", oss.str().c_str());
2555 Zoltan_Set_Param(zz,
"REMAP",
"1");
2557 Zoltan_Set_Param(zz,
"REMAP",
"0");
2559 if (objective != balanceCount){
2562 Zoltan_Set_Param(zz,
"OBJ_WEIGHT_DIM", oss.str().c_str());
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");
2572 Zoltan_Set_Param(zz,
"OBJ_WEIGHT_DIM",
"0");
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_);
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;
2585 MEMORY_CHECK(doMemory && rank==0,
"Before Zoltan_LB_Partition");
2588 aok = Zoltan_LB_Partition(zz, &changes, &numGidEntries, &numLidEntries,
2589 &numImport, &importGlobalGids, &importLocalGids,
2590 &importProcs, &importToPart,
2591 &numExport, &exportGlobalGids, &exportLocalGids,
2592 &exportProcs, &exportToPart);
2595 MEMORY_CHECK(doMemory && rank==0,
"After Zoltan_LB_Partition");
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");
2606 int *coordinate_grid_parts =
new int[this->numLocalCoords];
2607 switch (this->predistribution){
2622 delete []coordinate_grid_parts;
2633 return this->numWeightsPerCoord;
2636 return this->coordinate_dimension;
2639 return this->numLocalCoords;
2642 return this->numGlobalCoords;
2646 return this->coords;
2654 for(
int ii = 0; ii < this->coordinate_dimension; ++ii){
2655 #ifdef HAVE_ZOLTAN2_OMP
2656 #pragma omp parallel for
2658 for (
lno_t i = 0; i < this->numLocalCoords; ++i){
2659 c[ii][i] = this->coords[ii][i];
2665 for(
int ii = 0; ii < this->numWeightsPerCoord; ++ii){
2666 #ifdef HAVE_ZOLTAN2_OMP
2667 #pragma omp parallel for
2669 for (
lno_t i = 0; i < this->numLocalCoords; ++i){
2670 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)
map_t::global_ordinal_type gno_t
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)
map_t::local_ordinal_type lno_t
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_)
Tpetra::MultiVector< zscalar_t, zlno_t, zgno_t, znode_t > tMVector_t
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)