Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
scaling/rcbPerformanceZ1.cpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
52 #include "Zoltan2_config.h"
53 #include <zoltan.h>
54 
55 #include <Zoltan2_Util.hpp>
56 
57 #include <Teuchos_RCP.hpp>
58 #include <Teuchos_ArrayView.hpp>
59 #include <Teuchos_ParameterList.hpp>
60 #include <Teuchos_DefaultComm.hpp>
61 #include <Teuchos_Comm.hpp>
62 #include <Teuchos_CommHelpers.hpp>
63 
64 #include <Zoltan2_TestHelpers.hpp>
65 #include <Tpetra_MultiVector.hpp>
66 #include <Tpetra_KokkosCompat_DefaultNode.hpp>
67 #include <GeometricGenerator.hpp>
68 
69 #include <vector>
70 #include <string>
71 #include <ostream>
72 #include <sstream>
73 #include <fstream>
74 using std::string;
75 using std::vector;
76 using std::bad_alloc;
77 using Teuchos::RCP;
78 using Teuchos::rcp;
79 using Teuchos::Comm;
80 using Teuchos::ArrayView;
81 using Teuchos::CommandLineProcessor;
82 
83 typedef Tpetra::MultiVector<zscalar_t, zlno_t, zgno_t, znode_t> tMVector_t;
84 typedef Tpetra::Map<zlno_t, zgno_t, znode_t> tMap_t;
85 typedef tMap_t::node_type znode_t;
86 
88 // Data structure for data
89 typedef struct dots {
90  vector<vector<float> > weights;
92 } DOTS;
93 
94 const char param_comment = '#';
95 
97  const string& s,
98  const string& delimiters = " \f\n\r\t\v" )
99 {
100  return s.substr( 0, s.find_last_not_of( delimiters ) + 1 );
101 }
102 
104  const string& s,
105  const string& delimiters = " \f\n\r\t\v" )
106 {
107  return s.substr( s.find_first_not_of( delimiters ) );
108 }
109 
110 string trim_copy(
111  const string& s,
112  const string& delimiters = " \f\n\r\t\v" )
113 {
114  return trim_left_copy( trim_right_copy( s, delimiters ), delimiters );
115 }
116 
117 void readGeoGenParams(string paramFileName, Teuchos::ParameterList &geoparams, const RCP<const Teuchos::Comm<int> > & comm){
118  std::string input = "";
119  char inp[25000];
120  for(int i = 0; i < 25000; ++i){
121  inp[i] = 0;
122  }
123 
124  bool fail = false;
125  if(comm->getRank() == 0){
126 
127  std::fstream inParam(paramFileName.c_str());
128  if (inParam.fail())
129  {
130  fail = true;
131  }
132  if(!fail)
133  {
134  std::string tmp = "";
135  getline (inParam,tmp);
136  while (!inParam.eof()){
137  if(tmp != ""){
138  tmp = trim_copy(tmp);
139  if(tmp != ""){
140  input += tmp + "\n";
141  }
142  }
143  getline (inParam,tmp);
144  }
145  inParam.close();
146  for (size_t i = 0; i < input.size(); ++i){
147  inp[i] = input[i];
148  }
149  }
150  }
151 
152 
153 
154  int size = input.size();
155  if(fail){
156  size = -1;
157  }
158  comm->broadcast(0, sizeof(int), (char*) &size);
159  if(size == -1){
160  throw "File " + paramFileName + " cannot be opened.";
161  }
162  comm->broadcast(0, size, inp);
163  std::istringstream inParam(inp);
164  string str;
165  getline (inParam,str);
166  while (!inParam.eof()){
167  if(str[0] != param_comment){
168  size_t pos = str.find('=');
169  if(pos == string::npos){
170  throw "Invalid Line:" + str + " in parameter file";
171  }
172  string paramname = trim_copy(str.substr(0,pos));
173  string paramvalue = trim_copy(str.substr(pos + 1));
174  geoparams.set(paramname, paramvalue);
175  }
176  getline (inParam,str);
177  }
178 }
179 
180 
182 // Zoltan1 query functions
183 
184 int getNumObj(void *data, int *ierr)
185 {
186  *ierr = 0;
187  DOTS *dots = (DOTS *) data;
188  return dots->coordinates->getLocalLength();
189 }
190 
192 int getDim(void *data, int *ierr)
193 {
194  *ierr = 0;
195  DOTS *dots = (DOTS *) data;
196  int dim = dots->coordinates->getNumVectors();
197 
198  return dim;
199 }
200 
202 void getObjList(void *data, int numGid, int numLid,
203  ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
204  int num_wgts, float *obj_wgts, int *ierr)
205 {
206  *ierr = 0;
207  DOTS *dots = (DOTS *) data;
208 
209  size_t localLen = dots->coordinates->getLocalLength();
210  const zgno_t *ids =
211  dots->coordinates->getMap()->getLocalElementList().getRawPtr();
212 
213  if (sizeof(ZOLTAN_ID_TYPE) == sizeof(zgno_t))
214  memcpy(gids, ids, sizeof(ZOLTAN_ID_TYPE) * localLen);
215  else
216  for (size_t i=0; i < localLen; i++)
217  gids[i] = static_cast<ZOLTAN_ID_TYPE>(ids[i]);
218 
219  if (num_wgts > 0){
220  float *wgts = obj_wgts;
221  for (size_t i=0; i < localLen; i++)
222  for (int w=0; w < num_wgts; w++)
223  *wgts++ = dots->weights[w][i];
224  }
225 }
226 
228 void getCoords(void *data, int numGid, int numLid,
229  int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids,
230  int dim, double *coords, int *ierr)
231 {
232  // I know that Zoltan asks for coordinates in gid order.
233  if (dim == 3){
234  *ierr = 0;
235  DOTS *dots = (DOTS *) data;
236  double *val = coords;
237  const zscalar_t *x = dots->coordinates->getData(0).getRawPtr();
238  const zscalar_t *y = dots->coordinates->getData(1).getRawPtr();
239  const zscalar_t *z = dots->coordinates->getData(2).getRawPtr();
240  for (int i=0; i < numObj; i++){
241  *val++ = static_cast<double>(x[i]);
242  *val++ = static_cast<double>(y[i]);
243  *val++ = static_cast<double>(z[i]);
244  }
245  }
246  else {
247  *ierr = 0;
248  DOTS *dots = (DOTS *) data;
249  double *val = coords;
250  const zscalar_t *x = dots->coordinates->getData(0).getRawPtr();
251  const zscalar_t *y = dots->coordinates->getData(1).getRawPtr();
252  for (int i=0; i < numObj; i++){
253  *val++ = static_cast<double>(x[i]);
254  *val++ = static_cast<double>(y[i]);
255  }
256 
257 
258  }
259 }
260 
261 
263 
269 };
270 
272  const RCP<const Teuchos::Comm<int> > & comm,
273  vector<float> &wgts, weightTypes how, float scale, int rank)
274 {
275  zlno_t len = wgts.size();
276  if (how == upDown){
277  float val = scale + rank%2;
278  for (zlno_t i=0; i < len; i++)
279  wgts[i] = val;
280  }
281  else if (how == roundRobin){
282  for (int i=0; i < 10; i++){
283  float val = (i + 10)*scale;
284  for (zlno_t j=i; j < len; j += 10)
285  wgts[j] = val;
286  }
287  }
288  else if (how == increasing){
289  float val = scale + rank;
290  for (zlno_t i=0; i < len; i++)
291  wgts[i] = val;
292  }
293 }
294 
296 /* Create a mesh of approximately the desired size.
297  *
298  * We want 3 dimensions close to equal in length.
299  */
301  const RCP<const Teuchos::Comm<int> > & comm,
302  zgno_t numGlobalCoords)
303 {
304  int rank = comm->getRank();
305  int nprocs = comm->getSize();
306 
307  double k = log(numGlobalCoords) / 3;
308  double xdimf = exp(k) + 0.5;
309  ssize_t xdim = static_cast<ssize_t>(floor(xdimf));
310  ssize_t ydim = xdim;
311  ssize_t zdim = numGlobalCoords / (xdim*ydim);
312  ssize_t num=xdim*ydim*zdim;
313  ssize_t diff = numGlobalCoords - num;
314  ssize_t newdiff = 0;
315 
316  while (diff > 0){
317  if (zdim > xdim && zdim > ydim){
318  zdim++;
319  newdiff = diff - (xdim*ydim);
320  if (newdiff < 0)
321  if (diff < -newdiff)
322  zdim--;
323  }
324  else if (ydim > xdim && ydim > zdim){
325  ydim++;
326  newdiff = diff - (xdim*zdim);
327  if (newdiff < 0)
328  if (diff < -newdiff)
329  ydim--;
330  }
331  else{
332  xdim++;
333  newdiff = diff - (ydim*zdim);
334  if (newdiff < 0)
335  if (diff < -newdiff)
336  xdim--;
337  }
338 
339  diff = newdiff;
340  }
341 
342  num=xdim*ydim*zdim;
343  diff = numGlobalCoords - num;
344  if (diff < 0)
345  diff /= -numGlobalCoords;
346  else
347  diff /= numGlobalCoords;
348 
349  if (rank == 0){
350  if (diff > .01)
351  std::cout << "Warning: Difference " << diff*100 << " percent" << std::endl;
352  std::cout << "Mesh size: " << xdim << "x" << ydim << "x" <<
353  zdim << ", " << num << " vertices." << std::endl;
354  }
355 
356  // Divide coordinates.
357 
358  ssize_t numLocalCoords = num / nprocs;
359  ssize_t leftOver = num % nprocs;
360  ssize_t gid0 = 0;
361 
362  if (rank <= leftOver)
363  gid0 = rank * (numLocalCoords+1);
364  else
365  gid0 = (leftOver * (numLocalCoords+1)) +
366  ((rank - leftOver) * numLocalCoords);
367 
368  if (rank < leftOver)
369  numLocalCoords++;
370 
371  ssize_t gid1 = gid0 + numLocalCoords;
372 
373  zgno_t *ids = new zgno_t[numLocalCoords];
374  if (!ids)
375  throw bad_alloc();
376  ArrayView<zgno_t> idArray(ids, numLocalCoords);
377  zgno_t *idptr = ids;
378 
379  for (ssize_t i=gid0; i < gid1; i++)
380  *idptr++ = zgno_t(i);
381 
382  RCP<const tMap_t> idMap = rcp(new tMap_t(num, idArray, 0, comm));
383 
384  delete [] ids;
385 
386  // Create a Tpetra::MultiVector of coordinates.
387 
388  zscalar_t *x = new zscalar_t [numLocalCoords*3];
389  if (!x) throw bad_alloc();
390 
391  zscalar_t *y = x + numLocalCoords;
392  zscalar_t *z = y + numLocalCoords;
393 
394  zgno_t xStart = 0;
395  zgno_t yStart = 0;
396  zgno_t xyPlane = xdim*ydim;
397  zgno_t zStart = gid0 / xyPlane;
398  zgno_t rem = gid0 % xyPlane;
399  if (rem > 0){
400  yStart = rem / xdim;
401  xStart = rem % xdim;
402  }
403 
404  zlno_t next = 0;
405  for (zscalar_t zval=zStart; next < numLocalCoords && zval < zdim; zval+=1.){
406  for (zscalar_t yval=yStart; next < numLocalCoords && yval < ydim; yval+=1.){
407  for (zscalar_t xval=xStart; next < numLocalCoords && xval < xdim;xval+=1.){
408  x[next] = xval;
409  y[next] = yval;
410  z[next] = zval;
411  next++;
412  }
413  xStart = 0;
414  }
415  yStart = 0;
416  }
417 
418  ArrayView<const zscalar_t> xArray(x, numLocalCoords*3);
419  tMVector_t *dots = new tMVector_t(idMap, xArray, numLocalCoords, 3);
420 
421  delete [] x;
422  return dots;
423 }
424 
425 
426 int main(int narg, char *arg[])
427 {
428  // MEMORY_CHECK(true, "Before initializing MPI");
429 
430  Tpetra::ScopeGuard tscope(&narg, &arg);
431  Teuchos::RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
432  int rank = comm->getRank();
433  int nprocs = comm->getSize();
434  DOTS dots;
435 
436  MEMORY_CHECK(rank==0 || rank==nprocs-1, "After initializing MPI");
437 
438  if (rank==0)
439  std::cout << "Number of processes: " << nprocs << std::endl;
440 
441  // Default values
442  zgno_t numGlobalCoords = 1000;
443  int nWeights = 0;
444  int debugLevel=2;
445  string memoryOn("memoryOn");
446  string memoryOff("memoryOff");
447  bool doMemory=false;
448  int numGlobalParts = nprocs;
449  int dummyTimer=0;
450  bool remap=0;
451 
452  string balanceCount("balance_object_count");
453  string balanceWeight("balance_object_weight");
454  string mcnorm1("multicriteria_minimize_total_weight");
455  string mcnorm2("multicriteria_balance_total_maximum");
456  string mcnorm3("multicriteria_minimize_maximum_weight");
457  string objective(balanceWeight); // default
458 
459  // Process command line input
460  CommandLineProcessor commandLine(false, true);
461  //commandLine.setOption("size", &numGlobalCoords,
462  // "Approximate number of global coordinates.");
463  int input_option = 0;
464  commandLine.setOption("input_option", &input_option,
465  "whether to use mesh creation, geometric generator, or file input");
466  string inputFile = "";
467 
468  commandLine.setOption("input_file", &inputFile,
469  "the input file for geometric generator or file input");
470 
471 
472  commandLine.setOption("size", &numGlobalCoords,
473  "Approximate number of global coordinates.");
474  commandLine.setOption("numParts", &numGlobalParts,
475  "Number of parts (default is one per proc).");
476  commandLine.setOption("nWeights", &nWeights,
477  "Number of weights per coordinate, zero implies uniform weights.");
478  commandLine.setOption("debug", &debugLevel, "Zoltan1 debug level");
479  commandLine.setOption("remap", "no-remap", &remap,
480  "Zoltan1 REMAP parameter; disabled by default for scalability testing");
481  commandLine.setOption("timers", &dummyTimer, "ignored");
482  commandLine.setOption(memoryOn.c_str(), memoryOff.c_str(), &doMemory,
483  "do memory profiling");
484 
485  string doc(balanceCount);
486  doc.append(": ignore weights\n");
487  doc.append(balanceWeight);
488  doc.append(": balance on first weight\n");
489  doc.append(mcnorm1);
490  doc.append(": given multiple weights, balance their total.\n");
491  doc.append(mcnorm3);
492  doc.append(": given multiple weights, "
493  "balance the maximum for each coordinate.\n");
494  doc.append(mcnorm2);
495  doc.append(": given multiple weights, balance the L2 norm of the weights.\n");
496  commandLine.setOption("objective", &objective, doc.c_str());
497 
498  CommandLineProcessor::EParseCommandLineReturn rc =
499  commandLine.parse(narg, arg);
500 
501 
502 
503  if (rc != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) {
504  if (rc == Teuchos::CommandLineProcessor::PARSE_HELP_PRINTED) {
505  if (rank==0) std::cout << "PASS" << std::endl;
506  return 1;
507  }
508  else {
509  if (rank==0) std::cout << "FAIL" << std::endl;
510  return 0;
511  }
512  }
513 
514  //MEMORY_CHECK(doMemory && rank==0, "After processing parameters");
515 
516  // Create the data structure
517  size_t numLocalCoords = 0;
518  if (input_option == 0){
519  dots.coordinates = makeMeshCoordinates(comm, numGlobalCoords);
520  numLocalCoords = dots.coordinates->getLocalLength();
521 
522 #if 0
523  comm->barrier();
524  for (int p=0; p < nprocs; p++){
525  if (p==rank){
526  std::cout << "Rank " << rank << ", " << numLocalCoords << "coords" << std::endl;
527  const zscalar_t *x = coordinates->getData(0).getRawPtr();
528  const zscalar_t *y = coordinates->getData(1).getRawPtr();
529  const zscalar_t *z = coordinates->getData(2).getRawPtr();
530  for (zlno_t i=0; i < numLocalCoords; i++)
531  std::cout << " " << x[i] << " " << y[i] << " " << z[i] << std::endl;
532  }
533  std::cout.flush();
534  comm->barrier();
535  }
536 #endif
537 
538  if (nWeights > 0){
539 
540  dots.weights.resize(nWeights);
541 
542  int wt = 0;
543  float scale = 1.0;
544  for (int i=0; i < nWeights; i++){
545  dots.weights[i].resize(numLocalCoords);
546  makeWeights(comm, dots.weights[i], weightTypes(wt++), scale, rank);
547 
548  if (wt == numWeightTypes){
549  wt = 0;
550  scale++;
551  }
552  }
553  }
554  }
555  else if(input_option == 1){
556  Teuchos::ParameterList geoparams("geo params");
557  readGeoGenParams(inputFile, geoparams, comm);
559 
560  int coord_dim = gg->getCoordinateDimension();
561  nWeights = gg->getNumWeights();
562  numLocalCoords = gg->getNumLocalCoords();
563  numGlobalCoords = gg->getNumGlobalCoords();
564  zscalar_t **coords = new zscalar_t * [coord_dim];
565  for(int i = 0; i < coord_dim; ++i){
566  coords[i] = new zscalar_t[numLocalCoords];
567  }
568  gg->getLocalCoordinatesCopy(coords);
569  zscalar_t **weight = NULL;
570  if(nWeights){
571  weight= new zscalar_t * [nWeights];
572  for(int i = 0; i < nWeights; ++i){
573  weight[i] = new zscalar_t[numLocalCoords];
574  }
575  gg->getLocalWeightsCopy(weight);
576  }
577 
578  delete gg;
579 
580  RCP<Tpetra::Map<zlno_t, zgno_t, znode_t> > mp = rcp(
581  new Tpetra::Map<zlno_t, zgno_t, znode_t> (numGlobalCoords, numLocalCoords, 0, comm));
582 
583  Teuchos::Array<Teuchos::ArrayView<const zscalar_t> > coordView(coord_dim);
584  for (int i=0; i < coord_dim; i++){
585  if(numLocalCoords > 0){
586  Teuchos::ArrayView<const zscalar_t> a(coords[i], numLocalCoords);
587  coordView[i] = a;
588  } else{
589  Teuchos::ArrayView<const zscalar_t> a;
590  coordView[i] = a;
591  }
592  }
593 
594  tMVector_t *tmVector = new tMVector_t( mp, coordView.view(0, coord_dim), coord_dim);
595 
596  dots.coordinates = tmVector;
597  dots.weights.resize(nWeights);
598 
599  if(nWeights){
600  for (int i = 0; i < nWeights;++i){
601  for (zlno_t j = 0; j < zlno_t(numLocalCoords); ++j){
602  dots.weights[i].push_back(weight[i][j]);
603  }
604  }
605  }
606  if(nWeights){
607  for(int i = 0; i < nWeights; ++i)
608  delete [] weight[i];
609  delete [] weight;
610  }
611  }
612  else {
613 
614  UserInputForTests uinput(testDataFilePath, inputFile, comm, true);
615  RCP<tMVector_t> coords = uinput.getUICoordinates();
616  tMVector_t *newMulti = new tMVector_t(*coords);
617  dots.coordinates = newMulti;
618  numLocalCoords = coords->getLocalLength();
619  numGlobalCoords = coords->getGlobalLength();
620  }
621 
622  MEMORY_CHECK(doMemory && rank==0, "After creating input");
623 
624  // Now call Zoltan to partition the problem.
625 
626  float ver;
627  int aok = Zoltan_Initialize(narg, arg, &ver);
628 
629  if (aok != 0){
630  printf("Zoltan_Initialize failed\n");
631  exit(0);
632  }
633 
634  struct Zoltan_Struct *zz;
635  zz = Zoltan_Create(MPI_COMM_WORLD);
636 
637  Zoltan_Set_Param(zz, "LB_METHOD", "RCB");
638  Zoltan_Set_Param(zz, "LB_APPROACH", "PARTITION");
639  Zoltan_Set_Param(zz, "CHECK_GEOM", "0");
640  Zoltan_Set_Param(zz, "NUM_GID_ENTRIES", "1");
641  Zoltan_Set_Param(zz, "NUM_LID_ENTRIES", "0");
642  Zoltan_Set_Param(zz, "RETURN_LISTS", "PART");
643  std::ostringstream oss;
644  oss << numGlobalParts;
645  Zoltan_Set_Param(zz, "NUM_GLOBAL_PARTS", oss.str().c_str());
646  oss.str("");
647  oss << debugLevel;
648  Zoltan_Set_Param(zz, "DEBUG_LEVEL", oss.str().c_str());
649 
650  if (remap)
651  Zoltan_Set_Param(zz, "REMAP", "1");
652  else
653  Zoltan_Set_Param(zz, "REMAP", "0");
654 
655  if (objective != balanceCount){
656  oss.str("");
657  oss << nWeights;
658  Zoltan_Set_Param(zz, "OBJ_WEIGHT_DIM", oss.str().c_str());
659 
660  if (objective == mcnorm1)
661  Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "1");
662  else if (objective == mcnorm2)
663  Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "2");
664  else if (objective == mcnorm3)
665  Zoltan_Set_Param(zz, "RCB_MULTICRITERIA_NORM", "3");
666  }
667  else{
668  Zoltan_Set_Param(zz, "OBJ_WEIGHT_DIM", "0");
669  }
670 
671  Zoltan_Set_Num_Obj_Fn(zz, getNumObj, &dots);
672  Zoltan_Set_Obj_List_Fn(zz, getObjList, &dots);
673  Zoltan_Set_Num_Geom_Fn(zz, getDim, &dots);
674  Zoltan_Set_Geom_Multi_Fn(zz, getCoords, &dots);
675 
676  int changes, numGidEntries, numLidEntries, numImport, numExport;
677  ZOLTAN_ID_PTR importGlobalGids, importLocalGids;
678  ZOLTAN_ID_PTR exportGlobalGids, exportLocalGids;
679  int *importProcs, *importToPart, *exportProcs, *exportToPart;
680 
681  MEMORY_CHECK(doMemory && rank==0, "Before Zoltan_LB_Partition");
682 
683  if (rank == 0) std::cout << "Calling Zoltan_LB_Partition" << std::endl;
684  aok = Zoltan_LB_Partition(zz, &changes, &numGidEntries, &numLidEntries,
685  &numImport, &importGlobalGids, &importLocalGids,
686  &importProcs, &importToPart,
687  &numExport, &exportGlobalGids, &exportLocalGids,
688  &exportProcs, &exportToPart);
689  if (rank == 0) std::cout << "Returned from Zoltan_LB_Partition" << std::endl;
690 
691  MEMORY_CHECK(doMemory && rank==0, "After Zoltan_LB_Partition");
692 
693  /* Print the load-balance stats here */
694 
695  float *sumWgtPerPart = new float[numGlobalParts];
696  float *gsumWgtPerPart = new float[numGlobalParts];
697  for (int i = 0; i < numGlobalParts; i++) sumWgtPerPart[i] = 0.;
698 
699  for (size_t i = 0; i < numLocalCoords; i++)
700  sumWgtPerPart[exportToPart[i]] += (nWeights ? dots.weights[0][i]: 1.);
701 
702  Teuchos::reduceAll<int, float>(*comm, Teuchos::REDUCE_SUM, numGlobalParts,
703  sumWgtPerPart, gsumWgtPerPart);
704 
705  float maxSumWgtPerPart = 0.;
706  float minSumWgtPerPart = std::numeric_limits<float>::max();
707  float totWgt = 0.;
708  int maxSumWgtPart=0, minSumWgtPart=0;
709  for (int i = 0; i < numGlobalParts; i++) {
710  if (gsumWgtPerPart[i] > maxSumWgtPerPart) {
711  maxSumWgtPerPart = gsumWgtPerPart[i];
712  maxSumWgtPart = i;
713  }
714  if (gsumWgtPerPart[i] < minSumWgtPerPart) {
715  minSumWgtPerPart = gsumWgtPerPart[i];
716  minSumWgtPart = i;
717  }
718  totWgt += gsumWgtPerPart[i];
719  }
720 
721  if (rank == 0)
722  std::cout << std::endl << std::endl
723  << "Part loads (per part for " << numGlobalParts << " parts):"
724  << std::endl
725  << " min = " << minSumWgtPerPart
726  << " in part " << minSumWgtPart << std::endl
727  << " max = " << maxSumWgtPerPart
728  << " in part " << maxSumWgtPart << std::endl
729  << " tot = " << totWgt << std::endl
730  << " avg = " << totWgt / numGlobalParts
731  << std::endl << std::endl << std::endl;
732 
733  delete [] sumWgtPerPart;
734  delete [] gsumWgtPerPart;
735 
736  Zoltan_Destroy(&zz);
737  MEMORY_CHECK(doMemory && rank==0, "After Zoltan_Destroy");
738 
739  delete dots.coordinates;
740  for (int i = 0; i < nWeights; i++)
741  dots.weights[i].clear();
742  dots.weights.clear();
743 
744  MEMORY_CHECK(doMemory && rank==0, "After destroying input");
745 
746  if (rank==0){
747  if (aok != 0)
748  std::cout << "FAIL" << std::endl;
749  else
750  std::cout << "PASS" << std::endl;
751  }
752 
753  return 0;
754 }
void getCoords(void *data, int numGid, int numLid, int numObj, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int dim, double *coords_, int *ierr)
string trim_right_copy(const string &s, const string &delimiters=" \f\n\r\t\v")
tMVector_t * makeMeshCoordinates(const RCP< const Teuchos::Comm< int > > &comm, zgno_t numGlobalCoords)
void readGeoGenParams(string paramFileName, Teuchos::ParameterList &geoparams, const RCP< const Teuchos::Comm< int > > &comm)
tMVector_t * coordinates
int main(int narg, char **arg)
Definition: coloring1.cpp:199
common code used by tests
string trim_copy(const string &s, const string &delimiters=" \f\n\r\t\v")
const char param_comment
struct dots DOTS
ArrayRCP< zscalar_t > makeWeights(const RCP< const Teuchos::Comm< int > > &comm, zlno_t len, weightTypes how, zscalar_t scale, int rank)
int getNumObj(void *data, int *ierr)
static RCP< tMVector_t > coordinates
int getDim(void *data, int *ierr)
vector< vector< float > > weights
void getObjList(void *data, int numGid, int numLid, ZOLTAN_ID_PTR gids, ZOLTAN_ID_PTR lids, int num_wgts, float *obj_wgts, int *ierr)
Tpetra::Map::local_ordinal_type zlno_t
static const std::string fail
Tpetra::Map< zlno_t, zgno_t, znode_t > tMap_t
string trim_left_copy(const string &s, const string &delimiters=" \f\n\r\t\v")
int getNumWeights()
##END Predistribution functions######################//
RCP< tMVector_t > getUICoordinates()
float zscalar_t
A gathering of useful namespace methods.
Tpetra::Map::node_type znode_t
Tpetra::MultiVector< zscalar_t, zlno_t, zgno_t, znode_t > tMVector_t
Tpetra::Map::global_ordinal_type zgno_t
#define MEMORY_CHECK(iPrint, msg)
std::string testDataFilePath(".")