void OnePtAggregationAlgorithm_kokkos<LocalOrdinal, GlobalOrdinal, Node>::BuildAggregates(Teuchos::ParameterList const & params, LWGraph_kokkos const & graph, Aggregates_kokkos & aggregates, std::vector<unsigned>& aggStat, LO& numNonAggregatedNodes) const { Monitor m(*this, "BuildAggregates"); const LocalOrdinal nRows = graph.GetNodeNumVertices(); const int myRank = graph.GetComm()->getRank(); // vertex ids for output Teuchos::ArrayRCP<LocalOrdinal> vertex2AggId = aggregates.GetVertex2AggId()->getDataNonConst(0); Teuchos::ArrayRCP<LocalOrdinal> procWinner = aggregates.GetProcWinner()->getDataNonConst(0); // some internal variables LocalOrdinal nLocalAggregates = aggregates.GetNumAggregates(); // number of local aggregates on current proc LocalOrdinal iNode1 = 0; // current node // main loop over all local rows of graph(A) while (iNode1 < nRows) { if (aggStat[iNode1] == ONEPT) { aggregates.SetIsRoot(iNode1); // mark iNode1 as root node for new aggregate 'ag' std::vector<int> aggList; aggList.push_back(iNode1); int aggIndex = nLocalAggregates++; // finalize aggregate for (size_t k = 0; k < aggList.size(); k++) { aggStat[aggList[k]] = IGNORED; vertex2AggId[aggList[k]] = aggIndex; procWinner[aggList[k]] = myRank; } numNonAggregatedNodes -= aggList.size(); } iNode1++; } // end while // update aggregate object aggregates.SetNumAggregates(nLocalAggregates); }
void AggregationPhase1Algorithm_kokkos<LocalOrdinal, GlobalOrdinal, Node>:: BuildAggregates(const ParameterList& params, const LWGraph_kokkos& graph, Aggregates_kokkos& aggregates, std::vector<unsigned>& aggStat, LO& numNonAggregatedNodes) const { Monitor m(*this, "BuildAggregates"); std::string ordering = params.get<std::string>("aggregation: ordering"); int maxNeighAlreadySelected = params.get<int> ("aggregation: max selected neighbors"); int minNodesPerAggregate = params.get<int> ("aggregation: min agg size"); int maxNodesPerAggregate = params.get<int> ("aggregation: max agg size"); TEUCHOS_TEST_FOR_EXCEPTION(maxNodesPerAggregate < minNodesPerAggregate, Exceptions::RuntimeError, "MueLu::UncoupledAggregationAlgorithm::BuildAggregates: minNodesPerAggregate must be smaller or equal to MaxNodePerAggregate!"); const LO numRows = graph.GetNodeNumVertices(); const int myRank = graph.GetComm()->getRank(); ArrayRCP<LO> vertex2AggId = aggregates.GetVertex2AggId()->getDataNonConst(0); ArrayRCP<LO> procWinner = aggregates.GetProcWinner() ->getDataNonConst(0); LO numLocalAggregates = aggregates.GetNumAggregates(); ArrayRCP<LO> randomVector; if (ordering == "random") { randomVector = arcp<LO>(numRows); for (LO i = 0; i < numRows; i++) randomVector[i] = i; RandomReorder(randomVector); } int aggIndex = -1; size_t aggSize = 0; std::vector<int> aggList(graph.getNodeMaxNumRowEntries()); std::queue<LO> graphOrderQueue; // Main loop over all local rows of graph(A) for (LO i = 0; i < numRows; i++) { // Step 1: pick the next node to aggregate LO rootCandidate = 0; if (ordering == "natural") rootCandidate = i; else if (ordering == "random") rootCandidate = randomVector[i]; else if (ordering == "graph") { if (graphOrderQueue.size() == 0) { // Current queue is empty for "graph" ordering, populate with one READY node for (LO jnode = 0; jnode < numRows; jnode++) if (aggStat[jnode] == READY) { graphOrderQueue.push(jnode); break; } } if (graphOrderQueue.size() == 0) { // There are no more ready nodes, end the phase break; } rootCandidate = graphOrderQueue.front(); // take next node from graph ordering queue graphOrderQueue.pop(); // delete this node in list } if (aggStat[rootCandidate] != READY) continue; // Step 2: build tentative aggregate aggSize = 0; aggList[aggSize++] = rootCandidate; // TODO replace me //ArrayView<const LO> neighOfINode = graph.getNeighborVertices(rootCandidate); ArrayView<const LO> neighOfINode; // If the number of neighbors is less than the minimum number of nodes // per aggregate, we know this is not going to be a valid root, and we // may skip it, but only for "natural" and "random" (for "graph" we still // need to fetch the list of local neighbors to continue) if ((ordering == "natural" || ordering == "random") && neighOfINode.size() < minNodesPerAggregate) { continue; } LO numAggregatedNeighbours = 0; for (int j = 0; j < neighOfINode.size(); j++) { LO neigh = neighOfINode[j]; if (neigh != rootCandidate && graph.isLocalNeighborVertex(neigh)) { if (aggStat[neigh] == READY || aggStat[neigh] == NOTSEL) { // If aggregate size does not exceed max size, add node to the // tentative aggregate // NOTE: We do not exit the loop over all neighbours since we have // still to count all aggregated neighbour nodes for the // aggregation criteria // NOTE: We check here for the maximum aggregation size. If we // would do it below with all the other check too big aggregates // would not be accepted at all. if (aggSize < as<size_t>(maxNodesPerAggregate)) aggList[aggSize++] = neigh; } else { numAggregatedNeighbours++; } } } // Step 3: check if tentative aggregate is acceptable if ((numAggregatedNeighbours <= maxNeighAlreadySelected) && // too many connections to other aggregates (aggSize >= as<size_t>(minNodesPerAggregate))) { // too few nodes in the tentative aggregate // Accept new aggregate // rootCandidate becomes the root of the newly formed aggregate aggregates.SetIsRoot(rootCandidate); aggIndex = numLocalAggregates++; for (size_t k = 0; k < aggSize; k++) { aggStat [aggList[k]] = AGGREGATED; vertex2AggId[aggList[k]] = aggIndex; procWinner [aggList[k]] = myRank; } numNonAggregatedNodes -= aggSize; } else { // Aggregate is not accepted aggStat[rootCandidate] = NOTSEL; // Need this for the "graph" ordering below // The original candidate is always aggList[0] aggSize = 1; } if (ordering == "graph") { // Add candidates to the list of nodes // NOTE: the code have slightly different meanings depending on context: // - if aggregate was accepted, we add neighbors of neighbors of the original candidate // - if aggregate was not accepted, we add neighbors of the original candidate for (size_t k = 0; k < aggSize; k++) { // TODO replace this //ArrayView<const LO> neighOfJNode = graph.getNeighborVertices(aggList[k]); ArrayView<const LO> neighOfJNode; for (int j = 0; j < neighOfJNode.size(); j++) { LO neigh = neighOfJNode[j]; if (graph.isLocalNeighborVertex(neigh) && aggStat[neigh] == READY) graphOrderQueue.push(neigh); } } } } // Reset all NOTSEL vertices to READY // This simplifies other algorithms for (LO i = 0; i < numRows; i++) if (aggStat[i] == NOTSEL) aggStat[i] = READY; // update aggregate object aggregates.SetNumAggregates(numLocalAggregates); }