111 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> MultiVector_d;
113 const ParameterList& pL = GetParameterList();
114 RCP<MultiVector_d> coords = Get<RCP<MultiVector_d> >(currentLevel,
"Coordinates");
115 RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel,
"A");
116 RCP<const Map> rowMap = A->getRowMap();
117 RCP<const Map> colMap = A->getColMap();
118 GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
120 RCP<const Teuchos::Comm<int> > comm = rowMap->getComm();
121 int numProcs = comm->getSize();
122 int myRank = comm->getRank();
124 int numPoints = colMap->getLocalNumElements();
126 bx_ = pL.get<
int>(
"aggregation: brick x size");
127 by_ = pL.get<
int>(
"aggregation: brick y size");
128 bz_ = pL.get<
int>(
"aggregation: brick z size");
130 dirichletX_ = pL.get<
bool>(
"aggregation: brick x Dirichlet");
131 dirichletY_ = pL.get<
bool>(
"aggregation: brick y Dirichlet");
132 dirichletZ_ = pL.get<
bool>(
"aggregation: brick z Dirichlet");
133 if (dirichletX_) GetOStream(
Runtime0) <<
"Dirichlet boundaries in the x direction" << std::endl;
134 if (dirichletY_) GetOStream(
Runtime0) <<
"Dirichlet boundaries in the y direction" << std::endl;
135 if (dirichletZ_) GetOStream(
Runtime0) <<
"Dirichlet boundaries in the z direction" << std::endl;
142 RCP<MultiVector_d> overlappedCoords = coords;
143 RCP<const Import> importer = ImportFactory::Build(coords->getMap(), colMap);
144 if (!importer.is_null()) {
145 overlappedCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>::Build(colMap, coords->getNumVectors());
146 overlappedCoords->doImport(*coords, *importer, Xpetra::INSERT);
151 Setup(comm, overlappedCoords, colMap);
153 GetOStream(
Runtime0) <<
"Using brick size: " << bx_
154 << (nDim_ > 1 ?
"x " +
toString(by_) :
"")
155 << (nDim_ > 2 ?
"x " +
toString(bz_) :
"") << std::endl;
158 BuildGraph(currentLevel, A);
161 RCP<Aggregates> aggregates = rcp(
new Aggregates(colMap));
162 aggregates->setObjectLabel(
"Brick");
164 ArrayRCP<LO> vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0);
165 ArrayRCP<LO> procWinner = aggregates->GetProcWinner()->getDataNonConst(0);
174 std::set<GO> myAggGIDs, remoteAggGIDs;
175 for (LO LID = 0; LID < numPoints; LID++) {
176 GO aggGID = getAggGID(LID);
178 if (aggGID == GO_INVALID)
continue;
181 if ((revMap_.find(getRoot(LID)) != revMap_.end()) && rowMap->isNodeGlobalElement(colMap->getGlobalElement(revMap_[getRoot(LID)]))) {
183 vertex2AggId[LID] = aggGID;
184 myAggGIDs.insert(aggGID);
187 aggregates->SetIsRoot(LID);
190 remoteAggGIDs.insert(aggGID);
193 size_t numAggregates = myAggGIDs.size();
194 size_t numRemote = remoteAggGIDs.size();
195 aggregates->SetNumAggregates(numAggregates);
197 std::map<GO, LO> AggG2L;
198 std::map<GO, int> AggG2R;
200 Array<GO> myAggGIDsArray(numAggregates), remoteAggGIDsArray(numRemote);
204 for (
typename std::set<GO>::const_iterator it = myAggGIDs.begin(); it != myAggGIDs.end(); it++) {
206 AggG2R[*it] = myRank;
208 myAggGIDsArray[ind++] = *it;
212 RCP<Map> aggMap = MapFactory::Build(rowMap->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
213 myAggGIDsArray, 0, comm);
216 for (
typename std::set<GO>::const_iterator it = remoteAggGIDs.begin(); it != remoteAggGIDs.end(); it++)
217 remoteAggGIDsArray[ind++] = *it;
220 Array<int> remoteProcIDs(numRemote);
221 Array<LO> remoteLIDs(numRemote);
222 aggMap->getRemoteIndexList(remoteAggGIDsArray, remoteProcIDs, remoteLIDs);
225 for (
size_t i = 0; i < numRemote; i++) {
226 AggG2L[remoteAggGIDsArray[i]] = remoteLIDs[i];
227 AggG2R[remoteAggGIDsArray[i]] = remoteProcIDs[i];
231 for (LO LID = 0; LID < numPoints; LID++) {
232 if (revMap_.find(getRoot(LID)) != revMap_.end() && rowMap->isNodeGlobalElement(colMap->getGlobalElement(revMap_[getRoot(LID)]))) {
233 GO aggGID = vertex2AggId[LID];
235 vertex2AggId[LID] = AggG2L[aggGID];
236 procWinner[LID] = AggG2R[aggGID];
243 aggregates->AggregatesCrossProcessors(numGlobalRemote);
245 Set(currentLevel,
"Aggregates", aggregates);
247 GetOStream(
Statistics1) << aggregates->description() << std::endl;
252 Setup(
const RCP<
const Teuchos::Comm<int> >& comm,
const RCP<Xpetra::MultiVector<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> >& coords,
const RCP<const Map>& )
const {
253 nDim_ = coords->getNumVectors();
255 x_ = coords->getData(0);
256 xMap_ = Construct1DMap(comm, x_);
261 y_ = coords->getData(1);
262 yMap_ = Construct1DMap(comm, y_);
268 z_ = coords->getData(2);
269 zMap_ = Construct1DMap(comm, z_);
273 for (
size_t ind = 0; ind < coords->getLocalLength(); ind++) {
274 GO i = (*xMap_)[(coords->getData(0))[ind]], j = 0, k = 0;
276 j = (*yMap_)[(coords->getData(1))[ind]];
278 k = (*zMap_)[(coords->getData(2))[ind]];
280 revMap_[k * ny_ * nx_ + j * nx_ + i] = ind;
284 int xboost = dirichletX_ ? 1 : 0;
285 int yboost = dirichletY_ ? 1 : 0;
286 int zboost = dirichletZ_ ? 1 : 0;
287 naggx_ = (nx_ - 2 * xboost) / bx_ + ((nx_ - 2 * xboost) % bx_ ? 1 : 0);
290 naggy_ = (ny_ - 2 * yboost) / by_ + ((ny_ - 2 * yboost) % by_ ? 1 : 0);
295 naggz_ = (nz_ - 2 * zboost) / bz_ + ((nz_ - 2 * zboost) % bz_ ? 1 : 0);
304 const ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& x)
const {
308 RCP<container> gMap = rcp(
new container);
309 for (
int i = 0; i < n; i++)
316 int numProcs = comm->getSize();
318 RCP<const Teuchos::MpiComm<int> > dupMpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm->duplicate());
320 MPI_Comm rawComm = (*dupMpiComm->getRawMpiComm())();
322 int sendCnt = gMap->size(), cnt = 0, recvSize;
323 Array<int> recvCnt(numProcs), Displs(numProcs);
324 Array<double> sendBuf, recvBuf;
326 sendBuf.resize(sendCnt);
327 for (
typename container::const_iterator cit = gMap->begin(); cit != gMap->end(); cit++)
328 sendBuf[cnt++] = Teuchos::as<double>(STS::real(cit->first));
330 MPI_Allgather(&sendCnt, 1, MPI_INT, recvCnt.getRawPtr(), 1, MPI_INT, rawComm);
332 for (
int i = 0; i < numProcs - 1; i++)
333 Displs[i + 1] = Displs[i] + recvCnt[i];
334 recvSize = Displs[numProcs - 1] + recvCnt[numProcs - 1];
335 recvBuf.resize(recvSize);
336 MPI_Allgatherv(sendBuf.getRawPtr(), sendCnt, MPI_DOUBLE, recvBuf.getRawPtr(), recvCnt.getRawPtr(), Displs.getRawPtr(), MPI_DOUBLE, rawComm);
338 for (
int i = 0; i < recvSize; i++)
339 (*gMap)[as<SC>(recvBuf[i])] = 0;
344 for (
typename container::iterator it = gMap->begin(); it != gMap->end(); it++)
447 double dirichletThreshold = 0.0;
449 if (bx_ > 1 && (nDim_ <= 1 || by_ > 1) && (nDim_ <= 2 || bz_ > 1)) {
450 FactoryMonitor m(*
this,
"Generating Graph (trivial)", currentLevel);
453 RCP<LWGraph> graph = rcp(
new LWGraph(A->getCrsGraph(),
"graph of A"));
455 graph->SetBoundaryNodeMap(boundaryNodes);
458 GO numLocalBoundaryNodes = 0;
459 GO numGlobalBoundaryNodes = 0;
460 for (
size_t i = 0; i < boundaryNodes.size(); ++i)
461 if (boundaryNodes(i))
462 numLocalBoundaryNodes++;
463 RCP<const Teuchos::Comm<int> > comm = A->getRowMap()->getComm();
464 MueLu_sumAll(comm, numLocalBoundaryNodes, numGlobalBoundaryNodes);
465 GetOStream(
Statistics1) <<
"Detected " << numGlobalBoundaryNodes <<
" Dirichlet nodes" << std::endl;
467 Set(currentLevel,
"DofsPerNode", 1);
468 Set(currentLevel,
"Graph", graph);
469 Set(currentLevel,
"Filtering",
false);
475 bool drop_x = (bx_ == 1);
476 bool drop_y = (nDim_ > 1 && by_ == 1);
477 bool drop_z = (nDim_ > 2 && bz_ == 1);
479 typename LWGraph::row_type::non_const_type
rows(
"rows", A->getLocalNumRows() + 1);
480 typename LWGraph::entries_type::non_const_type columns(
"columns", A->getLocalNumEntries());
482 size_t N = A->getRowMap()->getLocalNumElements();
485 auto G = A->getLocalMatrixHost().graph;
486 auto rowptr = G.row_map;
487 auto colind = G.entries;
491 for (
size_t row = 0; row < N; row++) {
494 LO row2 = A->getColMap()->getLocalElement(A->getRowMap()->getGlobalElement(row));
495 getIJK(row2, ir, jr, kr);
497 for (
size_t cidx = rowptr[row]; cidx < rowptr[row + 1]; cidx++) {
499 LO col = colind[cidx];
500 getIJK(col, ic, jc, kc);
502 if ((row2 != col) && ((drop_x && ir != ic) || (drop_y && jr != jc) || (drop_z && kr != kc))) {
515 RCP<LWGraph> graph = rcp(
new LWGraph(
rows, columns, A->getRowMap(), A->getColMap(),
"thresholded graph of A"));
518 graph->SetBoundaryNodeMap(boundaryNodes);
521 GO numLocalBoundaryNodes = 0;
522 GO numGlobalBoundaryNodes = 0;
523 for (
size_t i = 0; i < boundaryNodes.size(); ++i)
524 if (boundaryNodes(i))
525 numLocalBoundaryNodes++;
526 RCP<const Teuchos::Comm<int> > comm = A->getRowMap()->getComm();
527 MueLu_sumAll(comm, numLocalBoundaryNodes, numGlobalBoundaryNodes);
528 GetOStream(
Statistics1) <<
"Detected " << numGlobalBoundaryNodes <<
" Dirichlet nodes" << std::endl;
530 Set(currentLevel,
"DofsPerNode", 1);
531 Set(currentLevel,
"Graph", graph);
532 Set(currentLevel,
"Filtering",
true);