52 #include <Teuchos_ParameterList.hpp> 53 #include <Teuchos_RCP.hpp> 54 #include <Teuchos_FancyOStream.hpp> 55 #include <Teuchos_CommandLineProcessor.hpp> 56 #include <Tpetra_CrsMatrix.hpp> 57 #include <Tpetra_DefaultPlatform.hpp> 58 #include <Tpetra_Vector.hpp> 59 #include <MatrixMarket_Tpetra.hpp> 82 typedef Tpetra::CrsMatrix<z2TestScalar, z2TestLO, z2TestGO>
SparseMatrix;
84 typedef Tpetra::Vector<z2TestScalar, z2TestLO, z2TestGO>
Vector;
85 typedef Vector::node_type
Node;
93 typedef Tpetra::Vector<int, z2TestLO, z2TestGO>
IntVector;
96 #define epsilon 0.00000001 102 std::string inputFile =
"";
103 std::string outputFile =
"";
105 std::string method =
"scotch";
106 bool verbose =
false;
107 bool distributeInput =
true;
108 bool haveFailure =
false;
114 Teuchos::GlobalMPISession mpiSession(&narg, &arg, NULL);
115 RCP<const Teuchos::Comm<int> > comm =
116 Tpetra::DefaultPlatform::getDefaultPlatform().getComm();
117 int me = comm->getRank();
120 Teuchos::CommandLineProcessor cmdp (
false,
false);
121 cmdp.setOption(
"inputPath", &inputPath,
122 "Path to the MatrixMarket or Zoltan file to be read; " 123 "if not specified, a default path will be used.");
124 cmdp.setOption(
"inputFile", &inputFile,
125 "Name of the Matrix Market or Zoltan file to read; " 126 "if not specified, a matrix will be generated by MueLu.");
127 cmdp.setOption(
"outputFile", &outputFile,
128 "Name of the Matrix Market sparse matrix file to write, " 129 "echoing the input/generated matrix.");
130 cmdp.setOption(
"method", &method,
131 "Partitioning method to use: scotch or parmetis.");
132 cmdp.setOption(
"vertexWeights", &nVwgts,
133 "Number of weights to generate for each vertex");
134 cmdp.setOption(
"edgeWeights", &nEwgts,
135 "Number of weights to generate for each edge");
136 cmdp.setOption(
"verbose",
"quiet", &verbose,
137 "Print messages and results.");
138 cmdp.setOption(
"distribute",
"no-distribute", &distributeInput,
139 "indicate whether or not to distribute " 140 "input across the communicator");
151 std::string matrixType(
"Laplace3D");
153 cmdp.setOption(
"x", &xdim,
154 "number of gridpoints in X dimension for " 155 "mesh used to generate matrix.");
156 cmdp.setOption(
"y", &ydim,
157 "number of gridpoints in Y dimension for " 158 "mesh used to generate matrix.");
159 cmdp.setOption(
"z", &zdim,
160 "number of gridpoints in Z dimension for " 161 "mesh used to generate matrix.");
162 cmdp.setOption(
"matrix", &matrixType,
163 "Matrix type: Laplace1D, Laplace2D, or Laplace3D");
166 cmdp.parse(narg, arg);
168 RCP<UserInputForTests> uinput;
172 true, distributeInput));
176 true, distributeInput));
178 RCP<SparseMatrix> origMatrix = uinput->getUITpetraCrsMatrix();
180 if (origMatrix->getGlobalNumRows() < 40) {
181 Teuchos::FancyOStream out(Teuchos::rcp(&std::cout,
false));
182 origMatrix->describe(out, Teuchos::VERB_EXTREME);
186 if (outputFile !=
"") {
188 Tpetra::MatrixMarket::Writer<SparseMatrix>::writeSparseFile(outputFile,
189 origMatrix, verbose);
193 cout <<
"NumRows = " << origMatrix->getGlobalNumRows() << endl
194 <<
"NumNonzeros = " << origMatrix->getGlobalNumEntries() << endl
195 <<
"NumProcs = " << comm->getSize() << endl
196 <<
"NumLocalRows (rank 0) = " << origMatrix->getNodeNumRows() << endl;
199 RCP<Vector> origVector, origProd;
200 origProd = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>(
201 origMatrix->getRangeMap());
202 origVector = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>(
203 origMatrix->getDomainMap());
204 origVector->randomize();
207 Teuchos::ParameterList params;
209 params.set(
"partitioning_approach",
"partition");
210 params.set(
"algorithm", method);
222 size_t nrows = origMatrix->getNodeNumRows();
225 for (
size_t i = 0; i < nrows; i++) {
226 size_t idx = i * nVwgts;
227 vwgts[idx] =
zscalar_t(origMatrix->getRowMap()->getGlobalElement(i))
229 for (
int j = 1; j < nVwgts; j++) vwgts[idx+j] = 1.;
231 for (
int j = 0; j < nVwgts; j++) {
232 if (j !=
NNZ_IDX) adapter.setVertexWeights(&vwgts[j], nVwgts, j);
233 else adapter.setVertexWeightIsDegree(
NNZ_IDX);
240 size_t nnz = origMatrix->getNodeNumEntries();
242 size_t nrows = origMatrix->getNodeNumRows();
243 size_t maxnzrow = origMatrix->getNodeMaxNumRowEntries();
246 Array<z2TestGO> egids(maxnzrow);
247 Array<zscalar_t> evals(maxnzrow);
248 for (
size_t i = 0; i < nrows; i++) {
250 z2TestGO gid = origMatrix->getRowMap()->getGlobalElement(i);
251 origMatrix->getGlobalRowCopy(gid, egids(), evals(), nnzinrow);
252 for (
size_t k = 0; k < nnzinrow; k++) {
253 ewgts[cnt] = (gid < egids[k] ? gid : egids[k]);
254 if (nEwgts > 1) ewgts[cnt+nnz] = (gid < egids[k] ? egids[k] : gid);
255 for (
int j = 2; j < nEwgts; j++) ewgts[cnt+nnz*j] = 1.;
259 for (
int j = 0; j < nEwgts; j++) {
260 adapter.setEdgeWeights(&ewgts[j*nnz], 1, j);
270 if (me == 0) cout <<
"Calling solve() " << endl;
274 if (me == 0) cout <<
"Done solve() " << endl;
276 catch (std::runtime_error &e) {
279 cout <<
"Runtime exception returned from solve(): " << e.what();
280 if (!strncmp(e.what(),
"BUILD ERROR", 11)) {
282 cout <<
" PASS" << endl;
287 cout <<
" FAIL" << endl;
291 catch (std::logic_error &e) {
294 cout <<
"Logic exception returned from solve(): " << e.what()
298 catch (std::bad_alloc &e) {
301 cout <<
"Bad_alloc exception returned from solve(): " << e.what()
305 catch (std::exception &e) {
308 cout <<
"Unknown exception returned from solve(). " << e.what()
315 size_t checkNparts = comm->getSize();
317 size_t checkLength = origMatrix->getNodeNumRows();
321 size_t *countPerPart =
new size_t[checkNparts];
322 size_t *globalCountPerPart =
new size_t[checkNparts];
325 for (
size_t i = 0; i < checkNparts; i++) countPerPart[i] = 0;
326 for (
size_t i = 0; i < checkNparts * nVwgts; i++) wtPerPart[i] = 0.;
328 for (
size_t i = 0; i < checkLength; i++) {
329 if (
size_t(checkParts[i]) >= checkNparts)
330 cout <<
"Invalid Part " << checkParts[i] <<
": FAIL" << endl;
331 countPerPart[checkParts[i]]++;
332 for (
int j = 0; j < nVwgts; j++) {
334 wtPerPart[checkParts[i]*nVwgts+j] += vwgts[i*nVwgts+j];
336 wtPerPart[checkParts[i]*nVwgts+j] += origMatrix->getNumEntriesInLocalRow(i);
339 Teuchos::reduceAll<int, size_t>(*comm, Teuchos::REDUCE_SUM, checkNparts,
340 countPerPart, globalCountPerPart);
341 Teuchos::reduceAll<int, zscalar_t>(*comm, Teuchos::REDUCE_SUM,
343 wtPerPart, globalWtPerPart);
345 size_t min = std::numeric_limits<std::size_t>::max();
348 size_t minrank = 0, maxrank = 0;
349 for (
size_t i = 0; i < checkNparts; i++) {
350 if (globalCountPerPart[i] < min) {min = globalCountPerPart[i]; minrank = i;}
351 if (globalCountPerPart[i] > max) {max = globalCountPerPart[i]; maxrank = i;}
352 sum += globalCountPerPart[i];
356 float avg = (float) sum / (
float) checkNparts;
357 cout <<
"Minimum count: " << min <<
" on rank " << minrank << endl;
358 cout <<
"Maximum count: " << max <<
" on rank " << maxrank << endl;
359 cout <<
"Average count: " << avg << endl;
360 cout <<
"Total count: " << sum
361 << (sum != origMatrix->getGlobalNumRows()
362 ?
"Work was lost; FAIL" 365 cout <<
"Imbalance: " << max / avg << endl;
367 std::vector<zscalar_t> minwt(nVwgts, std::numeric_limits<zscalar_t>::max());
368 std::vector<zscalar_t> maxwt(nVwgts, 0.);
369 std::vector<zscalar_t> sumwt(nVwgts, 0.);
370 for (
size_t i = 0; i < checkNparts; i++) {
371 for (
int j = 0; j < nVwgts; j++) {
372 size_t idx = i*nVwgts+j;
373 if (globalWtPerPart[idx] < minwt[j]) minwt[j] = globalWtPerPart[idx];
374 if (globalWtPerPart[idx] > maxwt[j]) maxwt[j] = globalWtPerPart[idx];
375 sumwt[j] += globalWtPerPart[idx];
378 for (
int j = 0; j < nVwgts; j++) {
379 float avgwt = (float) sumwt[j] / (
float) checkNparts;
381 cout <<
"Minimum weight[" << j <<
"]: " << minwt[j] << endl;
382 cout <<
"Maximum weight[" << j <<
"]: " << maxwt[j] << endl;
383 cout <<
"Average weight[" << j <<
"]: " << avgwt << endl;
384 cout <<
"Imbalance: " << maxwt[j] / avgwt << endl;
389 delete [] countPerPart;
391 delete [] globalCountPerPart;
392 delete [] globalWtPerPart;
398 if (me == 0) cout <<
"Redistributing matrix..." << endl;
403 if (redistribMatrix->getGlobalNumRows() < 40) {
404 Teuchos::FancyOStream out(Teuchos::rcp(&std::cout,
false));
405 redistribMatrix->describe(out, Teuchos::VERB_EXTREME);
408 if (me == 0) cout <<
"Redistributing vectors..." << endl;
416 RCP<Vector> redistribProd;
417 redistribProd = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>(
418 redistribMatrix->getRangeMap());
422 RCP<IntVector> origIntVec;
424 origIntVec = Tpetra::createVector<int,z2TestLO,z2TestGO>(
425 origMatrix->getRangeMap());
426 for (
size_t i = 0; i < origIntVec->getLocalLength(); i++)
427 origIntVec->replaceLocalValue(i, me);
432 int origIntNorm = origIntVec->norm1();
433 int redistIntNorm = redistIntVec->norm1();
434 if (me == 0) std::cout <<
"IntegerVectorTest: " << origIntNorm <<
" == " 435 << redistIntNorm <<
" ?";
436 if (origIntNorm != redistIntNorm) {
437 if (me == 0) std::cout <<
" FAIL" << std::endl;
440 else if (me == 0) std::cout <<
" OK" << std::endl;
446 if (me == 0) cout <<
"Matvec original..." << endl;
447 origMatrix->apply(*origVector, *origProd);
450 cout <<
"Norm of Original matvec prod: " << origNorm << endl;
452 if (me == 0) cout <<
"Matvec redistributed..." << endl;
453 redistribMatrix->apply(*redistribVector, *redistribProd);
456 cout <<
"Norm of Redistributed matvec prod: " << redistribNorm << endl;
458 if (redistribNorm > origNorm+
epsilon || redistribNorm < origNorm-
epsilon) {
463 delete redistribVector;
464 delete redistribMatrix;
468 std::cout <<
"Mat-Vec product changed; FAIL" << std::endl;
472 std::cout <<
"PASS" << std::endl;
Provides access for Zoltan2 to Xpetra::CrsMatrix data.
Provides access for Zoltan2 to Xpetra::CrsGraph data.
Zoltan2::XpetraCrsGraphAdapter< SparseGraph > SparseGraphAdapter
common code used by tests
Tpetra::CrsGraph< z2TestLO, z2TestGO > SparseGraph
Tpetra::CrsMatrix< z2TestScalar, z2TestLO, z2TestGO > SparseMatrix
Zoltan2::XpetraMultiVectorAdapter< IntVector > IntVectorAdapter
Defines the XpetraMultiVectorAdapter.
Defines XpetraCrsGraphAdapter class.
Defines the XpetraCrsMatrixAdapter class.
Tpetra::Vector< int, z2TestLO, z2TestGO > IntVector
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
InputTraits< User >::part_t part_t
An adapter for Xpetra::MultiVector.
Tpetra::Vector< z2TestScalar, z2TestLO, z2TestGO > Vector
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
PartitioningProblem sets up partitioning problems for the user.
Zoltan2::XpetraMultiVectorAdapter< Vector > MultiVectorAdapter
Zoltan2::XpetraCrsMatrixAdapter< SparseMatrix > SparseMatrixAdapter
Defines the PartitioningProblem class.
void applyPartitioningSolution(const User &in, User *&out, const PartitioningSolution< Adapter > &solution) const
int main(int narg, char **arg)
void solve(bool updateInputData=true)
Direct the problem to create a solution.
std::string testDataFilePath(".")