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