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");
79 #undef SET_VALID_ENTRY
83 validParamList->
set<
RCP<const FactoryBase>>(
"DofsPerNode", null,
"Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
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.");
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).");
96 return validParamList;
99 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
101 Input(currentLevel,
"Graph");
102 Input(currentLevel,
"DofsPerNode");
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") {
119 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true) {
126 "nodeOnInterface was not provided by the user on level0!");
129 Input(currentLevel,
"nodeOnInterface");
134 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
139 bDefinitionPhase_ =
false;
141 if (pL.
get<
int>(
"aggregation: max agg size") == -1)
142 pL.
set(
"aggregation: max agg size", INT_MAX);
157 std::string mapOnePtName = pL.
get<std::string>(
"OnePt aggregate map name");
159 if (mapOnePtName.length()) {
160 std::string mapOnePtFactName = pL.
get<std::string>(
"OnePt aggregate map factory");
161 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
165 OnePtMap = currentLevel.
Get<
RCP<Map>>(mapOnePtName, mapOnePtFact.
get());
170 std::string mapInterfaceName = pL.
get<std::string>(
"Interface aggregate map name");
171 RCP<Map> InterfaceMap = Teuchos::null;
180 graph = Get<RCP<LWGraph>>(currentLevel,
"Graph");
186 graph_kokkos = Get<RCP<LWGraph_kokkos>>(currentLevel,
"Graph");
188 comm = graph_kokkos->
GetComm();
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");
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");
204 AggStatHostType aggStatHost;
208 aggStatHost = AggStatHostType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
209 Kokkos::deep_copy(aggStatHost,
READY);
211 aggStat = AggStatType(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
212 Kokkos::deep_copy(aggStat,
READY);
216 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true) {
218 for (
LO i = 0; i < numRows; i++) {
219 if (nodeOnInterface[i])
228 Kokkos::parallel_for(
229 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
230 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph::execution_space>(0, numRows),
232 if (dirichletBoundaryMap(nodeIdx) ==
true) {
238 Kokkos::parallel_for(
239 "MueLu - UncoupledAggregation: tagging boundary nodes in aggStat",
240 Kokkos::RangePolicy<LocalOrdinal, typename LWGraph_kokkos::execution_space>(0, numRows),
242 if (dirichletBoundaryMap(nodeIdx) ==
true) {
249 if (OnePtMap != Teuchos::null) {
250 LO nDofsPerNode = Get<LO>(currentLevel,
"DofsPerNode");
254 for (
LO i = 0; i < numRows; i++) {
256 GO grid = (graph->
GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
258 for (
LO kr = 0; kr < nDofsPerNode; kr++)
259 if (OnePtMap->isNodeGlobalElement(grid + kr))
260 aggStatHost(i) =
ONEPT;
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),
272 GO grid = (lclDomainMap.getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
274 for (
LO kr = 0; kr < nDofsPerNode; kr++)
275 if (lclOnePtMap.getLocalElement(grid + kr) != INVALID)
281 LO numNonAggregatedNodes = numRows;
282 std::string aggAlgo = pL.
get<std::string>(
"aggregation: coloring algorithm");
283 if (aggAlgo ==
"mis2 coarsening" || aggAlgo ==
"mis2 aggregation") {
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();
296 typename colinds_t::non_const_type labels;
298 if (aggAlgo ==
"mis2 coarsening") {
300 labels = KokkosGraph::graph_mis2_coarsen<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
301 }
else if (aggAlgo ==
"mis2 aggregation") {
303 labels = KokkosGraph::graph_mis2_aggregate<device_t, rowmap_t, colinds_t>(aRowptrs, aColinds, numAggs);
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) {
314 vertex2AggId(i, 0) = labels(i);
317 numNonAggregatedNodes = 0;
321 DoGraphColoring(currentLevel, aggAlgo, pL.
get<
bool>(
"aggregation: deterministic"), graph_kokkos, aggregates);
327 GO numGlobalRows = 0;
328 GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
331 for (
size_t a = 0; a < algos_.size(); a++) {
332 std::string phase = algos_[a]->description();
335 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
337 algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStatHost, numNonAggregatedNodes);
339 algos_[a]->BuildAggregates(pL, *graph_kokkos, *aggregates, aggStat, numNonAggregatedNodes);
340 algos_[a]->SetProcRankVerbose(oldRank);
343 GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
345 MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
348 double aggPercent = 100 * as<double>(numGlobalAggregated) / as<double>(numGlobalRows);
349 if (aggPercent > 99.99 && aggPercent < 100.00) {
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;
371 Set(currentLevel,
"Aggregates", aggregates);
374 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
377 const std::string& aggAlgo,
378 const bool deterministic,
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>;
398 kh.create_distance2_graph_coloring_handle();
401 auto coloringHandle = kh.get_distance2_graph_coloring_handle();
414 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
416 }
else if (aggAlgo ==
"serial") {
417 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_SERIAL);
419 }
else if (aggAlgo ==
"default") {
420 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_DEFAULT);
422 }
else if (aggAlgo ==
"vertex based") {
423 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB);
425 }
else if (aggAlgo ==
"vertex based bit set") {
426 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT);
428 }
else if (aggAlgo ==
"edge filtering") {
429 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_VB_BIT_EF);
431 }
else if (aggAlgo ==
"net based bit set") {
432 coloringHandle->set_algorithm(KokkosGraph::COLORING_D2_NB_BIT);
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")
439 typename graph_t::row_map_type aRowptrs = graph->
getRowPtrs();
440 typename graph_t::entries_type aColinds = graph->
getEntries();
445 SubFactoryMonitor sfm2(*
this,
"Algo \"Graph Coloring\": KokkosGraph Call", currentLevel);
446 KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
451 aggregates->
SetGraphNumColors(static_cast<LO>(coloringHandle->get_num_colors()));
454 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)
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...
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.