10 #ifndef MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
11 #define MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
14 #include <Xpetra_MapFactory.hpp>
18 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
21 const int NumDimensions,
const int interpolationOrder,
22 const int MyRank,
const int NumRanks,
25 :
IndexManager(comm, coupled, false, NumDimensions, interpolationOrder, GFineNodesPerDir, LFineNodesPerDir)
27 , numRanks(NumRanks) {
34 for (
int dim = 0; dim < 3; ++dim) {
36 if (CoarseRate.
size() == 1) {
47 for (
int rank = 0; rank <
numRanks; ++rank) {
49 for (
int entry = 0; entry < 10; ++entry) {
50 meshData[rank][entry] = MeshData[10 * rank + entry];
61 for (
int dim = 0; dim < 3; ++dim) {
71 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
74 this->gNumCoarseNodes10 = this->gCoarseNodesPerDir[0] * this->gCoarseNodesPerDir[1];
75 this->gNumCoarseNodes = this->gNumCoarseNodes10 * this->gCoarseNodesPerDir[2];
78 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
85 ghostedNodeCoarseLIDs.
resize(this->getNumLocalGhostedNodes());
86 ghostedNodeCoarsePIDs.
resize(this->getNumLocalGhostedNodes());
87 ghostedNodeCoarseGIDs.
resize(this->numGhostedNodes);
94 Array<LO> ghostedCoarseNodeCoarseIndices(3), ghostedCoarseNodeFineIndices(3);
96 Array<GO> lCoarseNodeCoarseGIDs(this->lNumCoarseNodes);
97 LO currentIndex = -1, countCoarseNodes = 0;
98 for (
int k = 0; k < this->ghostedNodesPerDir[2]; ++k) {
99 for (
int j = 0; j < this->ghostedNodesPerDir[1]; ++j) {
100 for (
int i = 0; i < this->ghostedNodesPerDir[0]; ++i) {
101 currentIndex = k * this->numGhostedNodes10 + j * this->ghostedNodesPerDir[0] + i;
102 ghostedCoarseNodeCoarseIndices[0] = this->startGhostedCoarseNode[0] + i;
103 ghostedCoarseNodeFineIndices[0] = ghostedCoarseNodeCoarseIndices[0] * this->coarseRate[0];
104 if (ghostedCoarseNodeFineIndices[0] > this->gFineNodesPerDir[0] - 1) {
105 ghostedCoarseNodeFineIndices[0] = this->gFineNodesPerDir[0] - 1;
107 ghostedCoarseNodeCoarseIndices[1] = this->startGhostedCoarseNode[1] + j;
108 ghostedCoarseNodeFineIndices[1] = ghostedCoarseNodeCoarseIndices[1] * this->coarseRate[1];
109 if (ghostedCoarseNodeFineIndices[1] > this->gFineNodesPerDir[1] - 1) {
110 ghostedCoarseNodeFineIndices[1] = this->gFineNodesPerDir[1] - 1;
112 ghostedCoarseNodeCoarseIndices[2] = this->startGhostedCoarseNode[2] + k;
113 ghostedCoarseNodeFineIndices[2] = ghostedCoarseNodeCoarseIndices[2] * this->coarseRate[2];
114 if (ghostedCoarseNodeFineIndices[2] > this->gFineNodesPerDir[2] - 1) {
115 ghostedCoarseNodeFineIndices[2] = this->gFineNodesPerDir[2] - 1;
118 GO myGID = -1, myCoarseGID = -1;
119 LO myLID = -1, myPID = -1, myCoarseLID = -1;
120 getGIDLocalLexicographic(i, j, k, ghostedCoarseNodeFineIndices, myGID, myPID, myLID);
122 int rankIndex = rankIndices[myPID];
123 for (
int dim = 0; dim < 3; ++dim) {
124 if (dim < this->numDimensions) {
125 lCoarseNodeCoarseIndices[dim] = ghostedCoarseNodeCoarseIndices[dim] - coarseMeshData[rankIndex][3 + 2 * dim];
128 LO myRankIndexCoarseNodesInDir0 = coarseMeshData[rankIndex][4] - coarseMeshData[rankIndex][3] + 1;
129 LO myRankIndexCoarseNodes10 = (coarseMeshData[rankIndex][6] - coarseMeshData[rankIndex][5] + 1) * myRankIndexCoarseNodesInDir0;
130 myCoarseLID = lCoarseNodeCoarseIndices[2] * myRankIndexCoarseNodes10 + lCoarseNodeCoarseIndices[1] * myRankIndexCoarseNodesInDir0 + lCoarseNodeCoarseIndices[0];
131 myCoarseGID = myCoarseLID + coarseMeshData[rankIndex][9];
133 ghostedNodeCoarseLIDs[currentIndex] = myCoarseLID;
134 ghostedNodeCoarsePIDs[currentIndex] = myPID;
135 ghostedNodeCoarseGIDs[currentIndex] = myCoarseGID;
137 if (myPID == myRank) {
138 lCoarseNodeCoarseGIDs[countCoarseNodes] = myCoarseGID;
146 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
152 coarseNodeCoarseGIDs.
resize(this->getNumLocalCoarseNodes());
153 coarseNodeFineGIDs.
resize(this->getNumLocalCoarseNodes());
159 for (
int dim = 0; dim < 3; ++dim) {
160 coarseStartIndices[dim] = this->coarseMeshData[myRankIndex][2 * dim + 3];
165 for (
LO coarseLID = 0; coarseLID < this->getNumLocalCoarseNodes(); ++coarseLID) {
166 Array<LO> coarseIndices(3), fineIndices(3), gCoarseIndices(3);
167 this->getCoarseNodeLocalTuple(coarseLID,
171 getCoarseNodeFineLID(coarseIndices[0], coarseIndices[1], coarseIndices[2], fineLID);
172 coarseNodeFineGIDs[coarseLID] = fineNodeGIDs[fineLID];
174 LO myRankIndexCoarseNodesInDir0 = coarseMeshData[myRankIndex][4] - coarseMeshData[myRankIndex][3] + 1;
175 LO myRankIndexCoarseNodes10 = (coarseMeshData[myRankIndex][6] - coarseMeshData[myRankIndex][5] + 1) * myRankIndexCoarseNodesInDir0;
176 LO myCoarseLID = coarseIndices[2] * myRankIndexCoarseNodes10 + coarseIndices[1] * myRankIndexCoarseNodesInDir0 + coarseIndices[0];
177 GO myCoarseGID = myCoarseLID + coarseMeshData[myRankIndex][9];
178 coarseNodeCoarseGIDs[coarseLID] = myCoarseGID;
182 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
186 GO& myGID,
LO& myPID,
LO& myLID)
const {
187 LO ni = -1, nj = -1, li = -1, lj = -1, lk = -1;
188 LO myRankGuess = myRankIndex;
190 if (iGhosted == 0 && this->ghostInterface[0]) {
192 }
else if ((iGhosted == this->ghostedNodesPerDir[0] - 1) && this->ghostInterface[1]) {
195 if (jGhosted == 0 && this->ghostInterface[2]) {
197 }
else if ((jGhosted == this->ghostedNodesPerDir[1] - 1) && this->ghostInterface[3]) {
200 if (kGhosted == 0 && this->ghostInterface[4]) {
201 myRankGuess -= pj * pi;
202 }
else if ((kGhosted == this->ghostedNodesPerDir[2] - 1) && this->ghostInterface[5]) {
203 myRankGuess += pj * pi;
205 if (coarseNodeFineIndices[0] >= meshData[myRankGuess][3] && coarseNodeFineIndices[0] <= meshData[myRankGuess][4] && coarseNodeFineIndices[1] >= meshData[myRankGuess][5] && coarseNodeFineIndices[1] <= meshData[myRankGuess][6] && coarseNodeFineIndices[2] >= meshData[myRankGuess][7] && coarseNodeFineIndices[2] <= meshData[myRankGuess][8] && myRankGuess < numRanks - 1) {
206 myPID = meshData[myRankGuess][0];
207 ni = meshData[myRankGuess][4] - meshData[myRankGuess][3] + 1;
208 nj = meshData[myRankGuess][6] - meshData[myRankGuess][5] + 1;
209 li = coarseNodeFineIndices[0] - meshData[myRankGuess][3];
210 lj = coarseNodeFineIndices[1] - meshData[myRankGuess][5];
211 lk = coarseNodeFineIndices[2] - meshData[myRankGuess][7];
212 myLID = lk * nj * ni + lj * ni + li;
213 myGID = meshData[myRankGuess][9] + myLID;
217 auto nodeRank = std::find_if(myBlockStart, myBlockEnd,
218 [coarseNodeFineIndices](
const std::vector<GO>& vec) {
219 if (coarseNodeFineIndices[0] >= vec[3] && coarseNodeFineIndices[0] <= vec[4] && coarseNodeFineIndices[1] >= vec[5] && coarseNodeFineIndices[1] <= vec[6] && coarseNodeFineIndices[2] >= vec[7] && coarseNodeFineIndices[2] <= vec[8]) {
225 myPID = (*nodeRank)[0];
226 ni = (*nodeRank)[4] - (*nodeRank)[3] + 1;
227 nj = (*nodeRank)[6] - (*nodeRank)[5] + 1;
228 li = coarseNodeFineIndices[0] - (*nodeRank)[3];
229 lj = coarseNodeFineIndices[1] - (*nodeRank)[5];
230 lk = coarseNodeFineIndices[2] - (*nodeRank)[7];
231 myLID = lk * nj * ni + lj * ni + li;
232 myGID = (*nodeRank)[9] + myLID;
236 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
239 std::sort(meshData.begin(), meshData.end(),
240 [](
const std::vector<GO>& a,
const std::vector<GO>& b) ->
bool {
244 }
else if (a[2] == b[2]) {
247 }
else if (a[7] == b[7]) {
250 }
else if (a[5] == b[5]) {
260 numBlocks = meshData[numRanks - 1][2] + 1;
262 myBlockStart = std::lower_bound(meshData.begin(), meshData.end(), myBlock - 1,
263 [](
const std::vector<GO>& vec,
const GO val) ->
bool {
264 return (vec[2] < val) ?
true :
false;
266 myBlockEnd = std::upper_bound(meshData.begin(), meshData.end(), myBlock,
267 [](
const GO val,
const std::vector<GO>& vec) ->
bool {
268 return (val < vec[2]) ?
true :
false;
273 auto myKEnd = std::upper_bound(myBlockStart, myBlockEnd, (*myBlockStart)[3],
274 [](
const GO val,
const std::vector<GO>& vec) ->
bool {
275 return (val < vec[7]) ?
true :
false;
277 auto myJEnd = std::upper_bound(myBlockStart, myKEnd, (*myBlockStart)[3],
278 [](
const GO val,
const std::vector<GO>& vec) ->
bool {
279 return (val < vec[5]) ?
true :
false;
281 pi = std::distance(myBlockStart, myJEnd);
282 pj = std::distance(myBlockStart, myKEnd) / pi;
283 pk = std::distance(myBlockStart, myBlockEnd) / (pj * pi);
286 const int MyRank = myRank;
287 myRankIndex = std::distance(meshData.begin(),
288 std::find_if(myBlockStart, myBlockEnd,
289 [MyRank](
const std::vector<GO>& vec) ->
bool {
290 return (vec[0] == MyRank) ?
true :
false;
294 for (
int rankIndex = 0; rankIndex < numRanks; ++rankIndex) {
295 rankIndices[meshData[rankIndex][0]] = rankIndex;
299 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
303 for (
int rank = 0; rank < numRanks; ++rank) {
304 coarseMeshData[rank].resize(10);
305 coarseMeshData[rank][0] = meshData[rank][0];
306 coarseMeshData[rank][1] = meshData[rank][1];
307 coarseMeshData[rank][2] = meshData[rank][2];
308 for (
int dim = 0; dim < 3; ++dim) {
309 coarseMeshData[rank][3 + 2 * dim] = meshData[rank][3 + 2 * dim] / this->coarseRate[dim];
310 if (meshData[rank][3 + 2 * dim] % this->coarseRate[dim] > 0) {
311 ++coarseMeshData[rank][3 + 2 * dim];
313 coarseMeshData[rank][3 + 2 * dim + 1] = meshData[rank][3 + 2 * dim + 1] / this->coarseRate[dim];
314 if (meshData[rank][3 + 2 * dim + 1] == this->gFineNodesPerDir[dim] - 1 &&
315 meshData[rank][3 + 2 * dim + 1] % this->coarseRate[dim] > 0) {
317 ++coarseMeshData[rank][3 + 2 * dim + 1];
321 coarseMeshData[rank][9] = coarseMeshData[rank - 1][9] + (coarseMeshData[rank - 1][8] - coarseMeshData[rank - 1][7] + 1) * (coarseMeshData[rank - 1][6] - coarseMeshData[rank - 1][5] + 1) * (coarseMeshData[rank - 1][4] - coarseMeshData[rank - 1][3] + 1);
326 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
330 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
335 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
339 k = myLID / this->lNumFineNodes10;
340 tmp = myLID % this->lNumFineNodes10;
341 j = tmp / this->lFineNodesPerDir[0];
342 i = tmp % this->lFineNodesPerDir[0];
345 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
349 k = myLID / this->lNumFineNodes10;
350 tmp = myLID % this->lNumFineNodes10;
351 j = tmp / this->lFineNodesPerDir[0];
352 i = tmp % this->lFineNodesPerDir[0];
354 k += this->offsets[2];
355 j += this->offsets[1];
356 i += this->offsets[0];
359 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
364 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
369 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
374 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
378 k = myLID / this->lNumCoarseNodes10;
379 tmp = myLID % this->lNumCoarseNodes10;
380 j = tmp / this->lCoarseNodesPerDir[0];
381 i = tmp % this->lCoarseNodesPerDir[0];
384 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
389 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
394 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
397 myLID = k * this->numGhostedNodes10 + j * this->ghostedNodesPerDir[0] + i;
400 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
405 const LO multiplier[3] = {1, this->lFineNodesPerDir[0], this->lNumFineNodes10};
406 const LO indices[3] = {i, j, k};
409 for (
int dim = 0; dim < 3; ++dim) {
410 if ((indices[dim] == this->getLocalCoarseNodesInDir(dim) - 1) && this->meshEdge[2 * dim + 1]) {
413 myLID += (this->getLocalFineNodesInDir(dim) - 1) * multiplier[dim];
415 myLID += (indices[dim] * this->getCoarseningRate(dim) + this->getCoarseNodeOffset(dim)) * multiplier[dim];
420 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
425 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
const bool coupled_
Flag for coupled vs uncoupled aggregation mode, if true aggregation is coupled.
void getCoarseNodeGlobalTuple(const GO myGID, GO &i, GO &j, GO &k) const
void getCoarseNodeLocalTuple(const LO myLID, LO &i, LO &j, LO &k) const
void getGhostedNodesData(const RCP< const Map > fineMap, Array< LO > &ghostedNodeCoarseLIDs, Array< int > &ghostedNodeCoarsePIDs, Array< GO > &ghostedNodeCoarseGIDs) const
void getFineNodeLocalTuple(const LO myLID, LO &i, LO &j, LO &k) const
std::vector< std::vector< GO > > getCoarseMeshData() const
void sortLocalLexicographicData()
void getFineNodeGhostedTuple(const LO myLID, LO &i, LO &j, LO &k) const
void getGhostedNodeCoarseLID(const LO i, const LO j, const LO k, LO &myLID) const
void getGhostedNodeFineLID(const LO i, const LO j, const LO k, LO &myLID) const
int myRankIndex
local process index for record in meshData after sorting.
void getCoarseNodesData(const RCP< const Map > fineCoordinatesMap, Array< GO > &coarseNodeCoarseGIDs, Array< GO > &coarseNodeFineGIDs) const
Array< GO > startIndices
lowest global tuple (i,j,k) of a node on the local process
void getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO &myLID) const
std::vector< std::vector< GO > > meshData
layout of indices accross all processes.
void getCoarseNodeLID(const LO i, const LO j, const LO k, LO &myLID) const
int myBlock
local mesh block ID.
Array< int > coarseRate
coarsening rate in each direction
void getFineNodeGlobalTuple(const GO myGID, GO &i, GO &j, GO &k) const
const int numDimensions
Number of spacial dimensions in the problem.
Array< int > rankIndices
mapping between rank ID and reordered rank ID.
void getFineNodeGID(const GO i, const GO j, const GO k, GO &myGID) const
const int numRanks
Number of ranks used to decompose the problem.
void computeGlobalCoarseParameters()
void resize(size_type new_size, const value_type &x=value_type())
void getCoarseNodeGID(const GO i, const GO j, const GO k, GO &myGID) const
void getFineNodeLID(const LO i, const LO j, const LO k, LO &myLID) const
LocalLexicographicIndexManager()=default
void computeCoarseLocalLexicographicData()
void getCoarseNodeGhostedLID(const LO i, const LO j, const LO k, LO &myLID) const
void getGIDLocalLexicographic(const LO iGhosted, const LO jGhosted, const LO kGhosted, const Array< LO > coarseNodeFineIndices, GO &myGID, LO &myPID, LO &myLID) const
void computeMeshParameters()
const int myRank
Local rank ID.
Container class for mesh layout and indices calculation.
std::vector< std::vector< GO > > coarseMeshData
layout of indices accross all processes after coarsening.