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  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 
101 template <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 
136 template <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;
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 
408 template <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_ */
Kokkos::View< unsigned *, typename LWGraphHostType::device_type > AggStatHostType
Algorithm for coarsening a graph with uncoupled aggregation. keep special marked nodes as singleton n...
RCP< MueLu::LWGraph< LocalOrdinal, GlobalOrdinal, Node > > copyToHost()
#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...
RCP< MueLu::LWGraph_kokkos< LocalOrdinal, GlobalOrdinal, Node > > copyToDevice()
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.