MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
41 namespace MueLu {
42 
43 template <class LocalOrdinal, class GlobalOrdinal, class Node>
45  : bDefinitionPhase_(true) {}
46 
47 template <class LocalOrdinal, class GlobalOrdinal, class Node>
49 
50 template <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 #undef SET_VALID_ENTRY
80 
81  // general variables needed in AggregationFactory
82  validParamList->set<RCP<const FactoryBase>>("Graph", null, "Generating factory of the graph");
83  validParamList->set<RCP<const FactoryBase>>("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
84 
85  // special variables necessary for OnePtAggregationAlgorithm
86  validParamList->set<std::string>("OnePt aggregate map name", "", "Name of input map for single node aggregates. (default='')");
87  validParamList->set<std::string>("OnePt aggregate map factory", "", "Generating factory of (DOF) map for single node aggregates.");
88  // validParamList->set< RCP<const FactoryBase> >("OnePt aggregate map factory", NoFactory::getRCP(), "Generating factory of (DOF) map for single node aggregates.");
89 
90  // InterfaceAggregation parameters
91  // validParamList->set< bool > ("aggregation: use interface aggregation", "false", "Flag to trigger aggregation along an interface using specified aggregate seeds.");
92  validParamList->set<std::string>("Interface aggregate map name", "", "Name of input map for interface aggregates. (default='')");
93  validParamList->set<std::string>("Interface aggregate map factory", "", "Generating factory of (DOF) map for interface aggregates.");
94  validParamList->set<RCP<const FactoryBase>>("nodeOnInterface", Teuchos::null, "Array specifying whether or not a node is on the interface (1 or 0).");
95 
96  return validParamList;
97 }
98 
99 template <class LocalOrdinal, class GlobalOrdinal, class Node>
101  Input(currentLevel, "Graph");
102  Input(currentLevel, "DofsPerNode");
103 
104  const ParameterList& pL = GetParameterList();
105 
106  // request special data necessary for OnePtAggregationAlgorithm
107  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
108  if (mapOnePtName.length() > 0) {
109  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
110  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
111  currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
112  } else {
113  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
114  currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
115  }
116  }
117 
118  // request special data necessary for InterfaceAggregation
119  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
120  if (currentLevel.GetLevelID() == 0) {
121  if (currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
122  currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
123  } else {
124  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
126  "nodeOnInterface was not provided by the user on level0!");
127  }
128  } else {
129  Input(currentLevel, "nodeOnInterface");
130  }
131  }
132 }
133 
134 template <class LocalOrdinal, class GlobalOrdinal, class Node>
136  FactoryMonitor m(*this, "Build", currentLevel);
137 
138  ParameterList pL = GetParameterList();
139  bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
140 
141  if (pL.get<int>("aggregation: max agg size") == -1)
142  pL.set("aggregation: max agg size", INT_MAX);
143 
144  // define aggregation algorithms
145  RCP<const FactoryBase> graphFact = GetFactory("Graph");
146 
147  // TODO Can we keep different aggregation algorithms over more Build calls?
148  algos_.clear();
149  algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
150  if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm(graphFact)));
151  if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm(graphFact)));
152  if (pL.get<bool>("aggregation: enable phase 1") == true) algos_.push_back(rcp(new AggregationPhase1Algorithm(graphFact)));
153  if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm(graphFact)));
154  if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm(graphFact)));
155  if (pL.get<bool>("aggregation: enable phase 3") == true) algos_.push_back(rcp(new AggregationPhase3Algorithm(graphFact)));
156 
157  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
158  RCP<Map> OnePtMap = Teuchos::null;
159  if (mapOnePtName.length()) {
160  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
161  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
162  OnePtMap = currentLevel.Get<RCP<Map>>(mapOnePtName, NoFactory::get());
163  } else {
164  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
165  OnePtMap = currentLevel.Get<RCP<Map>>(mapOnePtName, mapOnePtFact.get());
166  }
167  }
168 
169  // Set map for interface aggregates
170  std::string mapInterfaceName = pL.get<std::string>("Interface aggregate map name");
171  RCP<Map> InterfaceMap = Teuchos::null;
172 
173  RCP<const LWGraph> graph;
174  RCP<const LWGraph_kokkos> graph_kokkos;
175  RCP<Aggregates> aggregates;
177  LO numRows;
178  bool runOnHost;
179  if (IsType<RCP<LWGraph>>(currentLevel, "Graph")) {
180  graph = Get<RCP<LWGraph>>(currentLevel, "Graph");
181  aggregates = rcp(new Aggregates(*graph));
182  comm = graph->GetComm();
183  numRows = graph->GetNodeNumVertices();
184  runOnHost = true;
185  } else {
186  graph_kokkos = Get<RCP<LWGraph_kokkos>>(currentLevel, "Graph");
187  aggregates = rcp(new Aggregates(*graph_kokkos));
188  comm = graph_kokkos->GetComm();
189  numRows = graph_kokkos->GetNodeNumVertices();
190  runOnHost = false;
191 
192  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");
193  // Sanity Checking: match ML behavior is not supported in UncoupledAggregation_Kokkos in Phase 1 or Phase 2b, but is in 2a
194  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");
195  TEUCHOS_TEST_FOR_EXCEPTION(pL.get<bool>("aggregation: match ML phase2b"), std::invalid_argument, "Option: 'aggregation: match ML phase2b' is not supported in the Kokkos version of uncoupled aggregation");
196  }
197 
198  // Build
199  aggregates->setObjectLabel("UC");
200 
201  // construct aggStat information
204  AggStatHostType aggStatHost;
205  AggStatType aggStat;
206 
207  if (runOnHost) {
208  aggStatHost = AggStatHostType(Kokkos::ViewAllocateWithoutInitializing("aggregation status"), numRows);
209  Kokkos::deep_copy(aggStatHost, READY);
210  } else {
211  aggStat = AggStatType(Kokkos::ViewAllocateWithoutInitializing("aggregation status"), numRows);
212  Kokkos::deep_copy(aggStat, READY);
213  }
214 
215  // interface
216  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
217  Teuchos::Array<LO> nodeOnInterface = Get<Array<LO>>(currentLevel, "nodeOnInterface");
218  for (LO i = 0; i < numRows; i++) {
219  if (nodeOnInterface[i])
220  aggStatHost[i] = INTERFACE;
221  }
222  }
223 
224  // Dirichlet nodes
225  {
226  if (runOnHost) {
227  auto dirichletBoundaryMap = graph->GetBoundaryNodeMap();
228  Kokkos::parallel_for(
229  "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
230  Kokkos::RangePolicy<LocalOrdinal, typename LWGraph::execution_space>(0, numRows),
231  KOKKOS_LAMBDA(const LocalOrdinal nodeIdx) {
232  if (dirichletBoundaryMap(nodeIdx) == true) {
233  aggStatHost(nodeIdx) = BOUNDARY;
234  }
235  });
236  } else {
237  auto dirichletBoundaryMap = graph_kokkos->GetBoundaryNodeMap();
238  Kokkos::parallel_for(
239  "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
240  Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
241  KOKKOS_LAMBDA(const LocalOrdinal nodeIdx) {
242  if (dirichletBoundaryMap(nodeIdx) == true) {
243  aggStat(nodeIdx) = BOUNDARY;
244  }
245  });
246  }
247  }
248 
249  if (OnePtMap != Teuchos::null) {
250  LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
251 
252  if (runOnHost) {
253  GO indexBase = graph->GetDomainMap()->getIndexBase();
254  for (LO i = 0; i < numRows; i++) {
255  // reconstruct global row id (FIXME only works for contiguous maps)
256  GO grid = (graph->GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
257 
258  for (LO kr = 0; kr < nDofsPerNode; kr++)
259  if (OnePtMap->isNodeGlobalElement(grid + kr))
260  aggStatHost(i) = ONEPT;
261  }
262  } else {
263  GO indexBase = graph_kokkos->GetDomainMap()->getIndexBase();
264  auto lclDomainMap = graph_kokkos->GetDomainMap()->getLocalMap();
265  auto lclOnePtMap = OnePtMap->getLocalMap();
266  const LocalOrdinal INVALID = Tpetra::Details::OrdinalTraits<LocalOrdinal>::invalid();
267  Kokkos::parallel_for(
268  "MueLu - UncoupledAggregation: tagging OnePt map",
269  Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
270  KOKKOS_LAMBDA(const LocalOrdinal i) {
271  // reconstruct global row id (FIXME only works for contiguous maps)
272  GO grid = (lclDomainMap.getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
273 
274  for (LO kr = 0; kr < nDofsPerNode; kr++)
275  if (lclOnePtMap.getLocalElement(grid + kr) != INVALID)
276  aggStat(i) = ONEPT;
277  });
278  }
279  }
280 
281  LO numNonAggregatedNodes = numRows;
282  std::string aggAlgo = pL.get<std::string>("aggregation: coloring algorithm");
283  if (aggAlgo == "mis2 coarsening" || aggAlgo == "mis2 aggregation") {
284  TEUCHOS_ASSERT(!runOnHost);
285 
286  SubFactoryMonitor sfm(*this, "Algo \"MIS2\"", currentLevel);
287  using graph_t = typename LWGraph_kokkos::local_graph_type;
288  using device_t = typename graph_t::device_type;
289  using exec_space = typename device_t::execution_space;
290  using rowmap_t = typename graph_t::row_map_type;
291  using colinds_t = typename graph_t::entries_type;
292  using lno_t = typename colinds_t::non_const_value_type;
293  rowmap_t aRowptrs = graph_kokkos->getRowPtrs();
294  colinds_t aColinds = graph_kokkos->getEntries();
295  lno_t numAggs = 0;
296  typename colinds_t::non_const_type labels;
297 
298  if (aggAlgo == "mis2 coarsening") {
299  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: MIS-2 coarsening" << std::endl;
300  labels = KokkosGraph::graph_mis2_coarsen<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
301  } else if (aggAlgo == "mis2 aggregation") {
302  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: MIS-2 aggregation" << std::endl;
303  labels = KokkosGraph::graph_mis2_aggregate<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
304  }
305  auto vertex2AggId = aggregates->GetVertex2AggId()->getDeviceLocalView(Xpetra::Access::ReadWrite);
306  auto procWinner = aggregates->GetProcWinner()->getDeviceLocalView(Xpetra::Access::OverwriteAll);
307  int rank = comm->getRank();
308  Kokkos::parallel_for(
309  Kokkos::RangePolicy<exec_space>(0, numRows),
310  KOKKOS_LAMBDA(lno_t i) {
311  procWinner(i, 0) = rank;
312  if (aggStat(i) == READY) {
313  aggStat(i) = AGGREGATED;
314  vertex2AggId(i, 0) = labels(i);
315  }
316  });
317  numNonAggregatedNodes = 0;
318  aggregates->SetNumAggregates(numAggs);
319  } else {
320  if (!runOnHost) {
321  DoGraphColoring(currentLevel, aggAlgo, pL.get<bool>("aggregation: deterministic"), graph_kokkos, aggregates);
322  if (IsPrint(Statistics1)) {
323  GetOStream(Statistics1) << " num colors: " << aggregates->GetGraphNumColors() << std::endl;
324  }
325  }
326 
327  GO numGlobalRows = 0;
328  GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
329  if (IsPrint(Statistics1))
330  MueLu_sumAll(comm, as<GO>(numRows), numGlobalRows);
331  for (size_t a = 0; a < algos_.size(); a++) {
332  std::string phase = algos_[a]->description();
333  SubFactoryMonitor sfm2(*this, "Algo \"" + phase + "\"", currentLevel);
334 
335  int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
336  if (runOnHost)
337  algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStatHost, numNonAggregatedNodes);
338  else
339  algos_[a]->BuildAggregates(pL, *graph_kokkos, *aggregates, aggStat, numNonAggregatedNodes);
340  algos_[a]->SetProcRankVerbose(oldRank);
341 
342  if (IsPrint(Statistics1)) {
343  GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
344  GO numLocalAggs = aggregates->GetNumAggregates(), numGlobalAggs = 0;
345  MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
346  MueLu_sumAll(comm, numLocalAggs, numGlobalAggs);
347 
348  double aggPercent = 100 * as<double>(numGlobalAggregated) / as<double>(numGlobalRows);
349  if (aggPercent > 99.99 && aggPercent < 100.00) {
350  // Due to round off (for instance, for 140465733/140466897), we could
351  // get 100.00% display even if there are some remaining nodes. This
352  // is bad from the users point of view. It is much better to change
353  // it to display 99.99%.
354  aggPercent = 99.99;
355  }
356  GetOStream(Statistics1) << " aggregated : " << (numGlobalAggregated - numGlobalAggregatedPrev) << " (phase), " << std::fixed
357  << std::setprecision(2) << numGlobalAggregated << "/" << numGlobalRows << " [" << aggPercent << "%] (total)\n"
358  << " remaining : " << numGlobalRows - numGlobalAggregated << "\n"
359  << " aggregates : " << numGlobalAggs - numGlobalAggsPrev << " (phase), " << numGlobalAggs << " (total)" << std::endl;
360  numGlobalAggregatedPrev = numGlobalAggregated;
361  numGlobalAggsPrev = numGlobalAggs;
362  }
363  }
364  }
365 
366  TEUCHOS_TEST_FOR_EXCEPTION(numNonAggregatedNodes, Exceptions::RuntimeError, "MueLu::UncoupledAggregationFactory::Build: Leftover nodes found! Error!");
367 
368  aggregates->AggregatesCrossProcessors(false);
369  aggregates->ComputeAggregateSizes(true /*forceRecompute*/);
370 
371  Set(currentLevel, "Aggregates", aggregates);
372 }
373 
374 template <class LocalOrdinal, class GlobalOrdinal, class Node>
376  DoGraphColoring(Level& currentLevel,
377  const std::string& aggAlgo,
378  const bool deterministic,
379  const RCP<const LWGraph_kokkos> graph,
380  RCP<Aggregates> aggregates) const {
381  SubFactoryMonitor sfm(*this, "Algo \"Graph Coloring\"", currentLevel);
382 
383  // LBV on Sept 06 2019: the note below is a little worrisome,
384  // can we guarantee that MueLu is never used on a non-symmetric
385  // graph?
386  // note: just using colinds_view in place of scalar_view_t type
387  // (it won't be used at all by symbolic SPGEMM)
388  using graph_t = typename LWGraph_kokkos::local_graph_type;
389  using KernelHandle = KokkosKernels::Experimental::
390  KokkosKernelsHandle<typename graph_t::row_map_type::value_type,
391  typename graph_t::entries_type::value_type,
392  typename graph_t::entries_type::value_type,
393  typename graph_t::device_type::execution_space,
394  typename graph_t::device_type::memory_space,
395  typename graph_t::device_type::memory_space>;
396  KernelHandle kh;
397  // leave gc algorithm choice as the default
398  kh.create_distance2_graph_coloring_handle();
399 
400  // get the distance-2 graph coloring handle
401  auto coloringHandle = kh.get_distance2_graph_coloring_handle();
402 
403  const LO numRows = graph->GetNodeNumVertices();
404 
405  // Set the distance-2 graph coloring algorithm to use.
406  // Options:
407  // COLORING_D2_DEFAULT - Let the kernel handle pick the variation
408  // COLORING_D2_SERIAL - Use the legacy serial-only implementation
409  // COLORING_D2_VB - Use the parallel vertex based direct method
410  // COLORING_D2_VB_BIT - Same as VB but using the bitvector forbidden array
411  // COLORING_D2_VB_BIT_EF - Add experimental edge-filtering to VB_BIT
412  // COLORING_D2_NB_BIT - Net-based coloring (generally the fastest)
413  if (deterministic) {
414  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
415  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
416  } else if (aggAlgo == "serial") {
417  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
418  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
419  } else if (aggAlgo == "default") {
420  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_DEFAULT);
421  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: default" << std::endl;
422  } else if (aggAlgo == "vertex based") {
423  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB);
424  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based" << std::endl;
425  } else if (aggAlgo == "vertex based bit set") {
426  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT);
427  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based bit set" << std::endl;
428  } else if (aggAlgo == "edge filtering") {
429  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT_EF);
430  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: edge filtering" << std::endl;
431  } else if (aggAlgo == "net based bit set") {
432  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_NB_BIT);
433  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: net based bit set" << std::endl;
434  } else {
435  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")
436  }
437 
438  // Create device views for graph rowptrs/colinds
439  typename graph_t::row_map_type aRowptrs = graph->getRowPtrs();
440  typename graph_t::entries_type aColinds = graph->getEntries();
441 
442  // run d2 graph coloring
443  // graph is symmetric so row map/entries and col map/entries are the same
444  {
445  SubFactoryMonitor sfm2(*this, "Algo \"Graph Coloring\": KokkosGraph Call", currentLevel); // CMS HACK
446  KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
447  }
448 
449  // extract the colors and store them in the aggregates
450  aggregates->SetGraphColors(coloringHandle->get_vertex_colors());
451  aggregates->SetGraphNumColors(static_cast<LO>(coloringHandle->get_num_colors()));
452 
453  // clean up coloring handle
454  kh.destroy_distance2_graph_coloring_handle();
455 }
456 
457 } // namespace MueLu
458 
459 #endif /* MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_ */
Kokkos::View< unsigned *, typename LWGraphHostType::device_type > AggStatHostType
Algorithm for coarsening a graph with uncoupled aggregation. keep special marked nodes as singleton n...
#define MueLu_sumAll(rcpComm, in, out)
MueLu::DefaultLocalOrdinal LocalOrdinal
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level-&gt;Get&lt; RCP&lt;Matrix&gt; &gt;(&quot;A&quot;, factory) if factory == NULL =&gt; use default factory.
void DoGraphColoring(Level &currentLevel, const std::string &aggAlgo, const bool deterministic, const RCP< const LWGraph_kokkos > graph, RCP< Aggregates > aggregates) const
const RCP< LOVector > & GetProcWinner() const
Returns constant vector that maps local node IDs to owning processor IDs.
KOKKOS_INLINE_FUNCTION row_type getRowPtrs() const
Return the row pointers of the local graph.
void SetGraphNumColors(const LO graphNumColors)
Set the number of colors needed by the distance 2 coloring.
Container class for aggregation information.
KOKKOS_INLINE_FUNCTION LO GetNumAggregates() const
typename std::conditional< OnHost, typename local_graph_device_type::HostMirror, local_graph_device_type >::type local_graph_type
void setValidator(RCP< const ParameterEntryValidator > const &validator)
virtual ~UncoupledAggregationFactory()
Destructor.
GlobalOrdinal GO
T & get(const std::string &name, T def_value)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Print more statistics.
LocalOrdinal LO
T * get() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
KOKKOS_INLINE_FUNCTION const boundary_nodes_type GetBoundaryNodeMap() const
Returns map with global ids of boundary nodes.
void DeclareInput(Level &currentLevel) const
Input.
static const NoFactory * get()
Algorithm for coarsening a graph with uncoupled aggregation. creates aggregates along an interface us...
Builds one-to-one aggregates for all Dirichlet boundary nodes. For some applications this might be ne...
LO GetGraphNumColors()
Get the number of colors needed by the distance 2 coloring.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
KOKKOS_INLINE_FUNCTION entries_type getEntries() const
Return the list entries in the local graph.
void SetGraphColors(colors_view_type graphColors)
Set a distance 2 coloring of the underlying graph. The coloring is computed and set during Phase1 of ...
virtual void setObjectLabel(const std::string &objectLabel)
const RCP< LOMultiVector > & GetVertex2AggId() const
Returns constant vector that maps local node IDs to local aggregates IDs.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
#define SET_VALID_ENTRY(name)
Among unaggregated points, see if we can make a reasonable size aggregate out of it.IdeaAmong unaggregated points, see if we can make a reasonable size aggregate out of it. We do this by looking at neighbors and seeing how many are unaggregated and on my processor. Loosely, base the number of new aggregates created on the percentage of unaggregated nodes.
void Build(Level &currentLevel) const
Build aggregates.
Add leftovers to existing aggregatesIdeaIn phase 2b non-aggregated nodes are added to existing aggreg...
const RCP< const Map > GetDomainMap() const
KOKKOS_INLINE_FUNCTION void AggregatesCrossProcessors(const bool &flag)
Record whether aggregates include DOFs from other processes.
Algorithm for coarsening a graph with uncoupled aggregation.
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:51
Exception throws to report errors in the internal logical of the program.
#define TEUCHOS_ASSERT(assertion_test)
Handle leftover nodes. Try to avoid singleton nodesIdeaIn phase 3 we try to stick unaggregated nodes ...
ParameterEntry & getEntry(const std::string &name)
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
const RCP< const Teuchos::Comm< int > > GetComm() const
aggregates_sizes_type::const_type ComputeAggregateSizes(bool forceRecompute=false) const
Compute sizes of aggregates.
Kokkos::View< unsigned *, typename LWGraphType::device_type > AggStatType
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
void SetNumAggregates(LO nAggregates)
Set number of local aggregates on current processor.