MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_UncoupledAggregationFactory_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
11#define MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
12
13#include <climits>
14
15#include <Xpetra_Map.hpp>
16#include <Xpetra_Vector.hpp>
17#include <Xpetra_MultiVectorFactory.hpp>
18#include <Xpetra_VectorFactory.hpp>
19
21
22#include "MueLu_InterfaceAggregationAlgorithm.hpp"
23#include "MueLu_OnePtAggregationAlgorithm.hpp"
24#include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
25
26#include "MueLu_AggregationPhase1Algorithm.hpp"
27#include "MueLu_AggregationPhase2aAlgorithm.hpp"
28#include "MueLu_AggregationPhase2bAlgorithm.hpp"
29#include "MueLu_AggregationPhase3Algorithm.hpp"
30
31#include "MueLu_Level.hpp"
32#include "MueLu_LWGraph.hpp"
33#include "MueLu_Aggregates.hpp"
34#include "MueLu_MasterList.hpp"
35#include "MueLu_Monitor.hpp"
36
37#include "KokkosGraph_Distance2ColorHandle.hpp"
38#include "KokkosGraph_Distance2Color.hpp"
39#include "KokkosGraph_MIS2.hpp"
40
41namespace MueLu {
42
43template <class LocalOrdinal, class GlobalOrdinal, class Node>
46
47template <class LocalOrdinal, class GlobalOrdinal, class Node>
49
50template <class LocalOrdinal, class GlobalOrdinal, class Node>
52 RCP<ParameterList> validParamList = rcp(new ParameterList());
53
54 // Aggregation parameters (used in aggregation algorithms)
55 // TODO introduce local member function for each aggregation algorithm such that each aggregation algorithm can define its own parameters
56
57#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
58 SET_VALID_ENTRY("aggregation: max agg size");
59 SET_VALID_ENTRY("aggregation: min agg size");
60 SET_VALID_ENTRY("aggregation: max selected neighbors");
61 SET_VALID_ENTRY("aggregation: ordering");
62 validParamList->getEntry("aggregation: ordering").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("natural", "graph", "random"))));
63 SET_VALID_ENTRY("aggregation: deterministic");
64 SET_VALID_ENTRY("aggregation: coloring algorithm");
65 SET_VALID_ENTRY("aggregation: enable phase 1");
66 SET_VALID_ENTRY("aggregation: enable phase 2a");
67 SET_VALID_ENTRY("aggregation: enable phase 2b");
68 SET_VALID_ENTRY("aggregation: enable phase 3");
69 SET_VALID_ENTRY("aggregation: match ML phase1");
70 SET_VALID_ENTRY("aggregation: match ML phase2a");
71 SET_VALID_ENTRY("aggregation: match ML phase2b");
72 SET_VALID_ENTRY("aggregation: phase2a agg factor");
73 SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
74 SET_VALID_ENTRY("aggregation: allow user-specified singletons");
75 SET_VALID_ENTRY("aggregation: use interface aggregation");
76 SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
77 SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
78 SET_VALID_ENTRY("aggregation: phase 1 algorithm");
79 SET_VALID_ENTRY("aggregation: backend");
80 validParamList->getEntry("aggregation: backend").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("default", "host", "kokkos"))));
81#undef SET_VALID_ENTRY
82
83 // general variables needed in AggregationFactory
84 validParamList->set<RCP<const FactoryBase>>("Graph", null, "Generating factory of the graph");
85 validParamList->set<RCP<const FactoryBase>>("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
86
87 // special variables necessary for OnePtAggregationAlgorithm
88 validParamList->set<std::string>("OnePt aggregate map name", "", "Name of input map for single node aggregates. (default='')");
89 validParamList->set<std::string>("OnePt aggregate map factory", "", "Generating factory of (DOF) map for single node aggregates.");
90 // validParamList->set< RCP<const FactoryBase> >("OnePt aggregate map factory", NoFactory::getRCP(), "Generating factory of (DOF) map for single node aggregates.");
91
92 // InterfaceAggregation parameters
93 // validParamList->set< bool > ("aggregation: use interface aggregation", "false", "Flag to trigger aggregation along an interface using specified aggregate seeds.");
94 validParamList->set<std::string>("Interface aggregate map name", "", "Name of input map for interface aggregates. (default='')");
95 validParamList->set<std::string>("Interface aggregate map factory", "", "Generating factory of (DOF) map for interface aggregates.");
96 validParamList->set<RCP<const FactoryBase>>("nodeOnInterface", Teuchos::null, "Array specifying whether or not a node is on the interface (1 or 0).");
97
98 return validParamList;
99}
100
101template <class LocalOrdinal, class GlobalOrdinal, class Node>
103 Input(currentLevel, "Graph");
104 Input(currentLevel, "DofsPerNode");
105
106 const ParameterList& pL = GetParameterList();
107
108 // request special data necessary for OnePtAggregationAlgorithm
109 std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
110 if (mapOnePtName.length() > 0) {
111 std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
112 if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
113 currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
114 } else {
115 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
116 currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
117 }
118 }
119
120 // request special data necessary for InterfaceAggregation
121 if (pL.get<bool>("aggregation: use interface aggregation") == true) {
122 if (currentLevel.GetLevelID() == 0) {
123 if (currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
124 currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
125 } else {
126 TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
128 "nodeOnInterface was not provided by the user on level0!");
129 }
130 } else {
131 Input(currentLevel, "nodeOnInterface");
132 }
133 }
134}
135
136template <class LocalOrdinal, class GlobalOrdinal, class Node>
138 FactoryMonitor m(*this, "Build", currentLevel);
139
140 ParameterList pL = GetParameterList();
141 bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
142
143 if (pL.get<int>("aggregation: max agg size") == -1)
144 pL.set("aggregation: max agg size", INT_MAX);
145
146 // define aggregation algorithms
147 RCP<const FactoryBase> graphFact = GetFactory("Graph");
148
149 // TODO Can we keep different aggregation algorithms over more Build calls?
150 algos_.clear();
151 algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
152 if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm(graphFact)));
153 if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm(graphFact)));
154 if (pL.get<bool>("aggregation: enable phase 1") == true) algos_.push_back(rcp(new AggregationPhase1Algorithm(graphFact)));
155 if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm(graphFact)));
156 if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm(graphFact)));
157 if (pL.get<bool>("aggregation: enable phase 3") == true) algos_.push_back(rcp(new AggregationPhase3Algorithm(graphFact)));
158
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") {
164 OnePtMap = currentLevel.Get<RCP<Map>>(mapOnePtName, NoFactory::get());
165 } else {
166 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
167 OnePtMap = currentLevel.Get<RCP<Map>>(mapOnePtName, mapOnePtFact.get());
168 }
169 }
170
171 // Set map for interface aggregates
172 std::string mapInterfaceName = pL.get<std::string>("Interface aggregate map name");
173 RCP<Map> InterfaceMap = Teuchos::null;
174
175 RCP<const LWGraph> graph;
176 RCP<const LWGraph_kokkos> graph_kokkos;
177 RCP<Aggregates> aggregates;
178 RCP<const Teuchos::Comm<int>> comm;
179 LO numRows;
180
181 const std::string aggregationBackend = pL.get<std::string>("aggregation: backend");
182
183 // "Graph" can have type "LWGraph" or "LWGraph_kokkos".
184 // The aggregation phases can call either "BuildAggregatesNonKokkos" or "BuildAggregates".
185
186 // "aggregation: backend" can take values "default", "non-Kokkos" or "Kokkos".
187 // "default": run depending on the type of "Graph"
188 // "non-Kokkos": run the non-Kokkos aggregation, moving "Graph" to host if necessary
189 // "Kokkos": run the Kokkos aggregation, potentially move "Graph", moving "Graph" to device if necessary
190
191 bool runOnHost;
192 if (IsType<RCP<LWGraph>>(currentLevel, "Graph")) {
193 if ((aggregationBackend == "default") || (aggregationBackend == "non-Kokkos")) {
194 graph = Get<RCP<LWGraph>>(currentLevel, "Graph");
195 aggregates = rcp(new Aggregates(*graph));
196 comm = graph->GetComm();
197 numRows = graph->GetNodeNumVertices();
198 runOnHost = true;
199 } else {
200 RCP<LWGraph> tmp_graph = Get<RCP<LWGraph>>(currentLevel, "Graph");
201 graph_kokkos = tmp_graph->copyToDevice();
202 aggregates = rcp(new Aggregates(*graph_kokkos));
203 comm = graph_kokkos->GetComm();
204 numRows = graph_kokkos->GetNodeNumVertices();
205 runOnHost = false;
206 }
207 } else if (IsType<RCP<LWGraph_kokkos>>(currentLevel, "Graph")) {
208 if ((aggregationBackend == "default") || (aggregationBackend == "Kokkos")) {
209 graph_kokkos = Get<RCP<LWGraph_kokkos>>(currentLevel, "Graph");
210 aggregates = rcp(new Aggregates(*graph_kokkos));
211 comm = graph_kokkos->GetComm();
212 numRows = graph_kokkos->GetNodeNumVertices();
213 runOnHost = false;
214 } else {
215 RCP<LWGraph_kokkos> tmp_graph_kokkos = Get<RCP<LWGraph_kokkos>>(currentLevel, "Graph");
216 graph = tmp_graph_kokkos->copyToHost();
217 aggregates = rcp(new Aggregates(*graph));
218 comm = graph->GetComm();
219 numRows = graph->GetNodeNumVertices();
220 runOnHost = true;
221 }
222 } else {
223 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Graph has bad type.");
224 }
225
226 if (!runOnHost) {
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");
228 // Sanity Checking: match ML behavior is not supported in UncoupledAggregation_Kokkos in Phase 1 , but it is in 2a and 2b
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");
230 }
231
232 // Build
233 aggregates->setObjectLabel("UC");
234
235 // construct aggStat information
238 AggStatHostType aggStatHost;
239 AggStatType aggStat;
240
241 if (runOnHost) {
242 aggStatHost = AggStatHostType(Kokkos::ViewAllocateWithoutInitializing("aggregation status"), numRows);
243 Kokkos::deep_copy(aggStatHost, READY);
244 } else {
245 aggStat = AggStatType(Kokkos::ViewAllocateWithoutInitializing("aggregation status"), numRows);
246 Kokkos::deep_copy(aggStat, READY);
247 }
248
249 // interface
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])
254 aggStatHost[i] = INTERFACE;
255 }
256 }
257
258 // Dirichlet nodes
259 {
260 if (runOnHost) {
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),
265 KOKKOS_LAMBDA(const LocalOrdinal nodeIdx) {
266 if (dirichletBoundaryMap(nodeIdx) == true) {
267 aggStatHost(nodeIdx) = BOUNDARY;
268 }
269 });
270 } else {
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),
275 KOKKOS_LAMBDA(const LocalOrdinal nodeIdx) {
276 if (dirichletBoundaryMap(nodeIdx) == true) {
277 aggStat(nodeIdx) = BOUNDARY;
278 }
279 });
280 }
281 }
282
283 if (OnePtMap != Teuchos::null) {
284 LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
285
286 if (runOnHost) {
287 GO indexBase = graph->GetDomainMap()->getIndexBase();
288 for (LO i = 0; i < numRows; i++) {
289 // reconstruct global row id (FIXME only works for contiguous maps)
290 GO grid = (graph->GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
291
292 for (LO kr = 0; kr < nDofsPerNode; kr++)
293 if (OnePtMap->isNodeGlobalElement(grid + kr))
294 aggStatHost(i) = ONEPT;
295 }
296 } else {
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),
304 KOKKOS_LAMBDA(const LocalOrdinal i) {
305 // reconstruct global row id (FIXME only works for contiguous maps)
306 GO grid = (lclDomainMap.getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
307
308 for (LO kr = 0; kr < nDofsPerNode; kr++)
309 if (lclOnePtMap.getLocalElement(grid + kr) != INVALID)
310 aggStat(i) = ONEPT;
311 });
312 }
313 }
314
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);
319
320 SubFactoryMonitor sfm(*this, "Algo \"MIS2\"", currentLevel);
321 using graph_t = typename LWGraph_kokkos::local_graph_type;
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();
329 lno_t numAggs = 0;
330 typename colinds_t::non_const_type labels;
331
332 if (aggAlgo == "mis2 coarsening") {
333 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: MIS-2 coarsening" << std::endl;
334 labels = KokkosGraph::graph_mis2_coarsen<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
335 } else if (aggAlgo == "mis2 aggregation") {
336 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: MIS-2 aggregation" << std::endl;
337 labels = KokkosGraph::graph_mis2_aggregate<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
338 }
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) {
347 aggStat(i) = AGGREGATED;
348 vertex2AggId(i, 0) = labels(i);
349 }
350 });
351 numNonAggregatedNodes = 0;
352 aggregates->SetNumAggregates(numAggs);
353 } else {
354 if (!runOnHost) {
355 DoGraphColoring(currentLevel, aggAlgo, pL.get<bool>("aggregation: deterministic"), graph_kokkos, aggregates);
356 if (IsPrint(Statistics1)) {
357 GetOStream(Statistics1) << " num colors: " << aggregates->GetGraphNumColors() << std::endl;
358 }
359 }
360
361 GO numGlobalRows = 0;
362 GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
363 if (IsPrint(Statistics1))
364 MueLu_sumAll(comm, as<GO>(numRows), numGlobalRows);
365 for (size_t a = 0; a < algos_.size(); a++) {
366 std::string phase = algos_[a]->description();
367 SubFactoryMonitor sfm2(*this, "Algo \"" + phase + "\"", currentLevel);
368
369 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
370 if (runOnHost)
371 algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStatHost, numNonAggregatedNodes);
372 else
373 algos_[a]->BuildAggregates(pL, *graph_kokkos, *aggregates, aggStat, numNonAggregatedNodes);
374 algos_[a]->SetProcRankVerbose(oldRank);
375
376 if (IsPrint(Statistics1)) {
377 GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
378 GO numLocalAggs = aggregates->GetNumAggregates(), numGlobalAggs = 0;
379 MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
380 MueLu_sumAll(comm, numLocalAggs, numGlobalAggs);
381
382 double aggPercent = 100 * as<double>(numGlobalAggregated) / as<double>(numGlobalRows);
383 if (aggPercent > 99.99 && aggPercent < 100.00) {
384 // Due to round off (for instance, for 140465733/140466897), we could
385 // get 100.00% display even if there are some remaining nodes. This
386 // is bad from the users point of view. It is much better to change
387 // it to display 99.99%.
388 aggPercent = 99.99;
389 }
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;
396 }
397 }
398 }
399
400 TEUCHOS_TEST_FOR_EXCEPTION(numNonAggregatedNodes, Exceptions::RuntimeError, "MueLu::UncoupledAggregationFactory::Build: Leftover nodes found! Error!");
401
402 aggregates->AggregatesCrossProcessors(false);
403 aggregates->ComputeAggregateSizes(true /*forceRecompute*/);
404
405 Set(currentLevel, "Aggregates", aggregates);
406}
407
408template <class LocalOrdinal, class GlobalOrdinal, class Node>
410 DoGraphColoring(Level& currentLevel,
411 const std::string& aggAlgo,
412 const bool deterministic,
413 const RCP<const LWGraph_kokkos> graph,
414 RCP<Aggregates> aggregates) const {
415 SubFactoryMonitor sfm(*this, "Algo \"Graph Coloring\"", currentLevel);
416
417 // LBV on Sept 06 2019: the note below is a little worrisome,
418 // can we guarantee that MueLu is never used on a non-symmetric
419 // graph?
420 // note: just using colinds_view in place of scalar_view_t type
421 // (it won't be used at all by symbolic SPGEMM)
422 using graph_t = typename LWGraph_kokkos::local_graph_type;
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>;
430 KernelHandle kh;
431 // leave gc algorithm choice as the default
432 kh.create_distance2_graph_coloring_handle();
433
434 // get the distance-2 graph coloring handle
435 auto coloringHandle = kh.get_distance2_graph_coloring_handle();
436
437 const LO numRows = graph->GetNodeNumVertices();
438
439 // Set the distance-2 graph coloring algorithm to use.
440 // Options:
441 // COLORING_D2_DEFAULT - Let the kernel handle pick the variation
442 // COLORING_D2_SERIAL - Use the legacy serial-only implementation
443 // COLORING_D2_VB - Use the parallel vertex based direct method
444 // COLORING_D2_VB_BIT - Same as VB but using the bitvector forbidden array
445 // COLORING_D2_VB_BIT_EF - Add experimental edge-filtering to VB_BIT
446 // COLORING_D2_NB_BIT - Net-based coloring (generally the fastest)
447 if (deterministic) {
448 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
449 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
450 } else if (aggAlgo == "serial") {
451 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
452 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
453 } else if (aggAlgo == "default") {
454 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_DEFAULT);
455 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: default" << std::endl;
456 } else if (aggAlgo == "vertex based") {
457 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB);
458 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based" << std::endl;
459 } else if (aggAlgo == "vertex based bit set") {
460 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT);
461 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based bit set" << std::endl;
462 } else if (aggAlgo == "edge filtering") {
463 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT_EF);
464 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: edge filtering" << std::endl;
465 } else if (aggAlgo == "net based bit set") {
466 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_NB_BIT);
467 if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: net based bit set" << std::endl;
468 } else {
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")
470 }
471
472 // Create device views for graph rowptrs/colinds
473 typename graph_t::row_map_type aRowptrs = graph->getRowPtrs();
474 typename graph_t::entries_type aColinds = graph->getEntries();
475
476 // run d2 graph coloring
477 // graph is symmetric so row map/entries and col map/entries are the same
478 {
479 SubFactoryMonitor sfm2(*this, "Algo \"Graph Coloring\": KokkosGraph Call", currentLevel); // CMS HACK
480 KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
481 }
482
483 // extract the colors and store them in the aggregates
484 aggregates->SetGraphColors(coloringHandle->get_vertex_colors());
485 aggregates->SetGraphNumColors(static_cast<LO>(coloringHandle->get_num_colors()));
486
487 // clean up coloring handle
488 kh.destroy_distance2_graph_coloring_handle();
489}
490
491} // namespace MueLu
492
493#endif /* MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_ */
#define SET_VALID_ENTRY(name)
#define MueLu_sumAll(rcpComm, in, out)
MueLu::DefaultLocalOrdinal LocalOrdinal
Container class for aggregation information.
Kokkos::View< unsigned *, typename LWGraphHostType::device_type > AggStatHostType
Kokkos::View< unsigned *, typename LWGraphType::device_type > AggStatType
Algorithm for coarsening a graph with uncoupled aggregation.
Among unaggregated points, see if we can make a reasonable size aggregate out of it.
Handle leftover nodes. Try to avoid singleton nodes.
Exception throws to report errors in the internal logical of the program.
Timer to be used in factories. Similar to Monitor but with additional timers.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
bool IsType(Level &level, const std::string &varName) const
void Set(Level &level, const std::string &varName, const T &data) const
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Default implementation of FactoryAcceptor::GetFactory().
Algorithm for coarsening a graph with uncoupled aggregation. creates aggregates along an interface us...
typename std::conditional< OnHost, typename local_graph_device_type::HostMirror, local_graph_device_type >::type local_graph_type
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput().
int GetLevelID() const
Return level number.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
static const NoFactory * get()
Algorithm for coarsening a graph with uncoupled aggregation. keep special marked nodes as singleton n...
virtual const Teuchos::ParameterList & GetParameterList() const
Builds one-to-one aggregates for all Dirichlet boundary nodes. For some applications this might be ne...
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void Build(Level &currentLevel) const
Build aggregates.
virtual ~UncoupledAggregationFactory()
Destructor.
void DoGraphColoring(Level &currentLevel, const std::string &aggAlgo, const bool deterministic, const RCP< const LWGraph_kokkos > graph, RCP< Aggregates > aggregates) const
std::vector< RCP< MueLu::AggregationAlgorithmBase< LocalOrdinal, GlobalOrdinal, Node > > > algos_
Append a new aggregation algorithm to list of aggregation algorithms.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
int GetProcRankVerbose() const
Get proc rank used for printing. Do not use this information for any other purpose....
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.