int LeftoverAggregationAlgorithm<LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::RemoveSmallAggs(Aggregates& aggregates, int min_size, RCP<Xpetra::Vector<double,LO,GO,NO> > & distWeights, const MueLu::CoupledAggregationCommHelper<LO,GO,NO,LMO> & myWidget) const { int myPid = aggregates.GetMap()->getComm()->getRank(); LO nAggregates = aggregates.GetNumAggregates(); ArrayRCP<LO> procWinner = aggregates.GetProcWinner()->getDataNonConst(0); ArrayRCP<LO> vertex2AggId = aggregates.GetVertex2AggId()->getDataNonConst(0); LO size = procWinner.size(); //ArrayRCP<int> AggInfo = Teuchos::arcp<int>(nAggregates+1); //aggregates.ComputeAggSizes(AggInfo); ArrayRCP<LO> AggInfo = aggregates.ComputeAggregateSizes(); ArrayRCP<double> weights = distWeights->getDataNonConst(0); // Make a list of all aggregates indicating New AggId // Use AggInfo array for this. LO NewNAggs = 0; for (LO i = 0; i < nAggregates; i++) { if ( AggInfo[i] < min_size) { AggInfo[i] = MUELU_UNAGGREGATED; } else AggInfo[i] = NewNAggs++; } for (LO k = 0; k < size; k++ ) { if (procWinner[k] == myPid) { if (vertex2AggId[k] != MUELU_UNAGGREGATED) { vertex2AggId[k] = AggInfo[vertex2AggId[k]]; weights[k] = 1.; } if (vertex2AggId[k] == MUELU_UNAGGREGATED) aggregates.SetIsRoot(k,false); } } nAggregates = NewNAggs; //TODO JJH We want to skip this call myWidget.ArbitrateAndCommunicate(*distWeights, aggregates, true); // All tentatively assigned vertices are now definitive // procWinner is not set correctly for aggregates which have // been eliminated for (LO i = 0; i < size; i++) { if (vertex2AggId[i] == MUELU_UNAGGREGATED) procWinner[i] = MUELU_UNASSIGNED; } aggregates.SetNumAggregates(nAggregates); return 0; //TODO } //RemoveSmallAggs
void MaxLinkAggregationAlgorithm<LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>:: BuildAggregates(const ParameterList& params, const GraphBase& graph, Aggregates& aggregates, std::vector<unsigned>& aggStat, LO& numNonAggregatedNodes) const { Monitor m(*this, "BuildAggregates"); LO MaxNodesPerAggregate = params.get<LO>("MaxNodesPerAggregate"); // vertex ids for output ArrayRCP<LO> vertex2AggId = aggregates.GetVertex2AggId()->getDataNonConst(0); ArrayRCP<LO> procWinner = aggregates.GetProcWinner() ->getDataNonConst(0); ArrayRCP<LO> aggSizes = aggregates.ComputeAggregateSizes(); // contains number of nodes in aggregate with given aggId const LO nRows = graph.GetNodeNumVertices(); const int myRank = graph.GetComm()->getRank(); size_t aggSize = 0; std::vector<int> aggList(graph.getNodeMaxNumRowEntries()); //bool recomputeAggregateSizes=false; // variable not used TODO remove it for (LO iNode = 0; iNode < nRows; iNode++) { if (aggStat[iNode] == NodeStats::AGGREGATED) continue; ArrayView<const LocalOrdinal> neighOfINode = graph.getNeighborVertices(iNode); aggSize = 0; for (LO j = 0; j < neighOfINode.size(); j++) { LO neigh = neighOfINode[j]; // NOTE: we don't need the check (neigh != iNode), as we work only // if aggStat[neigh] == AGGREGATED, which we know is different from aggStat[iNode] if (graph.isLocalNeighborVertex(neigh) && aggStat[neigh] == NodeStats::AGGREGATED) aggList[aggSize++] = vertex2AggId[neigh]; } // Ideally, we would have a _fast_ hash table here. // But for the absense of that, sorting works just fine. std::sort(aggList.begin(), aggList.begin() + aggSize); // terminator aggList[aggSize] = -1; // Find an aggregate id with most connections to LO maxNumConnections = 0, curNumConnections = 0; LO selectedAggregate = -1; for (size_t i = 0; i < aggSize; i++) { curNumConnections++; if (aggList[i+1] != aggList[i]) { if (curNumConnections > maxNumConnections && // only select aggregate if it has more connections aggSizes[aggList[i]] < MaxNodesPerAggregate) { // and if it is not too big (i.e. can have one more node) maxNumConnections = curNumConnections; selectedAggregate = aggList[i]; //recomputeAggregateSizes=true; } curNumConnections = 0; } } // Add node iNode to aggregate if (selectedAggregate != -1) { aggStat[iNode] = NodeStats::AGGREGATED; vertex2AggId[iNode] = selectedAggregate; procWinner[iNode] = myRank; numNonAggregatedNodes--; } } }