46 #ifndef MUELU_AGGREGATIONPHASE3ALGORITHM_DEF_HPP_
47 #define MUELU_AGGREGATIONPHASE3ALGORITHM_DEF_HPP_
49 #include <Teuchos_Comm.hpp>
50 #include <Teuchos_CommHelpers.hpp>
56 #include "MueLu_Aggregates.hpp"
58 #include "MueLu_LWGraph.hpp"
65 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
67 Monitor m(*
this,
"BuildAggregatesNonKokkos");
69 bool makeNonAdjAggs =
false;
70 bool error_on_isolated =
false;
71 if (params.
isParameter(
"aggregation: error on nodes with no on-rank neighbors"))
72 error_on_isolated = params.
get<
bool>(
"aggregation: error on nodes with no on-rank neighbors");
73 if (params.
isParameter(
"aggregation: phase3 avoid singletons"))
74 makeNonAdjAggs = params.
get<
bool>(
"aggregation: phase3 avoid singletons");
76 size_t numSingletons = 0;
79 const int myRank = graph.
GetComm()->getRank();
86 for (
LO i = 0; i < numRows; i++) {
94 bool isNewAggregate =
false;
95 bool failedToAggregate =
true;
96 for (
int j = 0; j < neighOfINode.length; j++) {
97 LO neigh = neighOfINode(j);
100 isNewAggregate =
true;
103 vertex2AggId[neigh] = numLocalAggregates;
104 procWinner[neigh] = myRank;
106 numNonAggregatedNodes--;
110 if (isNewAggregate) {
113 procWinner[i] = myRank;
114 numNonAggregatedNodes--;
116 vertex2AggId[i] = numLocalAggregates++;
118 failedToAggregate =
false;
125 for (; j < neighOfINode.length; j++) {
126 LO neigh = neighOfINode(j);
133 if (j < neighOfINode.length) {
135 vertex2AggId[i] = vertex2AggId[neighOfINode(j)];
136 numNonAggregatedNodes--;
137 failedToAggregate =
false;
141 if (failedToAggregate && makeNonAdjAggs) {
150 for (
LO ii = 0; ii < numRows; ii++) {
151 if ((ii != i) && (aggStat[ii] !=
IGNORED)) {
152 failedToAggregate =
false;
154 procWinner[i] = myRank;
157 vertex2AggId[i] = vertex2AggId[ii];
159 vertex2AggId[i] = numLocalAggregates;
160 vertex2AggId[ii] = numLocalAggregates;
162 procWinner[ii] = myRank;
163 numNonAggregatedNodes--;
165 numLocalAggregates++;
167 numNonAggregatedNodes--;
172 if (failedToAggregate) {
173 if (error_on_isolated) {
175 std::ostringstream oss;
176 oss <<
"MueLu::AggregationPhase3Algorithm::BuildAggregatesNonKokkos: MueLu has detected a non-Dirichlet node that has no on-rank neighbors and is terminating (by user request). " << std::endl;
177 oss <<
"If this error is being generated at level 0, this is due to an initial partitioning problem in your matrix." << std::endl;
178 oss <<
"If this error is being generated at any other level, try turning on repartitioning, which may fix this problem." << std::endl;
186 vertex2AggId[i] = numLocalAggregates++;
187 numNonAggregatedNodes--;
193 procWinner[i] = myRank;
197 if (numSingletons > 0)
198 this->GetOStream(
Runtime0) <<
" WARNING Rank " << myRank <<
" singletons :" << numSingletons <<
" (phase)" << std::endl;
206 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
212 LO& numNonAggregatedNodes)
const {
214 if (params.
get<
bool>(
"aggregation: deterministic")) {
215 Monitor m(*
this,
"BuildAggregatesDeterministic");
216 BuildAggregatesRandom(params, graph, aggregates, aggStat, numNonAggregatedNodes);
218 Monitor m(*
this,
"BuildAggregatesRandom");
219 BuildAggregatesRandom(params, graph, aggregates, aggStat, numNonAggregatedNodes);
225 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
231 LO& numNonAggregatedNodes)
const {
235 bool error_on_isolated = params.
get<
bool>(
"aggregation: error on nodes with no on-rank neighbors");
236 bool makeNonAdjAggs = params.
get<
bool>(
"aggregation: phase3 avoid singletons");
239 const int myRank = graph.
GetComm()->getRank();
241 auto vertex2AggId = aggregates.
GetVertex2AggId()->getDeviceLocalView(Xpetra::Access::ReadWrite);
242 auto procWinner = aggregates.
GetProcWinner()->getDeviceLocalView(Xpetra::Access::ReadWrite);
246 auto lclLWGraph = graph;
248 Kokkos::View<LO, device_type> numAggregates(
"numAggregates");
251 Kokkos::View<unsigned*, device_type> aggStatOld(Kokkos::ViewAllocateWithoutInitializing(
"Initial aggregation status"), aggStat.extent(0));
252 Kokkos::deep_copy(aggStatOld, aggStat);
253 Kokkos::View<LO, device_type> numNonAggregated(
"numNonAggregated");
254 Kokkos::deep_copy(numNonAggregated, numNonAggregatedNodes);
255 for (
int color = 1; color < numColors + 1; ++color) {
256 Kokkos::parallel_for(
257 "Aggregation Phase 3: aggregates clean-up",
258 Kokkos::RangePolicy<execution_space>(0, numRows),
259 KOKKOS_LAMBDA(
const LO nodeIdx) {
261 if ((colors(nodeIdx) != color) ||
263 (aggStatOld(nodeIdx) ==
IGNORED)) {
268 auto neighbors = lclLWGraph.getNeighborVertices(nodeIdx);
273 bool isNewAggregate =
false;
274 for (
int neigh = 0; neigh < neighbors.length; ++neigh) {
275 neighIdx = neighbors(neigh);
277 if ((neighIdx != nodeIdx) &&
278 lclLWGraph.isLocalNeighborVertex(neighIdx) &&
279 (aggStatOld(neighIdx) ==
READY)) {
280 isNewAggregate =
true;
286 if (isNewAggregate) {
289 const LO aggId = Kokkos::atomic_fetch_add(&numAggregates(), 1);
291 procWinner(nodeIdx, 0) = myRank;
292 vertex2AggId(nodeIdx, 0) = aggId;
294 Kokkos::atomic_decrement(&numNonAggregated());
295 for (
int neigh = 0; neigh < neighbors.length; ++neigh) {
296 neighIdx = neighbors(neigh);
297 if ((neighIdx != nodeIdx) &&
298 lclLWGraph.isLocalNeighborVertex(neighIdx) &&
299 (aggStatOld(neighIdx) ==
READY)) {
301 procWinner(neighIdx, 0) = myRank;
302 vertex2AggId(neighIdx, 0) = aggId;
303 Kokkos::atomic_decrement(&numNonAggregated());
311 for (
int neigh = 0; neigh < neighbors.length; ++neigh) {
312 neighIdx = neighbors(neigh);
313 if (lclLWGraph.isLocalNeighborVertex(neighIdx) &&
316 procWinner(nodeIdx, 0) = myRank;
317 vertex2AggId(nodeIdx, 0) = vertex2AggId(neighIdx, 0);
318 Kokkos::atomic_decrement(&numNonAggregated());
325 if (makeNonAdjAggs) {
326 for (
LO otherNodeIdx = 0; otherNodeIdx < numRows; ++otherNodeIdx) {
327 if ((otherNodeIdx != nodeIdx) &&
330 procWinner(nodeIdx, 0) = myRank;
331 vertex2AggId(nodeIdx, 0) = vertex2AggId(otherNodeIdx, 0);
332 Kokkos::atomic_decrement(&numNonAggregated());
340 if (!error_on_isolated) {
341 const LO aggId = Kokkos::atomic_fetch_add(&numAggregates(), 1);
343 procWinner(nodeIdx, 0) = myRank;
344 vertex2AggId(nodeIdx, 0) = aggId;
345 Kokkos::atomic_decrement(&numNonAggregated());
351 Kokkos::deep_copy(aggStatOld, aggStat);
354 auto numNonAggregated_h = Kokkos::create_mirror_view(numNonAggregated);
355 Kokkos::deep_copy(numNonAggregated_h, numNonAggregated);
356 numNonAggregatedNodes = numNonAggregated_h();
357 if ((error_on_isolated) && (numNonAggregatedNodes > 0)) {
359 std::ostringstream oss;
360 oss <<
"MueLu::AggregationPhase3Algorithm::BuildAggregates: MueLu has detected a non-Dirichlet node that has no on-rank neighbors and is terminating (by user request). " << std::endl;
361 oss <<
"If this error is being generated at level 0, this is due to an initial partitioning problem in your matrix." << std::endl;
362 oss <<
"If this error is being generated at any other level, try turning on repartitioning, which may fix this problem." << std::endl;
367 auto numAggregates_h = Kokkos::create_mirror_view(numAggregates);
368 Kokkos::deep_copy(numAggregates_h, numAggregates);
Kokkos::View< unsigned *, typename LWGraphHostType::device_type > AggStatHostType
Lightweight MueLu representation of a compressed row storage graph.
const RCP< LOVector > & GetProcWinner() const
Returns constant vector that maps local node IDs to owning processor IDs.
Container class for aggregation information.
KOKKOS_INLINE_FUNCTION LO GetNumAggregates() const
void BuildAggregates(const ParameterList ¶ms, const LWGraph_kokkos &graph, Aggregates &aggregates, typename AggregationAlgorithmBase< LocalOrdinal, GlobalOrdinal, Node >::AggStatType &aggStat, LO &numNonAggregatedNodes) const
T & get(const std::string &name, T def_value)
One-liner description of what is happening.
void BuildAggregatesNonKokkos(const ParameterList ¶ms, const LWGraph &graph, Aggregates &aggregates, typename AggregationAlgorithmBase< LocalOrdinal, GlobalOrdinal, Node >::AggStatHostType &aggStat, LO &numNonAggregatedNodes) const
Local aggregation.
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
void SetIsRoot(LO i, bool value=true)
Set root node information.
typename device_type::execution_space execution_space
bool isParameter(const std::string &name) const
LO GetGraphNumColors()
Get the number of colors needed by the distance 2 coloring.
colors_view_type & GetGraphColors()
Get a distance 2 coloring of the underlying graph. The coloring is computed and set during Phase1 of ...
KOKKOS_INLINE_FUNCTION bool isLocalNeighborVertex(LO i) const
Return true if vertex with local id 'v' is on current process.
const RCP< LOMultiVector > & GetVertex2AggId() const
Returns constant vector that maps local node IDs to local aggregates IDs.
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
Timer to be used in non-factories.
Lightweight MueLu representation of a compressed row storage graph.
Exception throws to report errors in the internal logical of the program.
void BuildAggregatesRandom(const ParameterList ¶ms, const LWGraph_kokkos &graph, Aggregates &aggregates, typename AggregationAlgorithmBase< LocalOrdinal, GlobalOrdinal, Node >::AggStatType &aggStat, LO &numNonAggregatedNodes) const
typename std::conditional< OnHost, Kokkos::Device< Kokkos::Serial, Kokkos::HostSpace >, typename Node::device_type >::type device_type
const RCP< const Teuchos::Comm< int > > GetComm() const
Kokkos::View< unsigned *, typename LWGraphType::device_type > AggStatType
void SetNumAggregates(LO nAggregates)
Set number of local aggregates on current processor.