109 typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO> MultiVector_d;
111 const ParameterList& pL = GetParameterList();
112 RCP<MultiVector_d> coords = Get<RCP<MultiVector_d> >(currentLevel,
"Coordinates");
113 RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel,
"A");
114 RCP<const Map> rowMap = A->getRowMap();
115 RCP<const Map> colMap = A->getColMap();
116 GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
118 RCP<const Teuchos::Comm<int> > comm = rowMap->getComm();
119 int numProcs = comm->getSize();
120 int myRank = comm->getRank();
122 int numPoints = colMap->getLocalNumElements();
124 bx_ = pL.get<
int>(
"aggregation: brick x size");
125 by_ = pL.get<
int>(
"aggregation: brick y size");
126 bz_ = pL.get<
int>(
"aggregation: brick z size");
128 dirichletX_ = pL.get<
bool>(
"aggregation: brick x Dirichlet");
129 dirichletY_ = pL.get<
bool>(
"aggregation: brick y Dirichlet");
130 dirichletZ_ = pL.get<
bool>(
"aggregation: brick z Dirichlet");
131 if (dirichletX_) GetOStream(
Runtime0) <<
"Dirichlet boundaries in the x direction" << std::endl;
132 if (dirichletY_) GetOStream(
Runtime0) <<
"Dirichlet boundaries in the y direction" << std::endl;
133 if (dirichletZ_) GetOStream(
Runtime0) <<
"Dirichlet boundaries in the z direction" << std::endl;
140 RCP<MultiVector_d> overlappedCoords = coords;
141 RCP<const Import> importer = ImportFactory::Build(coords->getMap(), colMap);
142 if (!importer.is_null()) {
143 overlappedCoords = Xpetra::MultiVectorFactory<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>::Build(colMap, coords->getNumVectors());
144 overlappedCoords->doImport(*coords, *importer, Xpetra::INSERT);
149 Setup(comm, overlappedCoords, colMap);
151 GetOStream(
Runtime0) <<
"Using brick size: " << bx_
152 << (nDim_ > 1 ?
"x " +
toString(by_) :
"")
153 << (nDim_ > 2 ?
"x " +
toString(bz_) :
"") << std::endl;
156 BuildGraph(currentLevel, A);
159 RCP<Aggregates> aggregates = rcp(
new Aggregates(colMap));
160 aggregates->setObjectLabel(
"Brick");
162 ArrayRCP<LO> vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0);
163 ArrayRCP<LO> procWinner = aggregates->GetProcWinner()->getDataNonConst(0);
172 std::set<GO> myAggGIDs, remoteAggGIDs;
173 for (LO LID = 0; LID < numPoints; LID++) {
174 GO aggGID = getAggGID(LID);
176 if (aggGID == GO_INVALID)
continue;
179 if ((revMap_.find(getRoot(LID)) != revMap_.end()) && rowMap->isNodeGlobalElement(colMap->getGlobalElement(revMap_[getRoot(LID)]))) {
181 vertex2AggId[LID] = aggGID;
182 myAggGIDs.insert(aggGID);
185 aggregates->SetIsRoot(LID);
188 remoteAggGIDs.insert(aggGID);
191 size_t numAggregates = myAggGIDs.size();
192 size_t numRemote = remoteAggGIDs.size();
193 aggregates->SetNumAggregates(numAggregates);
195 std::map<GO, LO> AggG2L;
196 std::map<GO, int> AggG2R;
198 Array<GO> myAggGIDsArray(numAggregates), remoteAggGIDsArray(numRemote);
202 for (
typename std::set<GO>::const_iterator it = myAggGIDs.begin(); it != myAggGIDs.end(); it++) {
204 AggG2R[*it] = myRank;
206 myAggGIDsArray[ind++] = *it;
210 RCP<Map> aggMap = MapFactory::Build(rowMap->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
211 myAggGIDsArray, 0, comm);
214 for (
typename std::set<GO>::const_iterator it = remoteAggGIDs.begin(); it != remoteAggGIDs.end(); it++)
215 remoteAggGIDsArray[ind++] = *it;
218 Array<int> remoteProcIDs(numRemote);
219 Array<LO> remoteLIDs(numRemote);
220 aggMap->getRemoteIndexList(remoteAggGIDsArray, remoteProcIDs, remoteLIDs);
223 for (
size_t i = 0; i < numRemote; i++) {
224 AggG2L[remoteAggGIDsArray[i]] = remoteLIDs[i];
225 AggG2R[remoteAggGIDsArray[i]] = remoteProcIDs[i];
229 for (LO LID = 0; LID < numPoints; LID++) {
230 if (revMap_.find(getRoot(LID)) != revMap_.end() && rowMap->isNodeGlobalElement(colMap->getGlobalElement(revMap_[getRoot(LID)]))) {
231 GO aggGID = vertex2AggId[LID];
233 vertex2AggId[LID] = AggG2L[aggGID];
234 procWinner[LID] = AggG2R[aggGID];
241 aggregates->AggregatesCrossProcessors(numGlobalRemote);
243 Set(currentLevel,
"Aggregates", aggregates);
245 GetOStream(
Statistics1) << aggregates->description() << std::endl;
250 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 {
251 nDim_ = coords->getNumVectors();
253 x_ = coords->getData(0);
254 xMap_ = Construct1DMap(comm, x_);
259 y_ = coords->getData(1);
260 yMap_ = Construct1DMap(comm, y_);
266 z_ = coords->getData(2);
267 zMap_ = Construct1DMap(comm, z_);
271 for (
size_t ind = 0; ind < coords->getLocalLength(); ind++) {
272 GO i = (*xMap_)[(coords->getData(0))[ind]], j = 0, k = 0;
274 j = (*yMap_)[(coords->getData(1))[ind]];
276 k = (*zMap_)[(coords->getData(2))[ind]];
278 revMap_[k * ny_ * nx_ + j * nx_ + i] = ind;
282 int xboost = dirichletX_ ? 1 : 0;
283 int yboost = dirichletY_ ? 1 : 0;
284 int zboost = dirichletZ_ ? 1 : 0;
285 naggx_ = (nx_ - 2 * xboost) / bx_ + ((nx_ - 2 * xboost) % bx_ ? 1 : 0);
288 naggy_ = (ny_ - 2 * yboost) / by_ + ((ny_ - 2 * yboost) % by_ ? 1 : 0);
293 naggz_ = (nz_ - 2 * zboost) / bz_ + ((nz_ - 2 * zboost) % bz_ ? 1 : 0);
302 const ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& x)
const {
306 RCP<container> gMap = rcp(
new container);
307 for (
int i = 0; i < n; i++)
314 int numProcs = comm->getSize();
316 RCP<const Teuchos::MpiComm<int> > dupMpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm->duplicate());
318 MPI_Comm rawComm = (*dupMpiComm->getRawMpiComm())();
320 int sendCnt = gMap->size(), cnt = 0, recvSize;
321 Array<int> recvCnt(numProcs), Displs(numProcs);
322 Array<double> sendBuf, recvBuf;
324 sendBuf.resize(sendCnt);
325 for (
typename container::const_iterator cit = gMap->begin(); cit != gMap->end(); cit++)
326 sendBuf[cnt++] = Teuchos::as<double>(STS::real(cit->first));
328 MPI_Allgather(&sendCnt, 1, MPI_INT, recvCnt.getRawPtr(), 1, MPI_INT, rawComm);
330 for (
int i = 0; i < numProcs - 1; i++)
331 Displs[i + 1] = Displs[i] + recvCnt[i];
332 recvSize = Displs[numProcs - 1] + recvCnt[numProcs - 1];
333 recvBuf.resize(recvSize);
334 MPI_Allgatherv(sendBuf.getRawPtr(), sendCnt, MPI_DOUBLE, recvBuf.getRawPtr(), recvCnt.getRawPtr(), Displs.getRawPtr(), MPI_DOUBLE, rawComm);
336 for (
int i = 0; i < recvSize; i++)
337 (*gMap)[as<SC>(recvBuf[i])] = 0;
342 for (
typename container::iterator it = gMap->begin(); it != gMap->end(); it++)
445 double dirichletThreshold = 0.0;
447 if (bx_ > 1 && (nDim_ <= 1 || by_ > 1) && (nDim_ <= 2 || bz_ > 1)) {
448 FactoryMonitor m(*
this,
"Generating Graph (trivial)", currentLevel);
451 RCP<LWGraph> graph = rcp(
new LWGraph(A->getCrsGraph(),
"graph of A"));
453 graph->SetBoundaryNodeMap(boundaryNodes);
456 GO numLocalBoundaryNodes = 0;
457 GO numGlobalBoundaryNodes = 0;
458 for (
size_t i = 0; i < boundaryNodes.size(); ++i)
459 if (boundaryNodes(i))
460 numLocalBoundaryNodes++;
461 RCP<const Teuchos::Comm<int> > comm = A->getRowMap()->getComm();
462 MueLu_sumAll(comm, numLocalBoundaryNodes, numGlobalBoundaryNodes);
463 GetOStream(
Statistics1) <<
"Detected " << numGlobalBoundaryNodes <<
" Dirichlet nodes" << std::endl;
465 Set(currentLevel,
"DofsPerNode", 1);
466 Set(currentLevel,
"Graph", graph);
467 Set(currentLevel,
"Filtering",
false);
473 bool drop_x = (bx_ == 1);
474 bool drop_y = (nDim_ > 1 && by_ == 1);
475 bool drop_z = (nDim_ > 2 && bz_ == 1);
477 typename LWGraph::row_type::non_const_type
rows(
"rows", A->getLocalNumRows() + 1);
478 typename LWGraph::entries_type::non_const_type columns(
"columns", A->getLocalNumEntries());
480 size_t N = A->getRowMap()->getLocalNumElements();
483 auto G = A->getLocalMatrixHost().graph;
484 auto rowptr = G.row_map;
485 auto colind = G.entries;
489 for (
size_t row = 0; row < N; row++) {
492 LO row2 = A->getColMap()->getLocalElement(A->getRowMap()->getGlobalElement(row));
493 getIJK(row2, ir, jr, kr);
495 for (
size_t cidx = rowptr[row]; cidx < rowptr[row + 1]; cidx++) {
497 LO col = colind[cidx];
498 getIJK(col, ic, jc, kc);
500 if ((row2 != col) && ((drop_x && ir != ic) || (drop_y && jr != jc) || (drop_z && kr != kc))) {
513 RCP<LWGraph> graph = rcp(
new LWGraph(
rows, columns, A->getRowMap(), A->getColMap(),
"thresholded graph of A"));
516 graph->SetBoundaryNodeMap(boundaryNodes);
519 GO numLocalBoundaryNodes = 0;
520 GO numGlobalBoundaryNodes = 0;
521 for (
size_t i = 0; i < boundaryNodes.size(); ++i)
522 if (boundaryNodes(i))
523 numLocalBoundaryNodes++;
524 RCP<const Teuchos::Comm<int> > comm = A->getRowMap()->getComm();
525 MueLu_sumAll(comm, numLocalBoundaryNodes, numGlobalBoundaryNodes);
526 GetOStream(
Statistics1) <<
"Detected " << numGlobalBoundaryNodes <<
" Dirichlet nodes" << std::endl;
528 Set(currentLevel,
"DofsPerNode", 1);
529 Set(currentLevel,
"Graph", graph);
530 Set(currentLevel,
"Filtering",
true);