10 #ifndef MUELU_AGGREGATIONPHASE3ALGORITHM_DEF_HPP_
11 #define MUELU_AGGREGATIONPHASE3ALGORITHM_DEF_HPP_
13 #include <Teuchos_Comm.hpp>
14 #include <Teuchos_CommHelpers.hpp>
20 #include "MueLu_Aggregates.hpp"
22 #include "MueLu_LWGraph.hpp"
29 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
31 Monitor m(*
this,
"BuildAggregatesNonKokkos");
33 bool makeNonAdjAggs =
false;
34 bool error_on_isolated =
false;
35 if (params.
isParameter(
"aggregation: error on nodes with no on-rank neighbors"))
36 error_on_isolated = params.
get<
bool>(
"aggregation: error on nodes with no on-rank neighbors");
37 if (params.
isParameter(
"aggregation: phase3 avoid singletons"))
38 makeNonAdjAggs = params.
get<
bool>(
"aggregation: phase3 avoid singletons");
40 size_t numSingletons = 0;
43 const int myRank = graph.
GetComm()->getRank();
50 for (
LO i = 0; i < numRows; i++) {
58 bool isNewAggregate =
false;
59 bool failedToAggregate =
true;
60 for (
int j = 0; j < neighOfINode.length; j++) {
61 LO neigh = neighOfINode(j);
64 isNewAggregate =
true;
67 vertex2AggId[neigh] = numLocalAggregates;
68 procWinner[neigh] = myRank;
70 numNonAggregatedNodes--;
77 procWinner[i] = myRank;
78 numNonAggregatedNodes--;
80 vertex2AggId[i] = numLocalAggregates++;
82 failedToAggregate =
false;
89 for (; j < neighOfINode.length; j++) {
90 LO neigh = neighOfINode(j);
97 if (j < neighOfINode.length) {
99 vertex2AggId[i] = vertex2AggId[neighOfINode(j)];
100 numNonAggregatedNodes--;
101 failedToAggregate =
false;
105 if (failedToAggregate && makeNonAdjAggs) {
114 for (
LO ii = 0; ii < numRows; ii++) {
115 if ((ii != i) && (aggStat[ii] !=
IGNORED)) {
116 failedToAggregate =
false;
118 procWinner[i] = myRank;
121 vertex2AggId[i] = vertex2AggId[ii];
123 vertex2AggId[i] = numLocalAggregates;
124 vertex2AggId[ii] = numLocalAggregates;
126 procWinner[ii] = myRank;
127 numNonAggregatedNodes--;
129 numLocalAggregates++;
131 numNonAggregatedNodes--;
136 if (failedToAggregate) {
137 if (error_on_isolated) {
139 std::ostringstream oss;
140 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;
141 oss <<
"If this error is being generated at level 0, this is due to an initial partitioning problem in your matrix." << std::endl;
142 oss <<
"If this error is being generated at any other level, try turning on repartitioning, which may fix this problem." << std::endl;
150 vertex2AggId[i] = numLocalAggregates++;
151 numNonAggregatedNodes--;
157 procWinner[i] = myRank;
161 if (numSingletons > 0)
162 this->GetOStream(
Runtime0) <<
" WARNING Rank " << myRank <<
" singletons :" << numSingletons <<
" (phase)" << std::endl;
170 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
176 LO& numNonAggregatedNodes)
const {
178 if (params.
get<
bool>(
"aggregation: deterministic")) {
179 Monitor m(*
this,
"BuildAggregatesDeterministic");
180 BuildAggregatesRandom(params, graph, aggregates, aggStat, numNonAggregatedNodes);
182 Monitor m(*
this,
"BuildAggregatesRandom");
183 BuildAggregatesRandom(params, graph, aggregates, aggStat, numNonAggregatedNodes);
189 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
195 LO& numNonAggregatedNodes)
const {
199 bool error_on_isolated = params.
get<
bool>(
"aggregation: error on nodes with no on-rank neighbors");
200 bool makeNonAdjAggs = params.
get<
bool>(
"aggregation: phase3 avoid singletons");
203 const int myRank = graph.
GetComm()->getRank();
205 auto vertex2AggId = aggregates.
GetVertex2AggId()->getDeviceLocalView(Xpetra::Access::ReadWrite);
206 auto procWinner = aggregates.
GetProcWinner()->getDeviceLocalView(Xpetra::Access::ReadWrite);
210 auto lclLWGraph = graph;
212 Kokkos::View<LO, device_type> numAggregates(
"numAggregates");
215 Kokkos::View<unsigned*, device_type> aggStatOld(Kokkos::ViewAllocateWithoutInitializing(
"Initial aggregation status"), aggStat.extent(0));
216 Kokkos::deep_copy(aggStatOld, aggStat);
217 Kokkos::View<LO, device_type> numNonAggregated(
"numNonAggregated");
218 Kokkos::deep_copy(numNonAggregated, numNonAggregatedNodes);
219 for (
int color = 1; color < numColors + 1; ++color) {
220 Kokkos::parallel_for(
221 "Aggregation Phase 3: aggregates clean-up",
222 Kokkos::RangePolicy<execution_space>(0, numRows),
223 KOKKOS_LAMBDA(
const LO nodeIdx) {
225 if ((colors(nodeIdx) != color) ||
227 (aggStatOld(nodeIdx) ==
IGNORED)) {
232 auto neighbors = lclLWGraph.getNeighborVertices(nodeIdx);
237 bool isNewAggregate =
false;
238 for (
int neigh = 0; neigh < neighbors.length; ++neigh) {
239 neighIdx = neighbors(neigh);
241 if ((neighIdx != nodeIdx) &&
242 lclLWGraph.isLocalNeighborVertex(neighIdx) &&
243 (aggStatOld(neighIdx) ==
READY)) {
244 isNewAggregate =
true;
250 if (isNewAggregate) {
253 const LO aggId = Kokkos::atomic_fetch_add(&numAggregates(), 1);
255 procWinner(nodeIdx, 0) = myRank;
256 vertex2AggId(nodeIdx, 0) = aggId;
258 Kokkos::atomic_dec(&numNonAggregated());
259 for (
int neigh = 0; neigh < neighbors.length; ++neigh) {
260 neighIdx = neighbors(neigh);
261 if ((neighIdx != nodeIdx) &&
262 lclLWGraph.isLocalNeighborVertex(neighIdx) &&
263 (aggStatOld(neighIdx) ==
READY)) {
265 procWinner(neighIdx, 0) = myRank;
266 vertex2AggId(neighIdx, 0) = aggId;
267 Kokkos::atomic_dec(&numNonAggregated());
275 for (
int neigh = 0; neigh < neighbors.length; ++neigh) {
276 neighIdx = neighbors(neigh);
277 if (lclLWGraph.isLocalNeighborVertex(neighIdx) &&
280 procWinner(nodeIdx, 0) = myRank;
281 vertex2AggId(nodeIdx, 0) = vertex2AggId(neighIdx, 0);
282 Kokkos::atomic_dec(&numNonAggregated());
289 if (makeNonAdjAggs) {
290 for (
LO otherNodeIdx = 0; otherNodeIdx < numRows; ++otherNodeIdx) {
291 if ((otherNodeIdx != nodeIdx) &&
294 procWinner(nodeIdx, 0) = myRank;
295 vertex2AggId(nodeIdx, 0) = vertex2AggId(otherNodeIdx, 0);
296 Kokkos::atomic_dec(&numNonAggregated());
304 if (!error_on_isolated) {
305 const LO aggId = Kokkos::atomic_fetch_add(&numAggregates(), 1);
307 procWinner(nodeIdx, 0) = myRank;
308 vertex2AggId(nodeIdx, 0) = aggId;
309 Kokkos::atomic_dec(&numNonAggregated());
315 Kokkos::deep_copy(aggStatOld, aggStat);
318 auto numNonAggregated_h = Kokkos::create_mirror_view(numNonAggregated);
319 Kokkos::deep_copy(numNonAggregated_h, numNonAggregated);
320 numNonAggregatedNodes = numNonAggregated_h();
321 if ((error_on_isolated) && (numNonAggregatedNodes > 0)) {
323 std::ostringstream oss;
324 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;
325 oss <<
"If this error is being generated at level 0, this is due to an initial partitioning problem in your matrix." << std::endl;
326 oss <<
"If this error is being generated at any other level, try turning on repartitioning, which may fix this problem." << std::endl;
331 auto numAggregates_h = Kokkos::create_mirror_view(numAggregates);
332 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.