143 if (pL.get<
int>(
"aggregation: max agg size") == -1)
144 pL.set(
"aggregation: max agg size", INT_MAX);
147 RCP<const FactoryBase> graphFact =
GetFactory(
"Graph");
159 std::string mapOnePtName = pL.get<std::string>(
"OnePt aggregate map name");
160 RCP<Map> OnePtMap = Teuchos::null;
161 if (mapOnePtName.length()) {
162 std::string mapOnePtFactName = pL.get<std::string>(
"OnePt aggregate map factory");
163 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
166 RCP<const FactoryBase> mapOnePtFact =
GetFactory(mapOnePtFactName);
167 OnePtMap = currentLevel.
Get<RCP<Map>>(mapOnePtName, mapOnePtFact.get());
172 std::string mapInterfaceName = pL.get<std::string>(
"Interface aggregate map name");
173 RCP<Map> InterfaceMap = Teuchos::null;
175 RCP<const LWGraph> graph;
176 RCP<const LWGraph_kokkos> graph_kokkos;
177 RCP<Aggregates> aggregates;
178 RCP<const Teuchos::Comm<int>> comm;
181 const std::string aggregationBackend = pL.get<std::string>(
"aggregation: backend");
192 if (
IsType<RCP<LWGraph>>(currentLevel,
"Graph")) {
193 if ((aggregationBackend ==
"default") || (aggregationBackend ==
"non-Kokkos")) {
196 comm = graph->GetComm();
197 numRows = graph->GetNodeNumVertices();
201 graph_kokkos = tmp_graph->copyToDevice();
202 aggregates = rcp(
new Aggregates(*graph_kokkos));
203 comm = graph_kokkos->GetComm();
204 numRows = graph_kokkos->GetNodeNumVertices();
207 }
else if (
IsType<RCP<LWGraph_kokkos>>(currentLevel,
"Graph")) {
208 if ((aggregationBackend ==
"default") || (aggregationBackend ==
"Kokkos")) {
210 aggregates = rcp(
new Aggregates(*graph_kokkos));
211 comm = graph_kokkos->GetComm();
212 numRows = graph_kokkos->GetNodeNumVertices();
216 graph = tmp_graph_kokkos->copyToHost();
218 comm = graph->GetComm();
219 numRows = graph->GetNodeNumVertices();
223 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Graph has bad type.");
227 TEUCHOS_TEST_FOR_EXCEPTION(pL.get<
bool>(
"aggregation: use interface aggregation"), std::invalid_argument,
"Option: 'aggregation: use interface aggregation' is not supported in the Kokkos version of uncoupled aggregation");
229 TEUCHOS_TEST_FOR_EXCEPTION(pL.get<
bool>(
"aggregation: match ML phase1"), std::invalid_argument,
"Option: 'aggregation: match ML phase1' is not supported in the Kokkos version of uncoupled aggregation");
233 aggregates->setObjectLabel(
"UC");
238 AggStatHostType aggStatHost;
242 aggStatHost = AggStatHostType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
243 Kokkos::deep_copy(aggStatHost,
READY);
245 aggStat = AggStatType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
246 Kokkos::deep_copy(aggStat,
READY);
250 if (pL.get<
bool>(
"aggregation: use interface aggregation") ==
true) {
251 Teuchos::Array<LO> nodeOnInterface =
Get<Array<LO>>(currentLevel,
"nodeOnInterface");
252 for (LO i = 0; i < numRows; i++) {
253 if (nodeOnInterface[i])
261 auto dirichletBoundaryMap = graph->GetBoundaryNodeMap();
262 Kokkos::parallel_for(
263 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
264 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph::execution_space>(0, numRows),
266 if (dirichletBoundaryMap(nodeIdx) ==
true) {
271 auto dirichletBoundaryMap = graph_kokkos->GetBoundaryNodeMap();
272 Kokkos::parallel_for(
273 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
274 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
276 if (dirichletBoundaryMap(nodeIdx) ==
true) {
283 if (OnePtMap != Teuchos::null) {
284 LO nDofsPerNode =
Get<LO>(currentLevel,
"DofsPerNode");
287 GO indexBase = graph->GetDomainMap()->getIndexBase();
288 for (LO i = 0; i < numRows; i++) {
290 GO grid = (graph->GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
292 for (LO kr = 0; kr < nDofsPerNode; kr++)
293 if (OnePtMap->isNodeGlobalElement(grid + kr))
294 aggStatHost(i) =
ONEPT;
297 GO indexBase = graph_kokkos->GetDomainMap()->getIndexBase();
298 auto lclDomainMap = graph_kokkos->GetDomainMap()->getLocalMap();
299 auto lclOnePtMap = OnePtMap->getLocalMap();
300 const LocalOrdinal INVALID = Tpetra::Details::OrdinalTraits<LocalOrdinal>::invalid();
301 Kokkos::parallel_for(
302 "MueLu - UncoupledAggregation: tagging OnePt map",
303 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
306 GO grid = (lclDomainMap.getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
308 for (LO kr = 0; kr < nDofsPerNode; kr++)
309 if (lclOnePtMap.getLocalElement(grid + kr) != INVALID)
315 LO numNonAggregatedNodes = numRows;
316 std::string aggAlgo = pL.get<std::string>(
"aggregation: coloring algorithm");
317 if (aggAlgo ==
"mis2 coarsening" || aggAlgo ==
"mis2 aggregation") {
318 TEUCHOS_ASSERT(!runOnHost);
322 using device_t =
typename graph_t::device_type;
323 using exec_space =
typename device_t::execution_space;
324 using rowmap_t =
typename graph_t::row_map_type;
325 using colinds_t =
typename graph_t::entries_type;
326 using lno_t =
typename colinds_t::non_const_value_type;
327 rowmap_t aRowptrs = graph_kokkos->getRowPtrs();
328 colinds_t aColinds = graph_kokkos->getEntries();
330 typename colinds_t::non_const_type labels;
332 if (aggAlgo ==
"mis2 coarsening") {
334 labels = KokkosGraph::graph_mis2_coarsen<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
335 }
else if (aggAlgo ==
"mis2 aggregation") {
337 labels = KokkosGraph::graph_mis2_aggregate<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
339 auto vertex2AggId = aggregates->GetVertex2AggId()->getDeviceLocalView(Xpetra::Access::ReadWrite);
340 auto procWinner = aggregates->GetProcWinner()->getDeviceLocalView(Xpetra::Access::OverwriteAll);
341 int rank = comm->getRank();
342 Kokkos::parallel_for(
343 Kokkos::RangePolicy<exec_space>(0, numRows),
344 KOKKOS_LAMBDA(lno_t i) {
345 procWinner(i, 0) = rank;
346 if (aggStat(i) ==
READY) {
348 vertex2AggId(i, 0) = labels(i);
351 numNonAggregatedNodes = 0;
352 aggregates->SetNumAggregates(numAggs);
355 DoGraphColoring(currentLevel, aggAlgo, pL.get<
bool>(
"aggregation: deterministic"), graph_kokkos, aggregates);
361 GO numGlobalRows = 0;
362 GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
365 for (
size_t a = 0; a <
algos_.size(); a++) {
366 std::string phase =
algos_[a]->description();
371 algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStatHost, numNonAggregatedNodes);
373 algos_[a]->BuildAggregates(pL, *graph_kokkos, *aggregates, aggStat, numNonAggregatedNodes);
374 algos_[a]->SetProcRankVerbose(oldRank);
377 GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
378 GO numLocalAggs = aggregates->GetNumAggregates(), numGlobalAggs = 0;
379 MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
382 double aggPercent = 100 * as<double>(numGlobalAggregated) / as<double>(numGlobalRows);
383 if (aggPercent > 99.99 && aggPercent < 100.00) {
390 GetOStream(
Statistics1) <<
" aggregated : " << (numGlobalAggregated - numGlobalAggregatedPrev) <<
" (phase), " << std::fixed
391 << std::setprecision(2) << numGlobalAggregated <<
"/" << numGlobalRows <<
" [" << aggPercent <<
"%] (total)\n"
392 <<
" remaining : " << numGlobalRows - numGlobalAggregated <<
"\n"
393 <<
" aggregates : " << numGlobalAggs - numGlobalAggsPrev <<
" (phase), " << numGlobalAggs <<
" (total)" << std::endl;
394 numGlobalAggregatedPrev = numGlobalAggregated;
395 numGlobalAggsPrev = numGlobalAggs;
400 TEUCHOS_TEST_FOR_EXCEPTION(numNonAggregatedNodes,
Exceptions::RuntimeError,
"MueLu::UncoupledAggregationFactory::Build: Leftover nodes found! Error!");
402 aggregates->AggregatesCrossProcessors(
false);
403 aggregates->ComputeAggregateSizes(
true );
405 Set(currentLevel,
"Aggregates", aggregates);
411 const std::string& aggAlgo,
412 const bool deterministic,
413 const RCP<const LWGraph_kokkos> graph,
414 RCP<Aggregates> aggregates)
const {
423 using KernelHandle = KokkosKernels::Experimental::
424 KokkosKernelsHandle<
typename graph_t::row_map_type::value_type,
425 typename graph_t::entries_type::value_type,
426 typename graph_t::entries_type::value_type,
427 typename graph_t::device_type::execution_space,
428 typename graph_t::device_type::memory_space,
429 typename graph_t::device_type::memory_space>;
432 kh.create_distance2_graph_coloring_handle();
435 auto coloringHandle = kh.get_distance2_graph_coloring_handle();
437 const LO numRows = graph->GetNodeNumVertices();
448 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
450 }
else if (aggAlgo ==
"serial") {
451 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
453 }
else if (aggAlgo ==
"default") {
454 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_DEFAULT);
456 }
else if (aggAlgo ==
"vertex based") {
457 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB);
459 }
else if (aggAlgo ==
"vertex based bit set") {
460 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT);
462 }
else if (aggAlgo ==
"edge filtering") {
463 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT_EF);
465 }
else if (aggAlgo ==
"net based bit set") {
466 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_NB_BIT);
469 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unrecognized distance 2 coloring algorithm, valid options are: serial, default, matrix squared, vertex based, vertex based bit set, edge filtering")
473 typename graph_t::row_map_type aRowptrs = graph->getRowPtrs();
474 typename graph_t::entries_type aColinds = graph->getEntries();
479 SubFactoryMonitor sfm2(*
this,
"Algo \"Graph Coloring\": KokkosGraph Call", currentLevel);
480 KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
484 aggregates->SetGraphColors(coloringHandle->get_vertex_colors());
485 aggregates->SetGraphNumColors(
static_cast<LO
>(coloringHandle->get_num_colors()));
488 kh.destroy_distance2_graph_coloring_handle();