17 #include <Teuchos_ParameterList.hpp>
18 #include <Teuchos_RCP.hpp>
19 #include <Teuchos_FancyOStream.hpp>
20 #include <Teuchos_CommandLineProcessor.hpp>
21 #include <Tpetra_CrsMatrix.hpp>
22 #include <Tpetra_Vector.hpp>
23 #include <MatrixMarket_Tpetra.hpp>
45 typedef Tpetra::CrsMatrix<z2TestScalar, z2TestLO, z2TestGO>
SparseMatrix;
47 typedef Tpetra::Vector<z2TestScalar, z2TestLO, z2TestGO>
Vector;
48 typedef Vector::node_type
Node;
56 typedef Tpetra::Vector<int, z2TestLO, z2TestGO>
IntVector;
59 #define epsilon 0.00000001
63 int main(
int narg,
char** arg)
65 std::string inputFile =
"";
66 std::string outputFile =
"";
68 std::string method =
"scotch";
70 bool distributeInput =
true;
71 bool haveFailure =
false;
78 Tpetra::ScopeGuard tscope(&narg, &arg);
79 RCP<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
80 int me = comm->getRank();
83 Teuchos::CommandLineProcessor cmdp (
false,
false);
84 cmdp.setOption(
"inputPath", &inputPath,
85 "Path to the MatrixMarket or Zoltan file to be read; "
86 "if not specified, a default path will be used.");
87 cmdp.setOption(
"inputFile", &inputFile,
88 "Name of the Matrix Market or Zoltan file to read; "
89 "if not specified, a matrix will be generated by MueLu.");
90 cmdp.setOption(
"outputFile", &outputFile,
91 "Name of the Matrix Market sparse matrix file to write, "
92 "echoing the input/generated matrix.");
93 cmdp.setOption(
"method", &method,
94 "Partitioning method to use: scotch or parmetis.");
95 cmdp.setOption(
"nparts", &nParts,
96 "Number of parts being requested");
97 cmdp.setOption(
"vertexWeights", &nVwgts,
98 "Number of weights to generate for each vertex");
99 cmdp.setOption(
"edgeWeights", &nEwgts,
100 "Number of weights to generate for each edge");
101 cmdp.setOption(
"verbose",
"quiet", &verbose,
102 "Print messages and results.");
103 cmdp.setOption(
"distribute",
"no-distribute", &distributeInput,
104 "indicate whether or not to distribute "
105 "input across the communicator");
116 std::string matrixType(
"Laplace3D");
118 cmdp.setOption(
"x", &xdim,
119 "number of gridpoints in X dimension for "
120 "mesh used to generate matrix.");
121 cmdp.setOption(
"y", &ydim,
122 "number of gridpoints in Y dimension for "
123 "mesh used to generate matrix.");
124 cmdp.setOption(
"z", &zdim,
125 "number of gridpoints in Z dimension for "
126 "mesh used to generate matrix.");
127 cmdp.setOption(
"matrix", &matrixType,
128 "Matrix type: Laplace1D, Laplace2D, or Laplace3D");
132 int quotientThreshold = -1;
133 cmdp.setOption(
"qthreshold", "ientThreshold,
134 "Threshold on the number of vertices for active MPI ranks to hold"
135 "after the migrating the communication graph to the active ranks.");
139 cmdp.parse(narg, arg);
141 RCP<UserInputForTests> uinput;
145 true, distributeInput));
149 true, distributeInput));
151 RCP<SparseMatrix> origMatrix = uinput->getUITpetraCrsMatrix();
153 if (origMatrix->getGlobalNumRows() < 40) {
154 Teuchos::FancyOStream out(Teuchos::rcp(&std::cout,
false));
155 origMatrix->describe(out, Teuchos::VERB_EXTREME);
159 if (outputFile !=
"") {
161 Tpetra::MatrixMarket::Writer<SparseMatrix>::writeSparseFile(outputFile,
162 origMatrix, verbose);
166 std::cout <<
"NumRows = " << origMatrix->getGlobalNumRows() << std::endl
167 <<
"NumNonzeros = " << origMatrix->getGlobalNumEntries() << std::endl
168 <<
"NumProcs = " << comm->getSize() << std::endl
169 <<
"NumLocalRows (rank 0) = " << origMatrix->getLocalNumRows() << std::endl;
172 RCP<Vector> origVector, origProd;
173 origProd = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>(
174 origMatrix->getRangeMap());
175 origVector = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>(
176 origMatrix->getDomainMap());
177 origVector->randomize();
180 Teuchos::ParameterList params;
182 params.set(
"partitioning_approach",
"partition");
183 params.set(
"algorithm", method);
187 params.set(
"num_global_parts", nParts);
191 if(method ==
"quotient" && quotientThreshold > 0) {
192 params.set(
"quotient_threshold", quotientThreshold);
205 size_t nrows = origMatrix->getLocalNumRows();
208 for (
size_t i = 0; i < nrows; i++) {
209 size_t idx = i * nVwgts;
210 vwgts[idx] =
zscalar_t(origMatrix->getRowMap()->getGlobalElement(i))
212 for (
int j = 1; j < nVwgts; j++) vwgts[idx+j] = 1.;
214 for (
int j = 0; j < nVwgts; j++) {
215 if (j !=
NNZ_IDX) adapter.setVertexWeights(&vwgts[j], nVwgts, j);
216 else adapter.setVertexWeightIsDegree(
NNZ_IDX);
223 size_t nnz = origMatrix->getLocalNumEntries();
225 size_t nrows = origMatrix->getLocalNumRows();
226 size_t maxnzrow = origMatrix->getLocalMaxNumRowEntries();
229 typename SparseMatrix::nonconst_global_inds_host_view_type egids(
"egids", maxnzrow);
230 typename SparseMatrix::nonconst_values_host_view_type evals(
"evals", maxnzrow);
231 for (
size_t i = 0; i < nrows; i++) {
233 z2TestGO gid = origMatrix->getRowMap()->getGlobalElement(i);
234 origMatrix->getGlobalRowCopy(gid, egids, evals, nnzinrow);
235 for (
size_t k = 0; k < nnzinrow; k++) {
236 ewgts[cnt] = (gid < egids[k] ? gid : egids[k]);
237 if (nEwgts > 1) ewgts[cnt+nnz] = (gid < egids[k] ? egids[k] : gid);
238 for (
int j = 2; j < nEwgts; j++) ewgts[cnt+nnz*j] = 1.;
242 for (
int j = 0; j < nEwgts; j++) {
243 adapter.setEdgeWeights(&ewgts[j*nnz], 1, j);
253 if (me == 0) std::cout <<
"Calling solve() " << std::endl;
257 if (me == 0) std::cout <<
"Done solve() " << std::endl;
259 catch (std::runtime_error &e) {
262 std::cout <<
"Runtime exception returned from solve(): " << e.what();
263 if (!strncmp(e.what(),
"BUILD ERROR", 11)) {
265 std::cout <<
" PASS" << std::endl;
270 std::cout <<
" FAIL" << std::endl;
274 catch (std::logic_error &e) {
277 std::cout <<
"Logic exception returned from solve(): " << e.what()
278 <<
" FAIL" << std::endl;
281 catch (std::bad_alloc &e) {
284 std::cout <<
"Bad_alloc exception returned from solve(): " << e.what()
285 <<
" FAIL" << std::endl;
288 catch (std::exception &e) {
291 std::cout <<
"Unknown exception returned from solve(). " << e.what()
292 <<
" FAIL" << std::endl;
298 size_t checkNparts = comm->getSize();
299 if(nParts != -1) checkNparts = size_t(nParts);
300 size_t checkLength = origMatrix->getLocalNumRows();
305 size_t *countPerPart =
new size_t[checkNparts];
306 size_t *globalCountPerPart =
new size_t[checkNparts];
309 for (
size_t i = 0; i < checkNparts; i++) countPerPart[i] = 0;
310 for (
size_t i = 0; i < checkNparts * nVwgts; i++) wtPerPart[i] = 0.;
312 for (
size_t i = 0; i < checkLength; i++) {
313 if (
size_t(checkParts[i]) >= checkNparts)
314 std::cout <<
"Invalid Part " << checkParts[i] <<
": FAIL" << std::endl;
315 countPerPart[checkParts[i]]++;
316 for (
int j = 0; j < nVwgts; j++) {
318 wtPerPart[checkParts[i]*nVwgts+j] += vwgts[i*nVwgts+j];
320 wtPerPart[checkParts[i]*nVwgts+j] += origMatrix->getNumEntriesInLocalRow(i);
325 if(method ==
"quotient") {
326 size_t result = size_t(checkParts[0]);
327 for (
size_t i = 1; i < checkLength; i++) {
328 if (
size_t(checkParts[i]) != result)
329 std::cout <<
"Different parts in the quotient algorithm: "
330 << result <<
"!=" << checkParts[i] <<
": FAIL" << std::endl;
335 Teuchos::reduceAll<int, size_t>(*comm, Teuchos::REDUCE_SUM, checkNparts,
336 countPerPart, globalCountPerPart);
337 Teuchos::reduceAll<int, zscalar_t>(*comm, Teuchos::REDUCE_SUM,
339 wtPerPart, globalWtPerPart);
341 size_t min = std::numeric_limits<std::size_t>::max();
344 size_t minrank = 0, maxrank = 0;
345 for (
size_t i = 0; i < checkNparts; i++) {
346 if (globalCountPerPart[i] < min) {min = globalCountPerPart[i]; minrank = i;}
347 if (globalCountPerPart[i] > max) {max = globalCountPerPart[i]; maxrank = i;}
348 sum += globalCountPerPart[i];
352 float avg = (float) sum / (
float) checkNparts;
353 std::cout <<
"Minimum count: " << min <<
" on rank " << minrank << std::endl;
354 std::cout <<
"Maximum count: " << max <<
" on rank " << maxrank << std::endl;
355 std::cout <<
"Average count: " << avg << std::endl;
356 std::cout <<
"Total count: " << sum
357 << (sum != origMatrix->getGlobalNumRows()
358 ?
"Work was lost; FAIL"
361 std::cout <<
"Imbalance: " << max / avg << std::endl;
363 std::vector<zscalar_t> minwt(nVwgts, std::numeric_limits<zscalar_t>::max());
364 std::vector<zscalar_t> maxwt(nVwgts, 0.);
365 std::vector<zscalar_t> sumwt(nVwgts, 0.);
366 for (
size_t i = 0; i < checkNparts; i++) {
367 for (
int j = 0; j < nVwgts; j++) {
368 size_t idx = i*nVwgts+j;
369 if (globalWtPerPart[idx] < minwt[j]) minwt[j] = globalWtPerPart[idx];
370 if (globalWtPerPart[idx] > maxwt[j]) maxwt[j] = globalWtPerPart[idx];
371 sumwt[j] += globalWtPerPart[idx];
374 for (
int j = 0; j < nVwgts; j++) {
375 float avgwt = (float) sumwt[j] / (
float) checkNparts;
376 std::cout << std::endl;
377 std::cout <<
"Minimum weight[" << j <<
"]: " << minwt[j] << std::endl;
378 std::cout <<
"Maximum weight[" << j <<
"]: " << maxwt[j] << std::endl;
379 std::cout <<
"Average weight[" << j <<
"]: " << avgwt << std::endl;
380 std::cout <<
"Imbalance: " << maxwt[j] / avgwt << std::endl;
385 delete [] countPerPart;
387 delete [] globalCountPerPart;
388 delete [] globalWtPerPart;
394 if (me == 0) std::cout <<
"Redistributing matrix..." << std::endl;
399 if (redistribMatrix->getGlobalNumRows() < 40) {
400 Teuchos::FancyOStream out(Teuchos::rcp(&std::cout,
false));
401 redistribMatrix->describe(out, Teuchos::VERB_EXTREME);
404 if (me == 0) std::cout <<
"Redistributing vectors..." << std::endl;
412 RCP<Vector> redistribProd;
413 redistribProd = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>(
414 redistribMatrix->getRangeMap());
418 RCP<IntVector> origIntVec;
420 origIntVec = Tpetra::createVector<int,z2TestLO,z2TestGO>(
421 origMatrix->getRangeMap());
422 for (
size_t i = 0; i < origIntVec->getLocalLength(); i++)
423 origIntVec->replaceLocalValue(i, me);
428 int origIntNorm = origIntVec->norm1();
429 int redistIntNorm = redistIntVec->norm1();
430 if (me == 0) std::cout <<
"IntegerVectorTest: " << origIntNorm <<
" == "
431 << redistIntNorm <<
" ?";
432 if (origIntNorm != redistIntNorm) {
433 if (me == 0) std::cout <<
" FAIL" << std::endl;
436 else if (me == 0) std::cout <<
" OK" << std::endl;
442 if (me == 0) std::cout <<
"Matvec original..." << std::endl;
443 origMatrix->apply(*origVector, *origProd);
446 std::cout <<
"Norm of Original matvec prod: " << origNorm << std::endl;
448 if (me == 0) std::cout <<
"Matvec redistributed..." << std::endl;
449 redistribMatrix->apply(*redistribVector, *redistribProd);
452 std::cout <<
"Norm of Redistributed matvec prod: " << redistribNorm << std::endl;
454 if (redistribNorm > origNorm+
epsilon || redistribNorm < origNorm-
epsilon) {
459 delete redistribVector;
460 delete redistribMatrix;
464 std::cout <<
"Mat-Vec product changed; FAIL" << std::endl;
468 std::cout <<
"PASS" << std::endl;
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
Tpetra::CrsMatrix< z2TestScalar, z2TestLO, z2TestGO > SparseMatrix
Provides access for Zoltan2 to Xpetra::CrsGraph data.
Zoltan2::XpetraCrsGraphAdapter< SparseGraph > SparseGraphAdapter
int main(int narg, char **arg)
common code used by tests
typename InputTraits< User >::part_t part_t
Tpetra::Vector< z2TestScalar, z2TestLO, z2TestGO > Vector
Defines the XpetraMultiVectorAdapter.
Defines XpetraCrsGraphAdapter class.
Defines the XpetraCrsMatrixAdapter class.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
An adapter for Xpetra::MultiVector.
Tpetra::Map::local_ordinal_type zlno_t
Zoltan2::XpetraMultiVectorAdapter< IntVector > IntVectorAdapter
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
Tpetra::CrsGraph< z2TestLO, z2TestGO > SparseGraph
PartitioningProblem sets up partitioning problems for the user.
Zoltan2::XpetraCrsMatrixAdapter< SparseMatrix > SparseMatrixAdapter
Tpetra::Vector< int, z2TestLO, z2TestGO > IntVector
Defines the PartitioningProblem class.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
Zoltan2::XpetraMultiVectorAdapter< Vector > MultiVectorAdapter
Tpetra::Map::global_ordinal_type zgno_t
void solve(bool updateInputData=true)
Direct the problem to create a solution.
std::string testDataFilePath(".")