10 #include "Teuchos_CommandLineProcessor.hpp" 
   11 #include "Tpetra_CrsMatrix.hpp" 
   12 #include "Tpetra_Core.hpp" 
   13 #include "Tpetra_KokkosCompat_DefaultNode.hpp" 
   19 #include "Teuchos_TimeMonitor.hpp"  
   20 #include "Teuchos_StackedTimer.hpp" 
   23 #include <Galeri_MultiVectorTraits.hpp> 
   24 #include <Galeri_XpetraProblemFactory.hpp> 
   25 #include <Galeri_XpetraParameters.hpp> 
   26 #include <MatrixMarket_Tpetra.hpp> 
   42 template <
typename lno_t, 
typename gno_t, 
typename scalar_t, 
typename nod_t>
 
   44     const Teuchos::RCP<
const Teuchos::Comm<int> > &comm,
 
   45     Teuchos::RCP<Tpetra::CrsMatrix<scalar_t, lno_t, gno_t, nod_t>> &M_)
 
   48   if (comm->getRank() == 0){
 
   49     std::cout << 
"Create matrix with " << problemType;
 
   50     std::cout << 
" (a " << xdim;
 
   52       std::cout << 
" x " << ydim << 
" x " << zdim << 
" ";
 
   54       std::cout << 
" x"  << ydim << 
" x 1 ";
 
   56       std::cout << 
"x 1 x 1 ";
 
   57     std::cout << 
" mesh)" << std::endl;
 
   60   Teuchos::CommandLineProcessor tclp;
 
   61   Galeri::Xpetra::Parameters<gno_t> params(tclp, xdim, ydim, zdim, problemType);
 
   63   Teuchos::RCP<const Tpetra::Map<lno_t, gno_t> > map =
 
   64     Teuchos::rcp(
new Tpetra::Map<lno_t, gno_t>(params.GetNumGlobalElements(), 0, comm));
 
   68     Teuchos::RCP<Galeri::Xpetra::Problem<Tpetra::Map<lno_t, gno_t>,
 
   69       Tpetra::CrsMatrix<scalar_t, lno_t, gno_t, nod_t>,
 
   70       Tpetra::MultiVector<scalar_t, lno_t, gno_t> > > Pr=
 
   71         Galeri::Xpetra::BuildProblem<scalar_t, 
lno_t, 
gno_t,
 
   72       Tpetra::Map<lno_t, gno_t>,
 
   73       Tpetra::CrsMatrix<scalar_t, lno_t, gno_t, nod_t>,
 
   74       Tpetra::MultiVector<scalar_t, lno_t, gno_t, nod_t> >
 
   75         (params.GetMatrixType(), map, params.GetParameterList());
 
   77     M_ = Pr->BuildMatrix();
 
   79   catch (std::exception &e) {    
 
   80     if(comm->getRank() == 0) std::cout << 
"Error returned from Galeri " << e.what() << std::endl;
 
   89 template <
typename adapter_type>
 
   95   typedef typename graph_type::global_ordinal_type GO;
 
   96   typedef typename graph_type::local_ordinal_type LO;
 
   97   typedef typename graph_type::node_type NO;
 
  100   using ordinal_view_t = Kokkos::View<GO*, typename NO::device_type>;
 
  101   using part_view_t = Kokkos::View<PT*, typename NO::device_type>;
 
  103   auto graph = adapter->getUserGraph();
 
  104   auto rowMap = graph->getRowMap();
 
  105   auto colMap = graph->getColMap();
 
  107   size_t numLclRows = rowMap->getLocalNumElements();
 
  108   size_t numGblRows = rowMap->getGlobalNumElements();
 
  109   size_t numLclCols = colMap->getLocalNumElements();
 
  111   ordinal_view_t colLocalToGlobal(Kokkos::view_alloc(
"colLocalToGlobal", Kokkos::WithoutInitializing), numLclCols);
 
  112   auto colMapHost = Kokkos::create_mirror_view (Kokkos::HostSpace (), colLocalToGlobal);
 
  113   for(
size_t i = 0; i < numLclCols; ++i)
 
  114     colMapHost[i] = colMap->getGlobalElement(i);
 
  115   Kokkos::deep_copy (colLocalToGlobal, colMapHost);
 
  117   ordinal_view_t rowLocalToGlobal(Kokkos::view_alloc(
"rowLocalToGlobal", Kokkos::WithoutInitializing), numLclRows);
 
  118   auto rowMapHost = Kokkos::create_mirror_view (Kokkos::HostSpace (), rowLocalToGlobal);
 
  119   for(
size_t i = 0; i < numLclRows; ++i)
 
  120     rowMapHost[i] = rowMap->getGlobalElement(i);
 
  121   Kokkos::deep_copy (rowLocalToGlobal, rowMapHost);
 
  123   part_view_t localParts(
"localParts", numGblRows);
 
  124   part_view_t globalParts(
"globalParts", numGblRows);
 
  125   auto localPartsHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), localParts);
 
  128   for(
size_t i = 0; i < numLclRows; i++){
 
  129     GO gi = rowMap->getGlobalElement(i);
 
  130     localPartsHost(gi) = parts[i];
 
  132   Kokkos::deep_copy(localParts, localPartsHost);
 
  134   auto comm = graph->getComm();
 
  135   Teuchos::reduceAll<int, PT> (*comm, Teuchos::REDUCE_SUM, numGblRows, localParts.data(), globalParts.data());
 
  137   auto rowPtr = graph->getLocalGraphHost().row_map;
 
  138   auto colInd = graph->getLocalGraphHost().entries;
 
  140   size_t localtotalcut = 0, totalcut = 0;
 
  142   using execution_space = 
typename NO::device_type::execution_space;
 
  143   using range_policy = Kokkos::RangePolicy<execution_space, Kokkos::IndexType<LO>>;
 
  144   Kokkos::parallel_reduce(
"Compute cut", range_policy(0, numLclRows),
 
  145       KOKKOS_LAMBDA(
const LO i, 
size_t &cut){
 
  147       const GO gRid = rowLocalToGlobal(i);
 
  148       const PT gi = globalParts(gRid);
 
  150       const size_t start = rowPtr(i);
 
  151       const size_t end = rowPtr(i+1);
 
  152       for(
size_t j = start; j < end; ++j) {
 
  154       const GO gCid = colLocalToGlobal(colInd(j)); 
 
  155       PT gj = globalParts(gCid);
 
  161   Teuchos::reduceAll (*comm, Teuchos::REDUCE_SUM, 1, &localtotalcut, &totalcut);
 
  164   auto rowPtr_h = Kokkos::create_mirror_view(rowPtr);
 
  165   Kokkos::deep_copy(rowPtr_h, rowPtr);
 
  168   size_t *partw = 
new size_t[nparts];
 
  169   size_t *partc = 
new size_t[nparts];
 
  171   size_t *gpartw = 
new size_t[nparts];
 
  172   size_t *gpartc = 
new size_t[nparts];
 
  174   for(
int i = 0; i < nparts; i++){
 
  175     partw[i] = 0; partc[i] = 0;
 
  176     gpartw[i] = 0; gpartc[i] = 0;
 
  179   for(
size_t i = 0; i < numLclRows; i++){
 
  180     partw[parts[i]] += rowPtr_h(i+1) - rowPtr_h(i) - 1;
 
  184   Teuchos::reduceAll (*comm, Teuchos::REDUCE_SUM, nparts, partw, gpartw); 
 
  185   Teuchos::reduceAll (*comm, Teuchos::REDUCE_SUM, nparts, partc, gpartc); 
 
  187   size_t maxc = 0, totc = 0;
 
  188   size_t maxw = 0, totw = 0;
 
  190   for(
int i = 0; i < nparts; i++){
 
  199   double imbw = (double)maxw/((
double)totw/nparts);
 
  200   double imbc = (double)maxc/((
double)totc/nparts);
 
  202   if(comm->getRank() == 0) {
 
  204     std::cout << 
"\n\n************************************************" << std::endl;
 
  205     std::cout << 
"                              EDGECUT: " << totalcut <<  std::endl;
 
  206     std::cout << 
"                       MAX/AVG WEIGHT: " << imbw <<  std::endl;
 
  207     std::cout << 
"                        MAX/AVG COUNT: " << imbc <<  std::endl;
 
  208     std::cout << 
"************************************************\n\n" << std::endl;
 
  214 int main(
int narg, 
char *arg[]) 
 
  217   Tpetra::ScopeGuard tpetraScope (&narg, &arg);
 
  220     const Teuchos::RCP<const Teuchos::Comm<int>> pComm= Tpetra::getDefaultComm();
 
  222     int me = pComm->getRank();
 
  226     int max_iters = 1000;
 
  231     std::string matrix_file = 
"";
 
  232     std::string eigensolve = 
"LOBPCG"; 
 
  233     bool parmetis = 
false;
 
  238     std::string ptype = 
"";
 
  239     std::string prec = 
"jacobi";
 
  240     std::string init = 
"random";
 
  245       for (
int i = 0; i < narg; i++)
 
  246         std::cout << arg[i] << 
" ";
 
  247       std::cout << std::endl;
 
  250     Teuchos::CommandLineProcessor cmdp(
false,
true);
 
  251     cmdp.setOption(
"matrix_file",&matrix_file,
 
  252         "Path and filename of the matrix to be read.");
 
  253     cmdp.setOption(
"nparts",&nparts,
 
  254         "Number of global parts desired in the resulting partition.");
 
  255     cmdp.setOption(
"rand_seed",&rand_seed,
 
  256         "Seed for the random multivector.");
 
  257     cmdp.setOption(
"max_iters",&max_iters,
 
  258         "Maximum iters for the eigensolver.");
 
  259     cmdp.setOption(
"block_size",&block_size,
 
  261     cmdp.setOption(
"verbosity", &verbosity,
 
  263     cmdp.setOption(
"parmetis", 
"sphynx", &parmetis,
 
  264         "Whether to use parmetis.");
 
  265     cmdp.setOption(
"pulp", 
"sphynx", &pulp,
 
  266         "Whether to use pulp.");
 
  267     cmdp.setOption(
"prec", &prec,
 
  268         "Prec type to use.");
 
  269     cmdp.setOption(
"eigensolve", &eigensolve,
 
  270         "Eigensolver to use: LOBPCG, BlockDavidson, GeneralizedDavidson, BlockKrylovSchur or randomized.");
 
  271     cmdp.setOption(
"prob", &ptype,
 
  272         "Problem type to use. Options are combinatorial, normalized or generalized.");
 
  273     cmdp.setOption(
"tol", &tol,
 
  274         "Tolerance to use.");
 
  275     cmdp.setOption(
"init",  &init,
 
  276         "Sphynx Initial guess. Options: random or constants. Default: random if randomized solver is used.");
 
  277     cmdp.setOption(
"resFreq",  &resFreq,
 
  278         "(For randomized) Specify how often to check the residuals. Orthogonalization of the basis is also done.");
 
  279     cmdp.setOption(
"orthoFreq",  &orthoFreq,
 
  280         "(For randomized) Specify how often to orthogonalize the basis.");
 
  282     if (cmdp.parse(narg,arg)!=Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) 
return -1;
 
  286       std::cout << std::endl << 
"--------------------------------------------------" << matrix_file << std::endl;
 
  287       std::cout << 
"| Sphynx Parameters                              |" << matrix_file << std::endl;
 
  288       std::cout << 
"--------------------------------------------------" << matrix_file << std::endl;
 
  289       std::cout << 
"  matrix file = " << matrix_file << std::endl;
 
  290       std::cout << 
"  nparts      = " << nparts << std::endl;
 
  291       std::cout << 
"  verbosity   = " << verbosity << std::endl;
 
  292       std::cout << 
"  parmetis    = " << parmetis << std::endl;
 
  293       std::cout << 
"  pulp        = " << pulp << std::endl;
 
  294       std::cout << 
"  prec        = " << prec << std::endl;
 
  295       std::cout << 
"  eigensolver = " << eigensolve << std::endl;
 
  296       std::cout << 
"  prob        = " << ptype << std::endl;
 
  297       std::cout << 
"  tol         = " << tol << std::endl;
 
  298       std::cout << 
"  init        = " << init << std::endl;
 
  299       std::cout << 
"  resFreq     = " << resFreq << std::endl;
 
  300       std::cout << 
"  orthoFreq   = " << orthoFreq << std::endl;
 
  301       std::cout << 
"--------------------------------------------------" << matrix_file << std::endl << std::endl;
 
  304     using scalar_type = Tpetra::Details::DefaultTypes::scalar_type;
 
  305     using local_ordinal_type = Tpetra::Details::DefaultTypes::local_ordinal_type;
 
  306     using global_ordinal_type = Tpetra::Details::DefaultTypes::global_ordinal_type;
 
  307     using node_type = Tpetra::Details::DefaultTypes::node_type;
 
  309     using crs_matrix_type = Tpetra::CrsMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type>;  
 
  314     Teuchos::RCP<adapter_type> adapter;
 
  315     Teuchos::RCP<crs_matrix_type> tmatrix;
 
  318     std::srand(rand_seed);
 
  321     std::string mtx = 
".mtx", mm = 
".mm", lc = 
".largestComp", lc2 = 
".bin";
 
  322     if(std::equal(lc.rbegin(), lc.rend(), matrix_file.rbegin()) || std::equal(lc2.rbegin(), lc2.rend(), matrix_file.rbegin())) {
 
  323       tmatrix  = readMatrixFromBinaryFile<crs_matrix_type>(matrix_file, pComm, 
true, verbosity>0);
 
  324       if(me == 0 && verbosity > 1) std::cout << 
"Used Seher's reader for Largest Comp." << std::endl;
 
  326     else if(std::equal(mtx.rbegin(), mtx.rend(), matrix_file.rbegin()) || std::equal(mm.rbegin(), mm.rend(), matrix_file.rbegin())) {
 
  327       typedef Tpetra::MatrixMarket::Reader<crs_matrix_type> reader_type;
 
  329       tmatrix = r.readSparseFile(matrix_file, pComm);
 
  330       if(me == 0 && verbosity > 1) std::cout << 
"Used standard Matrix Market reader." << std::endl;
 
  337       if(matrix_file != 
"")
 
  339         std::string::const_iterator it = matrix_file.begin();
 
  340         while(it != matrix_file.end() && std::isdigit(*it)) ++it;
 
  341         if(it == matrix_file.end())
 
  343           meshdim = std::stoi(matrix_file);
 
  346           if(me == 0) std::cout << 
"Invalid matrix file entered. Reverting to default matrix." << std::endl;
 
  349       int ierr = buildCrsMatrix<local_ordinal_type, global_ordinal_type, scalar_type>
 
  350         (meshdim, meshdim, meshdim, 
"Brick3D", pComm, tmatrix);
 
  351       if (ierr != 0) std::cout << 
"Error! Brick3D failed to build!" << std::endl;
 
  354     if(me == 0 && verbosity > 0) std::cout << 
"Done with reading/creating the matrix." << std::endl;
 
  356     Teuchos::RCP<const Tpetra::Map<> > map = tmatrix->getMap();
 
  358     adapter = Teuchos::rcp(
new adapter_type(tmatrix->getCrsGraph(), 1));
 
  359     adapter->setVertexWeightIsDegree(0);
 
  362     Teuchos::RCP<Teuchos::ParameterList> params = Teuchos::rcp(
new Teuchos::ParameterList());
 
  363     Teuchos::RCP<Teuchos::ParameterList> sphynxParams(
new Teuchos::ParameterList);
 
  364     params->set(
"num_global_parts", nparts);
 
  366     Teuchos::RCP<Teuchos::StackedTimer> stacked_timer;  
 
  367     stacked_timer = Teuchos::rcp(
new Teuchos::StackedTimer(
"SphynxDriver"));
 
  368     Teuchos::TimeMonitor::setStackedTimer(stacked_timer);
 
  369     if(parmetis || pulp) {
 
  371       params->set(
"partitioning_approach", 
"partition");
 
  372       params->set(
"imbalance_tolerance", 1.01);
 
  374         params->set(
"algorithm", 
"parmetis");
 
  375         params->set(
"imbalance_tolerance", 1.01);
 
  378         params->set(
"algorithm", 
"pulp");
 
  379         params->set(
"pulp_vert_imbalance", 1.01);
 
  383       Teuchos::RCP<problem_type> problem;
 
  386         Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Partitioning::All"));
 
  388           Teuchos::TimeMonitor t2(*Teuchos::TimeMonitor::getNewTimer(
"Partitioning::Problem"));
 
  389           problem = Teuchos::rcp(
new problem_type(adapter.getRawPtr(), params.getRawPtr(), Tpetra::getDefaultComm()));
 
  392           Teuchos::TimeMonitor t3(*Teuchos::TimeMonitor::getNewTimer(
"Partitioning::Solve"));
 
  398       solution_type solution = problem->getSolution();
 
  399       compute_edgecut<adapter_type>(adapter, solution);
 
  403       sphynxParams->set(
"sphynx_verbosity", verbosity);
 
  404       sphynxParams->set(
"sphynx_max_iterations", max_iters);
 
  405       sphynxParams->set(
"sphynx_ortho_freq", orthoFreq);
 
  406       sphynxParams->set(
"sphynx_res_freq", resFreq);
 
  407       sphynxParams->set(
"sphynx_skip_preprocessing", 
true);
 
  408       sphynxParams->set(
"sphynx_eigensolver", eigensolve);
 
  409       if (block_size > 0) sphynxParams->set(
"sphynx_block_size", block_size);
 
  410       if (ptype != 
"") sphynxParams->set(
"sphynx_problem_type", ptype);
 
  411       if (init != 
"") sphynxParams->set(
"sphynx_initial_guess", init);
 
  412       if (prec != 
"") sphynxParams->set(
"sphynx_preconditioner_type", prec);
 
  413       if (tol != -1) sphynxParams->set(
"sphynx_tolerance", tol);
 
  416       Teuchos::RCP<problem_type> problem;
 
  419         Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Partitioning::All"));
 
  421           Teuchos::TimeMonitor t2(*Teuchos::TimeMonitor::getNewTimer(
"Partitioning::Problem"));
 
  422           problem = Teuchos::rcp(
new problem_type(adapter.get(), params.get(), sphynxParams, Tpetra::getDefaultComm()));
 
  425           if(me == 0) std::cout << eigensolve << 
" will be used to solve the partitioning problem." << std::endl;
 
  430       solution_type solution = problem->getSolution();
 
  431       compute_edgecut<adapter_type>(adapter, solution);
 
  433     stacked_timer->stopBaseTimer();       
 
  435     Teuchos::RCP<Teuchos::FancyOStream> fancy2 = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
 
  436     Teuchos::FancyOStream& out2 = *fancy2;
 
  437     Teuchos::StackedTimer::OutputOptions options;
 
  438     options.output_fraction = options.output_histogram = options.output_minmax = 
true;
 
  439     stacked_timer->report(out2, pComm, options);
 
  441     Teuchos::TimeMonitor::summarize();
 
void compute_edgecut(Teuchos::RCP< adapter_type > &adapter, Zoltan2::PartitioningSolution< adapter_type > &solution)
 
map_t::global_ordinal_type gno_t
 
Provides access for Zoltan2 to Xpetra::CrsGraph data. 
 
int main(int narg, char **arg)
 
int buildCrsMatrix(int xdim, int ydim, int zdim, std::string problemType, const Teuchos::RCP< const Teuchos::Comm< int > > &comm, Teuchos::RCP< Tpetra::CrsMatrix< scalar_t, lno_t, gno_t, nod_t >> &M_)
 
Defines XpetraCrsGraphAdapter class. 
 
SparseMatrixAdapter_t::part_t part_t
 
A PartitioningSolution is a solution to a partitioning problem. 
 
const part_t * getPartListView() const 
Returns the part list corresponding to the global ID list. 
 
map_t::local_ordinal_type lno_t
 
PartitioningProblem sets up partitioning problems for the user. 
 
Defines the PartitioningProblem class. 
 
size_t getTargetGlobalNumberOfParts() const 
Returns the global number of parts desired in the solution. 
 
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t