int main(int narg, char** arg) { std::string inputFile = ""; // Matrix Market file to read std::string outputFile = ""; // Matrix Market file to write bool verbose = false; // Verbosity of output int testReturn = 0; ////// Establish session. Teuchos::GlobalMPISession mpiSession(&narg, &arg, NULL); RCP<const Teuchos::Comm<int> > comm = Tpetra::DefaultPlatform::getDefaultPlatform().getComm(); int me = comm->getRank(); // Read run-time options. Teuchos::CommandLineProcessor cmdp (false, false); cmdp.setOption("inputFile", &inputFile, "Name of a Matrix Market file in the data directory; " "if not specified, a matrix will be generated by MueLu."); cmdp.setOption("outputFile", &outputFile, "Name of the Matrix Market sparse matrix file to write, " "echoing the input/generated matrix."); cmdp.setOption("verbose", "quiet", &verbose, "Print messages and results."); ////////////////////////////////// // Even with cmdp option "true", I get errors for having these // arguments on the command line. (On redsky build) // KDDKDD Should just be warnings, right? Code should still work with these // KDDKDD params in the create-a-matrix file. Better to have them where // KDDKDD they are used. int xdim=10; int ydim=10; int zdim=10; std::string matrixType("Laplace3D"); cmdp.setOption("x", &xdim, "number of gridpoints in X dimension for " "mesh used to generate matrix."); cmdp.setOption("y", &ydim, "number of gridpoints in Y dimension for " "mesh used to generate matrix."); cmdp.setOption("z", &zdim, "number of gridpoints in Z dimension for " "mesh used to generate matrix."); cmdp.setOption("matrix", &matrixType, "Matrix type: Laplace1D, Laplace2D, or Laplace3D"); ////////////////////////////////// cmdp.parse(narg, arg); RCP<UserInputForTests> uinput; if (inputFile != "") // Input file specified; read a matrix uinput = rcp(new UserInputForTests(testDataFilePath, inputFile, comm, true)); else // Let MueLu generate a matrix uinput = rcp(new UserInputForTests(xdim, ydim, zdim, matrixType, comm, true, true)); RCP<SparseMatrix> origMatrix = uinput->getUITpetraCrsMatrix(); if (outputFile != "") { // Just a sanity check. Tpetra::MatrixMarket::Writer<SparseMatrix>::writeSparseFile(outputFile, origMatrix, verbose); } if (me == 0) cout << "NumRows = " << origMatrix->getGlobalNumRows() << endl << "NumNonzeros = " << origMatrix->getGlobalNumEntries() << endl << "NumProcs = " << comm->getSize() << endl; ////// Create a vector to use with the matrix. RCP<Vector> origVector, origProd; origProd = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>( origMatrix->getRangeMap()); origVector = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>( origMatrix->getDomainMap()); origVector->randomize(); ////// Specify problem parameters Teuchos::ParameterList params; ////// Basic metric checking of the ordering solution size_t checkLength; z2TestLO *checkPerm; ////// Create an input adapter for the Tpetra matrix. SparseMatrixAdapter adapter(origMatrix); params.set("order_method", "minimum_degree"); params.set("order_package", "amd"); ////// Create and solve ordering problem try { Zoltan2::OrderingProblem<SparseMatrixAdapter> problem(&adapter, ¶ms); problem.solve(); Zoltan2::OrderingSolution<z2TestLO, z2TestGO> *soln = problem.getSolution(); // Check that the solution is really a permutation checkLength = soln->getPermutationSize(); checkPerm = soln->getPermutation(); for (size_t ii = 0; ii < checkLength; ii++) cout << checkPerm[ii] << " "; cout << endl; // Verify that checkPerm is a permutation testReturn = validatePerm(checkLength, checkPerm); } catch (std::exception &e){ #ifdef HAVE_ZOLTAN2_AMD // AMD is defined and still got an exception. if (comm->getSize() != 1) { std::cout << "AMD is enabled. We do not support distributed matrices." << "AMD Algorithm threw an exception." << std::endl; std::cout << "PASS" << std::endl; } else { std::cout << "Exception from AMD Algorithm" << std::endl; std::cout << "FAIL" << std::endl; } return 0; #else std::cout << "AMD is not enabled. AMD Algorithm threw an exception." << std::endl; std::cout << "PASS" << std::endl; return 0; #endif } if (me == 0) { if (testReturn) std::cout << "Solution is not a permutation; FAIL" << std::endl; else std::cout << "PASS" << std::endl; } return 0; }
int main(int narg, char** arg) { std::string inputFile = ""; // Matrix Market file to read std::string outputFile = ""; // Output file to write bool verbose = false; // Verbosity of output int testReturn = 0; ////// Establish session. Teuchos::GlobalMPISession mpiSession(&narg, &arg, NULL); RCP<const Teuchos::Comm<int> > comm = Tpetra::DefaultPlatform::getDefaultPlatform().getComm(); int me = comm->getRank(); // Read run-time options. Teuchos::CommandLineProcessor cmdp (false, false); cmdp.setOption("inputFile", &inputFile, "Name of a Matrix Market file in the data directory; " "if not specified, a matrix will be generated by Galeri."); cmdp.setOption("outputFile", &outputFile, "Name of file to write the permutation"); cmdp.setOption("verbose", "quiet", &verbose, "Print messages and results."); cout << "Starting everything" << endl; ////////////////////////////////// // Even with cmdp option "true", I get errors for having these // arguments on the command line. (On redsky build) // KDDKDD Should just be warnings, right? Code should still work with these // KDDKDD params in the create-a-matrix file. Better to have them where // KDDKDD they are used. int xdim=10; int ydim=10; int zdim=10; std::string matrixType("Laplace3D"); cmdp.setOption("x", &xdim, "number of gridpoints in X dimension for " "mesh used to generate matrix."); cmdp.setOption("y", &ydim, "number of gridpoints in Y dimension for " "mesh used to generate matrix."); cmdp.setOption("z", &zdim, "number of gridpoints in Z dimension for " "mesh used to generate matrix."); cmdp.setOption("matrix", &matrixType, "Matrix type: Laplace1D, Laplace2D, or Laplace3D"); ////////////////////////////////// // Ordering options to test. ////////////////////////////////// std::string orderMethod("scotch"); // NYI cmdp.setOption("order_method", &orderMethod, "order_method: natural, random, rcm, scotch"); ////////////////////////////////// cmdp.parse(narg, arg); RCP<UserInputForTests> uinput; if (inputFile != ""){ // Input file specified; read a matrix uinput = rcp(new UserInputForTests(testDataFilePath, inputFile, comm, true)); } else // Let Galeri generate a matrix uinput = rcp(new UserInputForTests(xdim, ydim, zdim, matrixType, comm, true, true)); RCP<SparseMatrix> origMatrix = uinput->getUITpetraCrsMatrix(); if (me == 0) cout << "NumRows = " << origMatrix->getGlobalNumRows() << endl << "NumNonzeros = " << origMatrix->getGlobalNumEntries() << endl << "NumProcs = " << comm->getSize() << endl; ////// Create a vector to use with the matrix. RCP<Vector> origVector, origProd; origProd = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>( origMatrix->getRangeMap()); origVector = Tpetra::createVector<z2TestScalar,z2TestLO,z2TestGO>( origMatrix->getDomainMap()); origVector->randomize(); ////// Specify problem parameters Teuchos::ParameterList params; params.set("order_method", orderMethod); ////// Create an input adapter for the Tpetra matrix. SparseMatrixAdapter adapter(origMatrix); ////// Create and solve ordering problem try { Zoltan2::OrderingProblem<SparseMatrixAdapter> problem(&adapter, ¶ms); cout << "Going to solve" << endl; problem.solve(); ////// Basic metric checking of the ordering solution size_t checkLength; z2TestLO *checkPerm; Zoltan2::OrderingSolution<z2TestLO, z2TestGO> *soln = problem.getSolution(); cout << "Going to get results" << endl; // Permutation checkLength = soln->getPermutationSize(); checkPerm = soln->getPermutation(); checkInvPerm = soln->getInversePermutation(); // MNYI // Separators. // The following methods needs to be supported: // haveSeparators: true if Scotch Nested Dissection was called. // getCBlkPtr: *CBlkPtr from Scotch_graphOrder // getRangTab: RangTab from Scotch_graphOrder // getTreeTab: TreeTab from Scotch_graphOrder if (soln->haveSeparators()){ // NYI z2TestLO NumBlocks = soln->getCBlkPtr(); // NYI z2TestLO * RangTab = soln->getRangTab(); // NYI z2TestLO * TreeTab = soln->getTreeTab(); // NYI // TODO Use accessor names that make more sense to users // getNumSeparatorBlocks() // getVertexSeparator(NumBlocks, RangeTab, TreeTab) // // RangTab is size NumBlocks+1; offsets into inverse permutation array giving vertices // belonging to a block // TreeTab is size NumBlocks; gives parent blocks of a block } else { // TODO FAIL with error } if (outputFile != "") { ofstream permFile; // Write permutation (0-based) to file // each process writes local perm to a separate file //std::string fname = outputFile + "." + me; std::stringstream fname; fname << outputFile << "." << comm->getSize() << "." << me; permFile.open(fname.str().c_str()); for (size_t i=0; i<checkLength; i++){ permFile << " " << checkPerm[i] << endl; } permFile.close(); } cout << "Going to validate the soln" << endl; // Verify that checkPerm is a permutation testReturn = validatePerm(checkLength, checkPerm); // TODO How do we validate the separator? // E.g., RangeTab monitonically increasing, RT[0] = 0; RT[NumBlocks+1]=nVtx; // TreeTab root has -1, other values < NumBlocks // NumBlocks appropriate for nLevels // TODO How do we validate the inverse permutation? // InversePerm[Perm[i]] == i? cout << "Going to compute the bandwidth" << endl; // Compute original bandwidth cout << "Original Bandwidth: " << computeBandwidth(origMatrix, 0) << endl; // Compute permuted bandwidth cout << "Permuted Bandwidth: " << computeBandwidth(origMatrix, checkPerm) << endl; } catch (std::exception &e){ if (comm->getSize() != 1) { std::cout << "Ordering does not support distributed matrices." << std::endl; std::cout << "PASS" << std::endl; } else { std::cout << "Exception caught in ordering" << std::endl; std::cout << e.what() << std::endl; std::cout << "FAIL" << std::endl; } return 0; } if (me == 0) { if (testReturn) std::cout << "Solution is not a permutation; FAIL" << std::endl; else std::cout << "PASS" << std::endl; } }