46 #ifndef MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
47 #define MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
51 #include <Xpetra_Map.hpp>
53 #include <Xpetra_MultiVectorFactory.hpp>
58 #include "MueLu_InterfaceAggregationAlgorithm.hpp"
59 #include "MueLu_OnePtAggregationAlgorithm.hpp"
60 #include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
62 #include "MueLu_AggregationPhase1Algorithm.hpp"
63 #include "MueLu_AggregationPhase2aAlgorithm.hpp"
64 #include "MueLu_AggregationPhase2bAlgorithm.hpp"
65 #include "MueLu_AggregationPhase3Algorithm.hpp"
68 #include "MueLu_LWGraph.hpp"
69 #include "MueLu_Aggregates.hpp"
73 #include "KokkosGraph_Distance2ColorHandle.hpp"
74 #include "KokkosGraph_Distance2Color.hpp"
75 #include "KokkosGraph_MIS2.hpp"
79 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
81 : bDefinitionPhase_(true) {}
83 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
90 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
109 SET_VALID_ENTRY(
"aggregation: error on nodes with no on-rank neighbors");
113 #undef SET_VALID_ENTRY
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\'");
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.");
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).");
131 return validParamList;
134 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
136 Input(currentLevel,
"Graph");
137 Input(currentLevel,
"DofsPerNode");
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") {
154 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true) {
161 "nodeOnInterface was not provided by the user on level0!");
164 Input(currentLevel,
"nodeOnInterface");
168 if (pL.
get<
bool>(
"aggregation: compute aggregate qualities")) {
169 Input(currentLevel,
"AggregateQualities");
173 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
178 bDefinitionPhase_ =
false;
180 if (pL.
get<
int>(
"aggregation: max agg size") == -1)
181 pL.
set(
"aggregation: max agg size", INT_MAX);
196 std::string mapOnePtName = pL.
get<std::string>(
"OnePt aggregate map name");
198 if (mapOnePtName.length()) {
199 std::string mapOnePtFactName = pL.
get<std::string>(
"OnePt aggregate map factory");
200 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
204 OnePtMap = currentLevel.
Get<
RCP<Map>>(mapOnePtName, mapOnePtFact.
get());
209 std::string mapInterfaceName = pL.
get<std::string>(
"Interface aggregate map name");
210 RCP<Map> InterfaceMap = Teuchos::null;
219 graph = Get<RCP<LWGraph>>(currentLevel,
"Graph");
225 graph_kokkos = Get<RCP<LWGraph_kokkos>>(currentLevel,
"Graph");
227 comm = graph_kokkos->
GetComm();
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");
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");
243 AggStatHostType aggStatHost;
247 aggStatHost = AggStatHostType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
248 Kokkos::deep_copy(aggStatHost,
READY);
250 aggStat = AggStatType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
251 Kokkos::deep_copy(aggStat,
READY);
255 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true) {
257 for (
LO i = 0; i < numRows; i++) {
258 if (nodeOnInterface[i])
267 Kokkos::parallel_for(
268 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
269 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph::execution_space>(0, numRows),
271 if (dirichletBoundaryMap(nodeIdx) ==
true) {
277 Kokkos::parallel_for(
278 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
279 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
281 if (dirichletBoundaryMap(nodeIdx) ==
true) {
288 if (OnePtMap != Teuchos::null) {
289 LO nDofsPerNode = Get<LO>(currentLevel,
"DofsPerNode");
293 for (
LO i = 0; i < numRows; i++) {
295 GO grid = (graph->
GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
297 for (
LO kr = 0; kr < nDofsPerNode; kr++)
298 if (OnePtMap->isNodeGlobalElement(grid + kr))
299 aggStatHost(i) =
ONEPT;
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),
311 GO grid = (lclDomainMap.getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
313 for (
LO kr = 0; kr < nDofsPerNode; kr++)
314 if (lclOnePtMap.getLocalElement(grid + kr) != INVALID)
320 LO numNonAggregatedNodes = numRows;
321 std::string aggAlgo = pL.
get<std::string>(
"aggregation: coloring algorithm");
322 if (aggAlgo ==
"mis2 coarsening" || aggAlgo ==
"mis2 aggregation") {
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();
335 typename colinds_t::non_const_type labels;
337 if (aggAlgo ==
"mis2 coarsening") {
339 labels = KokkosGraph::graph_mis2_coarsen<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
340 }
else if (aggAlgo ==
"mis2 aggregation") {
342 labels = KokkosGraph::graph_mis2_aggregate<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
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) {
353 vertex2AggId(i, 0) = labels(i);
356 numNonAggregatedNodes = 0;
360 DoGraphColoring(currentLevel, aggAlgo, pL.
get<
bool>(
"aggregation: deterministic"), graph_kokkos, aggregates);
366 GO numGlobalRows = 0;
367 GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
370 for (
size_t a = 0; a < algos_.size(); a++) {
371 std::string phase = algos_[a]->description();
374 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
376 algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStatHost, numNonAggregatedNodes);
378 algos_[a]->BuildAggregates(pL, *graph_kokkos, *aggregates, aggStat, numNonAggregatedNodes);
379 algos_[a]->SetProcRankVerbose(oldRank);
382 GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
384 MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
387 double aggPercent = 100 * as<double>(numGlobalAggregated) / as<double>(numGlobalRows);
388 if (aggPercent > 99.99 && aggPercent < 100.00) {
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;
410 Set(currentLevel,
"Aggregates", aggregates);
412 if (pL.
get<
bool>(
"aggregation: compute aggregate qualities")) {
417 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
420 const std::string& aggAlgo,
421 const bool deterministic,
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>;
441 kh.create_distance2_graph_coloring_handle();
444 auto coloringHandle = kh.get_distance2_graph_coloring_handle();
457 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
459 }
else if (aggAlgo ==
"serial") {
460 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
462 }
else if (aggAlgo ==
"default") {
463 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_DEFAULT);
465 }
else if (aggAlgo ==
"vertex based") {
466 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB);
468 }
else if (aggAlgo ==
"vertex based bit set") {
469 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT);
471 }
else if (aggAlgo ==
"edge filtering") {
472 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT_EF);
474 }
else if (aggAlgo ==
"net based bit set") {
475 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_NB_BIT);
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")
482 typename graph_t::row_map_type aRowptrs = graph->
getRowPtrs();
483 typename graph_t::entries_type aColinds = graph->
getEntries();
488 SubFactoryMonitor sfm2(*
this,
"Algo \"Graph Coloring\": KokkosGraph Call", currentLevel);
489 KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
494 aggregates->
SetGraphNumColors(static_cast<LO>(coloringHandle->get_num_colors()));
497 kh.destroy_distance2_graph_coloring_handle();
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->Get< RCP<Matrix> >("A", factory) if factory == NULL => use default factory.
void DoGraphColoring(Level ¤tLevel, 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)
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)
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 ¤tLevel) 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.
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)
UncoupledAggregationFactory()
Constructor.
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 ¤tLevel) 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.
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's value has been saved.
void SetNumAggregates(LO nAggregates)
Set number of local aggregates on current processor.