10 #ifndef MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
11 #define MUELU_UNCOUPLEDAGGREGATIONFACTORY_DEF_HPP_
15 #include <Xpetra_Map.hpp>
17 #include <Xpetra_MultiVectorFactory.hpp>
22 #include "MueLu_InterfaceAggregationAlgorithm.hpp"
23 #include "MueLu_OnePtAggregationAlgorithm.hpp"
24 #include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
26 #include "MueLu_AggregationPhase1Algorithm.hpp"
27 #include "MueLu_AggregationPhase2aAlgorithm.hpp"
28 #include "MueLu_AggregationPhase2bAlgorithm.hpp"
29 #include "MueLu_AggregationPhase3Algorithm.hpp"
32 #include "MueLu_LWGraph.hpp"
33 #include "MueLu_Aggregates.hpp"
37 #include "KokkosGraph_Distance2ColorHandle.hpp"
38 #include "KokkosGraph_Distance2Color.hpp"
39 #include "KokkosGraph_MIS2.hpp"
43 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
45 : bDefinitionPhase_(true) {}
47 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
50 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
57 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
76 SET_VALID_ENTRY(
"aggregation: error on nodes with no on-rank neighbors");
81 #undef SET_VALID_ENTRY
85 validParamList->
set<
RCP<const FactoryBase>>(
"DofsPerNode", null,
"Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
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.");
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).");
98 return validParamList;
101 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
103 Input(currentLevel,
"Graph");
104 Input(currentLevel,
"DofsPerNode");
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") {
121 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true) {
128 "nodeOnInterface was not provided by the user on level0!");
131 Input(currentLevel,
"nodeOnInterface");
136 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
141 bDefinitionPhase_ =
false;
143 if (pL.
get<
int>(
"aggregation: max agg size") == -1)
144 pL.
set(
"aggregation: max agg size", INT_MAX);
159 std::string mapOnePtName = pL.
get<std::string>(
"OnePt aggregate map name");
161 if (mapOnePtName.length()) {
162 std::string mapOnePtFactName = pL.
get<std::string>(
"OnePt aggregate map factory");
163 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
167 OnePtMap = currentLevel.
Get<
RCP<Map>>(mapOnePtName, mapOnePtFact.
get());
172 std::string mapInterfaceName = pL.
get<std::string>(
"Interface aggregate map name");
173 RCP<Map> InterfaceMap = Teuchos::null;
181 const std::string aggregationBackend = pL.
get<std::string>(
"aggregation: backend");
193 if ((aggregationBackend ==
"default") || (aggregationBackend ==
"non-Kokkos")) {
194 graph = Get<RCP<LWGraph>>(currentLevel,
"Graph");
200 RCP<LWGraph> tmp_graph = Get<RCP<LWGraph>>(currentLevel,
"Graph");
203 comm = graph_kokkos->GetComm();
204 numRows = graph_kokkos->GetNodeNumVertices();
208 if ((aggregationBackend ==
"default") || (aggregationBackend ==
"Kokkos")) {
209 graph_kokkos = Get<RCP<LWGraph_kokkos>>(currentLevel,
"Graph");
211 comm = graph_kokkos->
GetComm();
218 comm = graph->GetComm();
219 numRows = graph->GetNodeNumVertices();
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");
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");
238 AggStatHostType aggStatHost;
242 aggStatHost = AggStatHostType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
243 Kokkos::deep_copy(aggStatHost,
READY);
245 aggStat = AggStatType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
246 Kokkos::deep_copy(aggStat,
READY);
250 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true) {
252 for (
LO i = 0; i < numRows; i++) {
253 if (nodeOnInterface[i])
262 Kokkos::parallel_for(
263 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
264 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph::execution_space>(0, numRows),
266 if (dirichletBoundaryMap(nodeIdx) ==
true) {
272 Kokkos::parallel_for(
273 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
274 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
276 if (dirichletBoundaryMap(nodeIdx) ==
true) {
283 if (OnePtMap != Teuchos::null) {
284 LO nDofsPerNode = Get<LO>(currentLevel,
"DofsPerNode");
288 for (
LO i = 0; i < numRows; i++) {
290 GO grid = (graph->
GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
292 for (
LO kr = 0; kr < nDofsPerNode; kr++)
293 if (OnePtMap->isNodeGlobalElement(grid + kr))
294 aggStatHost(i) =
ONEPT;
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),
306 GO grid = (lclDomainMap.getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
308 for (
LO kr = 0; kr < nDofsPerNode; kr++)
309 if (lclOnePtMap.getLocalElement(grid + kr) != INVALID)
315 LO numNonAggregatedNodes = numRows;
316 std::string aggAlgo = pL.
get<std::string>(
"aggregation: coloring algorithm");
317 if (aggAlgo ==
"mis2 coarsening" || aggAlgo ==
"mis2 aggregation") {
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();
330 typename colinds_t::non_const_type labels;
332 if (aggAlgo ==
"mis2 coarsening") {
334 labels = KokkosGraph::graph_mis2_coarsen<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
335 }
else if (aggAlgo ==
"mis2 aggregation") {
337 labels = KokkosGraph::graph_mis2_aggregate<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
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) {
348 vertex2AggId(i, 0) = labels(i);
351 numNonAggregatedNodes = 0;
355 DoGraphColoring(currentLevel, aggAlgo, pL.
get<
bool>(
"aggregation: deterministic"), graph_kokkos, aggregates);
361 GO numGlobalRows = 0;
362 GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
365 for (
size_t a = 0; a < algos_.size(); a++) {
366 std::string phase = algos_[a]->description();
369 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
371 algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStatHost, numNonAggregatedNodes);
373 algos_[a]->BuildAggregates(pL, *graph_kokkos, *aggregates, aggStat, numNonAggregatedNodes);
374 algos_[a]->SetProcRankVerbose(oldRank);
377 GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
379 MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
382 double aggPercent = 100 * as<double>(numGlobalAggregated) / as<double>(numGlobalRows);
383 if (aggPercent > 99.99 && aggPercent < 100.00) {
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;
405 Set(currentLevel,
"Aggregates", aggregates);
408 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
411 const std::string& aggAlgo,
412 const bool deterministic,
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>;
432 kh.create_distance2_graph_coloring_handle();
435 auto coloringHandle = kh.get_distance2_graph_coloring_handle();
448 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
450 }
else if (aggAlgo ==
"serial") {
451 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
453 }
else if (aggAlgo ==
"default") {
454 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_DEFAULT);
456 }
else if (aggAlgo ==
"vertex based") {
457 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB);
459 }
else if (aggAlgo ==
"vertex based bit set") {
460 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT);
462 }
else if (aggAlgo ==
"edge filtering") {
463 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT_EF);
465 }
else if (aggAlgo ==
"net based bit set") {
466 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_NB_BIT);
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")
473 typename graph_t::row_map_type aRowptrs = graph->
getRowPtrs();
474 typename graph_t::entries_type aColinds = graph->
getEntries();
479 SubFactoryMonitor sfm2(*
this,
"Algo \"Graph Coloring\": KokkosGraph Call", currentLevel);
480 KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
485 aggregates->
SetGraphNumColors(static_cast<LO>(coloringHandle->get_num_colors()));
488 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...
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->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)
virtual ~UncoupledAggregationFactory()
Destructor.
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)
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 ¤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...
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.
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.