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 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
47 #define MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
48 
49 #include <climits>
50 
51 #include <Xpetra_Map.hpp>
52 #include <Xpetra_Vector.hpp>
53 #include <Xpetra_MultiVectorFactory.hpp>
54 #include <Xpetra_VectorFactory.hpp>
55 
57 
58 #include "MueLu_InterfaceAggregationAlgorithm.hpp"
59 #include "MueLu_OnePtAggregationAlgorithm.hpp"
60 #include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
61 
62 #include "MueLu_AggregationPhase1Algorithm.hpp"
63 #include "MueLu_AggregationPhase2aAlgorithm.hpp"
64 #include "MueLu_AggregationPhase2bAlgorithm.hpp"
65 #include "MueLu_AggregationPhase3Algorithm.hpp"
66 
67 #include "MueLu_Level.hpp"
68 #include "MueLu_LWGraph.hpp"
69 #include "MueLu_Aggregates.hpp"
70 #include "MueLu_MasterList.hpp"
71 #include "MueLu_Monitor.hpp"
72 
73 #include "KokkosGraph_Distance2ColorHandle.hpp"
74 #include "KokkosGraph_Distance2Color.hpp"
75 #include "KokkosGraph_MIS2.hpp"
76 
77 namespace MueLu {
78 
79 template <class LocalOrdinal, class GlobalOrdinal, class Node>
81  : bDefinitionPhase_(true) {}
82 
83 template <class LocalOrdinal, class GlobalOrdinal, class Node>
85  RCP<ParameterList> validParamList = rcp(new ParameterList());
86 
87  // Aggregation parameters (used in aggregation algorithms)
88  // TODO introduce local member function for each aggregation algorithm such that each aggregation algorithm can define its own parameters
89 
90 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
91  SET_VALID_ENTRY("aggregation: max agg size");
92  SET_VALID_ENTRY("aggregation: min agg size");
93  SET_VALID_ENTRY("aggregation: max selected neighbors");
94  SET_VALID_ENTRY("aggregation: ordering");
95  validParamList->getEntry("aggregation: ordering").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("natural", "graph", "random"))));
96  SET_VALID_ENTRY("aggregation: deterministic");
97  SET_VALID_ENTRY("aggregation: coloring algorithm");
98  SET_VALID_ENTRY("aggregation: enable phase 1");
99  SET_VALID_ENTRY("aggregation: enable phase 2a");
100  SET_VALID_ENTRY("aggregation: enable phase 2b");
101  SET_VALID_ENTRY("aggregation: enable phase 3");
102  SET_VALID_ENTRY("aggregation: match ML phase1");
103  SET_VALID_ENTRY("aggregation: match ML phase2a");
104  SET_VALID_ENTRY("aggregation: match ML phase2b");
105  SET_VALID_ENTRY("aggregation: phase2a agg factor");
106  SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
107  SET_VALID_ENTRY("aggregation: allow user-specified singletons");
108  SET_VALID_ENTRY("aggregation: use interface aggregation");
109  SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
110  SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
111  SET_VALID_ENTRY("aggregation: compute aggregate qualities");
112  SET_VALID_ENTRY("aggregation: phase 1 algorithm");
113 #undef SET_VALID_ENTRY
114 
115  // general variables needed in AggregationFactory
116  validParamList->set<RCP<const FactoryBase>>("Graph", null, "Generating factory of the graph");
117  validParamList->set<RCP<const FactoryBase>>("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
118  validParamList->set<RCP<const FactoryBase>>("AggregateQualities", null, "Generating factory for variable \'AggregateQualities\'");
119 
120  // special variables necessary for OnePtAggregationAlgorithm
121  validParamList->set<std::string>("OnePt aggregate map name", "", "Name of input map for single node aggregates. (default='')");
122  validParamList->set<std::string>("OnePt aggregate map factory", "", "Generating factory of (DOF) map for single node aggregates.");
123  // validParamList->set< RCP<const FactoryBase> >("OnePt aggregate map factory", NoFactory::getRCP(), "Generating factory of (DOF) map for single node aggregates.");
124 
125  // InterfaceAggregation parameters
126  // validParamList->set< bool > ("aggregation: use interface aggregation", "false", "Flag to trigger aggregation along an interface using specified aggregate seeds.");
127  validParamList->set<std::string>("Interface aggregate map name", "", "Name of input map for interface aggregates. (default='')");
128  validParamList->set<std::string>("Interface aggregate map factory", "", "Generating factory of (DOF) map for interface aggregates.");
129  validParamList->set<RCP<const FactoryBase>>("nodeOnInterface", Teuchos::null, "Array specifying whether or not a node is on the interface (1 or 0).");
130 
131  return validParamList;
132 }
133 
134 template <class LocalOrdinal, class GlobalOrdinal, class Node>
136  Input(currentLevel, "Graph");
137  Input(currentLevel, "DofsPerNode");
138 
139  const ParameterList& pL = GetParameterList();
140 
141  // request special data necessary for OnePtAggregationAlgorithm
142  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
143  if (mapOnePtName.length() > 0) {
144  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
145  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
146  currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
147  } else {
148  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
149  currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
150  }
151  }
152 
153  // request special data necessary for InterfaceAggregation
154  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
155  if (currentLevel.GetLevelID() == 0) {
156  if (currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
157  currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
158  } else {
159  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
161  "nodeOnInterface was not provided by the user on level0!");
162  }
163  } else {
164  Input(currentLevel, "nodeOnInterface");
165  }
166  }
167 
168  if (pL.get<bool>("aggregation: compute aggregate qualities")) {
169  Input(currentLevel, "AggregateQualities");
170  }
171 }
172 
173 template <class LocalOrdinal, class GlobalOrdinal, class Node>
175  FactoryMonitor m(*this, "Build", currentLevel);
176 
177  ParameterList pL = GetParameterList();
178  bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
179 
180  if (pL.get<int>("aggregation: max agg size") == -1)
181  pL.set("aggregation: max agg size", INT_MAX);
182 
183  // define aggregation algorithms
184  RCP<const FactoryBase> graphFact = GetFactory("Graph");
185 
186  // TODO Can we keep different aggregation algorithms over more Build calls?
187  algos_.clear();
188  algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
189  if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm(graphFact)));
190  if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm(graphFact)));
191  if (pL.get<bool>("aggregation: enable phase 1") == true) algos_.push_back(rcp(new AggregationPhase1Algorithm(graphFact)));
192  if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm(graphFact)));
193  if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm(graphFact)));
194  if (pL.get<bool>("aggregation: enable phase 3") == true) algos_.push_back(rcp(new AggregationPhase3Algorithm(graphFact)));
195 
196  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
197  RCP<Map> OnePtMap = Teuchos::null;
198  if (mapOnePtName.length()) {
199  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
200  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
201  OnePtMap = currentLevel.Get<RCP<Map>>(mapOnePtName, NoFactory::get());
202  } else {
203  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
204  OnePtMap = currentLevel.Get<RCP<Map>>(mapOnePtName, mapOnePtFact.get());
205  }
206  }
207 
208  // Set map for interface aggregates
209  std::string mapInterfaceName = pL.get<std::string>("Interface aggregate map name");
210  RCP<Map> InterfaceMap = Teuchos::null;
211 
212  RCP<const LWGraph> graph;
213  RCP<const LWGraph_kokkos> graph_kokkos;
214  RCP<Aggregates> aggregates;
216  LO numRows;
217  bool runOnHost;
218  if (IsType<RCP<LWGraph>>(currentLevel, "Graph")) {
219  graph = Get<RCP<LWGraph>>(currentLevel, "Graph");
220  aggregates = rcp(new Aggregates(*graph));
221  comm = graph->GetComm();
222  numRows = graph->GetNodeNumVertices();
223  runOnHost = true;
224  } else {
225  graph_kokkos = Get<RCP<LWGraph_kokkos>>(currentLevel, "Graph");
226  aggregates = rcp(new Aggregates(*graph_kokkos));
227  comm = graph_kokkos->GetComm();
228  numRows = graph_kokkos->GetNodeNumVertices();
229  runOnHost = false;
230 
231  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");
232  // Sanity Checking: match ML behavior is not supported in UncoupledAggregation_Kokkos in Phase 1 or Phase 2b, but is in 2a
233  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");
234  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");
235  }
236 
237  // Build
238  aggregates->setObjectLabel("UC");
239 
240  // construct aggStat information
243  AggStatHostType aggStatHost;
244  AggStatType aggStat;
245 
246  if (runOnHost) {
247  aggStatHost = AggStatHostType(Kokkos::ViewAllocateWithoutInitializing("aggregation status"), numRows);
248  Kokkos::deep_copy(aggStatHost, READY);
249  } else {
250  aggStat = AggStatType(Kokkos::ViewAllocateWithoutInitializing("aggregation status"), numRows);
251  Kokkos::deep_copy(aggStat, READY);
252  }
253 
254  // interface
255  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
256  Teuchos::Array<LO> nodeOnInterface = Get<Array<LO>>(currentLevel, "nodeOnInterface");
257  for (LO i = 0; i < numRows; i++) {
258  if (nodeOnInterface[i])
259  aggStatHost[i] = INTERFACE;
260  }
261  }
262 
263  // Dirichlet nodes
264  {
265  if (runOnHost) {
266  auto dirichletBoundaryMap = graph->GetBoundaryNodeMap();
267  Kokkos::parallel_for(
268  "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
269  Kokkos::RangePolicy<LocalOrdinal, typename LWGraph::execution_space>(0, numRows),
270  KOKKOS_LAMBDA(const LocalOrdinal nodeIdx) {
271  if (dirichletBoundaryMap(nodeIdx) == true) {
272  aggStatHost(nodeIdx) = BOUNDARY;
273  }
274  });
275  } else {
276  auto dirichletBoundaryMap = graph_kokkos->GetBoundaryNodeMap();
277  Kokkos::parallel_for(
278  "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
279  Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
280  KOKKOS_LAMBDA(const LocalOrdinal nodeIdx) {
281  if (dirichletBoundaryMap(nodeIdx) == true) {
282  aggStat(nodeIdx) = BOUNDARY;
283  }
284  });
285  }
286  }
287 
288  if (OnePtMap != Teuchos::null) {
289  LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
290 
291  if (runOnHost) {
292  GO indexBase = graph->GetDomainMap()->getIndexBase();
293  for (LO i = 0; i < numRows; i++) {
294  // reconstruct global row id (FIXME only works for contiguous maps)
295  GO grid = (graph->GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
296 
297  for (LO kr = 0; kr < nDofsPerNode; kr++)
298  if (OnePtMap->isNodeGlobalElement(grid + kr))
299  aggStatHost(i) = ONEPT;
300  }
301  } else {
302  GO indexBase = graph_kokkos->GetDomainMap()->getIndexBase();
303  auto lclDomainMap = graph_kokkos->GetDomainMap()->getLocalMap();
304  auto lclOnePtMap = OnePtMap->getLocalMap();
305  const LocalOrdinal INVALID = Tpetra::Details::OrdinalTraits<LocalOrdinal>::invalid();
306  Kokkos::parallel_for(
307  "MueLu - UncoupledAggregation: tagging OnePt map",
308  Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
309  KOKKOS_LAMBDA(const LocalOrdinal i) {
310  // reconstruct global row id (FIXME only works for contiguous maps)
311  GO grid = (lclDomainMap.getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
312 
313  for (LO kr = 0; kr < nDofsPerNode; kr++)
314  if (lclOnePtMap.getLocalElement(grid + kr) != INVALID)
315  aggStat(i) = ONEPT;
316  });
317  }
318  }
319 
320  LO numNonAggregatedNodes = numRows;
321  std::string aggAlgo = pL.get<std::string>("aggregation: coloring algorithm");
322  if (aggAlgo == "mis2 coarsening" || aggAlgo == "mis2 aggregation") {
323  TEUCHOS_ASSERT(!runOnHost);
324 
325  SubFactoryMonitor sfm(*this, "Algo \"MIS2\"", currentLevel);
326  using graph_t = typename LWGraph_kokkos::local_graph_type;
327  using device_t = typename graph_t::device_type;
328  using exec_space = typename device_t::execution_space;
329  using rowmap_t = typename graph_t::row_map_type;
330  using colinds_t = typename graph_t::entries_type;
331  using lno_t = typename colinds_t::non_const_value_type;
332  rowmap_t aRowptrs = graph_kokkos->getRowPtrs();
333  colinds_t aColinds = graph_kokkos->getEntries();
334  lno_t numAggs = 0;
335  typename colinds_t::non_const_type labels;
336 
337  if (aggAlgo == "mis2 coarsening") {
338  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: MIS-2 coarsening" << std::endl;
339  labels = KokkosGraph::graph_mis2_coarsen<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
340  } else if (aggAlgo == "mis2 aggregation") {
341  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: MIS-2 aggregation" << std::endl;
342  labels = KokkosGraph::graph_mis2_aggregate<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
343  }
344  auto vertex2AggId = aggregates->GetVertex2AggId()->getDeviceLocalView(Xpetra::Access::ReadWrite);
345  auto procWinner = aggregates->GetProcWinner()->getDeviceLocalView(Xpetra::Access::OverwriteAll);
346  int rank = comm->getRank();
347  Kokkos::parallel_for(
348  Kokkos::RangePolicy<exec_space>(0, numRows),
349  KOKKOS_LAMBDA(lno_t i) {
350  procWinner(i, 0) = rank;
351  if (aggStat(i) == READY) {
352  aggStat(i) = AGGREGATED;
353  vertex2AggId(i, 0) = labels(i);
354  }
355  });
356  numNonAggregatedNodes = 0;
357  aggregates->SetNumAggregates(numAggs);
358  } else {
359  if (!runOnHost) {
360  DoGraphColoring(currentLevel, aggAlgo, pL.get<bool>("aggregation: deterministic"), graph_kokkos, aggregates);
361  if (IsPrint(Statistics1)) {
362  GetOStream(Statistics1) << " num colors: " << aggregates->GetGraphNumColors() << std::endl;
363  }
364  }
365 
366  GO numGlobalRows = 0;
367  GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
368  if (IsPrint(Statistics1))
369  MueLu_sumAll(comm, as<GO>(numRows), numGlobalRows);
370  for (size_t a = 0; a < algos_.size(); a++) {
371  std::string phase = algos_[a]->description();
372  SubFactoryMonitor sfm2(*this, "Algo \"" + phase + "\"", currentLevel);
373 
374  int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
375  if (runOnHost)
376  algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStatHost, numNonAggregatedNodes);
377  else
378  algos_[a]->BuildAggregates(pL, *graph_kokkos, *aggregates, aggStat, numNonAggregatedNodes);
379  algos_[a]->SetProcRankVerbose(oldRank);
380 
381  if (IsPrint(Statistics1)) {
382  GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
383  GO numLocalAggs = aggregates->GetNumAggregates(), numGlobalAggs = 0;
384  MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
385  MueLu_sumAll(comm, numLocalAggs, numGlobalAggs);
386 
387  double aggPercent = 100 * as<double>(numGlobalAggregated) / as<double>(numGlobalRows);
388  if (aggPercent > 99.99 && aggPercent < 100.00) {
389  // Due to round off (for instance, for 140465733/140466897), we could
390  // get 100.00% display even if there are some remaining nodes. This
391  // is bad from the users point of view. It is much better to change
392  // it to display 99.99%.
393  aggPercent = 99.99;
394  }
395  GetOStream(Statistics1) << " aggregated : " << (numGlobalAggregated - numGlobalAggregatedPrev) << " (phase), " << std::fixed
396  << std::setprecision(2) << numGlobalAggregated << "/" << numGlobalRows << " [" << aggPercent << "%] (total)\n"
397  << " remaining : " << numGlobalRows - numGlobalAggregated << "\n"
398  << " aggregates : " << numGlobalAggs - numGlobalAggsPrev << " (phase), " << numGlobalAggs << " (total)" << std::endl;
399  numGlobalAggregatedPrev = numGlobalAggregated;
400  numGlobalAggsPrev = numGlobalAggs;
401  }
402  }
403  }
404 
405  TEUCHOS_TEST_FOR_EXCEPTION(numNonAggregatedNodes, Exceptions::RuntimeError, "MueLu::UncoupledAggregationFactory::Build: Leftover nodes found! Error!");
406 
407  aggregates->AggregatesCrossProcessors(false);
408  aggregates->ComputeAggregateSizes(true /*forceRecompute*/);
409 
410  Set(currentLevel, "Aggregates", aggregates);
411 
412  if (pL.get<bool>("aggregation: compute aggregate qualities")) {
413  RCP<Xpetra::MultiVector<DefaultScalar, LO, GO, Node>> aggQualities = Get<RCP<Xpetra::MultiVector<DefaultScalar, LO, GO, Node>>>(currentLevel, "AggregateQualities");
414  }
415 }
416 
417 template <class LocalOrdinal, class GlobalOrdinal, class Node>
419  DoGraphColoring(Level& currentLevel,
420  const std::string& aggAlgo,
421  const bool deterministic,
422  const RCP<const LWGraph_kokkos> graph,
423  RCP<Aggregates> aggregates) const {
424  SubFactoryMonitor sfm(*this, "Algo \"Graph Coloring\"", currentLevel);
425 
426  // LBV on Sept 06 2019: the note below is a little worrisome,
427  // can we guarantee that MueLu is never used on a non-symmetric
428  // graph?
429  // note: just using colinds_view in place of scalar_view_t type
430  // (it won't be used at all by symbolic SPGEMM)
431  using graph_t = typename LWGraph_kokkos::local_graph_type;
432  using KernelHandle = KokkosKernels::Experimental::
433  KokkosKernelsHandle<typename graph_t::row_map_type::value_type,
434  typename graph_t::entries_type::value_type,
435  typename graph_t::entries_type::value_type,
436  typename graph_t::device_type::execution_space,
437  typename graph_t::device_type::memory_space,
438  typename graph_t::device_type::memory_space>;
439  KernelHandle kh;
440  // leave gc algorithm choice as the default
441  kh.create_distance2_graph_coloring_handle();
442 
443  // get the distance-2 graph coloring handle
444  auto coloringHandle = kh.get_distance2_graph_coloring_handle();
445 
446  const LO numRows = graph->GetNodeNumVertices();
447 
448  // Set the distance-2 graph coloring algorithm to use.
449  // Options:
450  // COLORING_D2_DEFAULT - Let the kernel handle pick the variation
451  // COLORING_D2_SERIAL - Use the legacy serial-only implementation
452  // COLORING_D2_VB - Use the parallel vertex based direct method
453  // COLORING_D2_VB_BIT - Same as VB but using the bitvector forbidden array
454  // COLORING_D2_VB_BIT_EF - Add experimental edge-filtering to VB_BIT
455  // COLORING_D2_NB_BIT - Net-based coloring (generally the fastest)
456  if (deterministic) {
457  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
458  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
459  } else if (aggAlgo == "serial") {
460  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
461  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: serial" << std::endl;
462  } else if (aggAlgo == "default") {
463  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_DEFAULT);
464  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: default" << std::endl;
465  } else if (aggAlgo == "vertex based") {
466  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB);
467  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based" << std::endl;
468  } else if (aggAlgo == "vertex based bit set") {
469  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT);
470  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: vertex based bit set" << std::endl;
471  } else if (aggAlgo == "edge filtering") {
472  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT_EF);
473  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: edge filtering" << std::endl;
474  } else if (aggAlgo == "net based bit set") {
475  coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_NB_BIT);
476  if (IsPrint(Statistics1)) GetOStream(Statistics1) << " algorithm: net based bit set" << std::endl;
477  } else {
478  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")
479  }
480 
481  // Create device views for graph rowptrs/colinds
482  typename graph_t::row_map_type aRowptrs = graph->getRowPtrs();
483  typename graph_t::entries_type aColinds = graph->getEntries();
484 
485  // run d2 graph coloring
486  // graph is symmetric so row map/entries and col map/entries are the same
487  {
488  SubFactoryMonitor sfm2(*this, "Algo \"Graph Coloring\": KokkosGraph Call", currentLevel); // CMS HACK
489  KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
490  }
491 
492  // extract the colors and store them in the aggregates
493  aggregates->SetGraphColors(coloringHandle->get_vertex_colors());
494  aggregates->SetGraphNumColors(static_cast<LO>(coloringHandle->get_num_colors()));
495 
496  // clean up coloring handle
497  kh.destroy_distance2_graph_coloring_handle();
498 }
499 
500 } // namespace MueLu
501 
502 #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)
GlobalOrdinal GO
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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
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:99
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:76
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.