46 #ifndef MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_ 47 #define MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_ 50 #include <Xpetra_MapFactory.hpp> 54 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
57 const int NumDimensions,
const int interpolationOrder,
58 const int MyRank,
const int NumRanks,
59 const Array<GO> GFineNodesPerDir,
const Array<LO> LFineNodesPerDir,
60 const Array<LO> CoarseRate,
const Array<GO> MeshData) :
61 IndexManager(comm, coupled, NumDimensions, interpolationOrder, GFineNodesPerDir, LFineNodesPerDir),
62 myRank(MyRank), numRanks(NumRanks) {
70 for(
int dim = 0; dim < 3; ++dim) {
72 if(CoarseRate.size() == 1) {
83 for(
int rank = 0; rank <
numRanks; ++rank) {
85 for(
int entry = 0; entry < 10; ++entry) {
86 meshData[rank][entry] = MeshData[10*rank + entry];
97 for(
int dim = 0; dim < 3; ++dim) {
107 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
110 this->gNumCoarseNodes10 = this->gCoarseNodesPerDir[0]*this->gCoarseNodesPerDir[1];
111 this->gNumCoarseNodes = this->gNumCoarseNodes10*this->gCoarseNodesPerDir[2];
114 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
117 Array<LO>& ghostedNodeCoarseLIDs, Array<int>& ghostedNodeCoarsePIDs, Array<GO>& ghostedNodeCoarseGIDs)
const {
120 ghostedNodeCoarseLIDs.resize(this->getNumLocalGhostedNodes());
121 ghostedNodeCoarsePIDs.resize(this->getNumLocalGhostedNodes());
122 ghostedNodeCoarseGIDs.resize(this->numGhostedNodes);
129 Array<LO> ghostedCoarseNodeCoarseIndices(3), ghostedCoarseNodeFineIndices(3);
130 Array<LO> lCoarseNodeCoarseIndices(3);
131 Array<GO> lCoarseNodeCoarseGIDs(this->lNumCoarseNodes);
132 LO currentIndex = -1, countCoarseNodes = 0;
133 for(
int k = 0; k < this->ghostedNodesPerDir[2]; ++k) {
134 for(
int j = 0; j < this->ghostedNodesPerDir[1]; ++j) {
135 for(
int i = 0; i < this->ghostedNodesPerDir[0]; ++i) {
136 currentIndex = k*this->numGhostedNodes10 + j*this->ghostedNodesPerDir[0] + i;
137 ghostedCoarseNodeCoarseIndices[0] = this->startGhostedCoarseNode[0] + i;
138 ghostedCoarseNodeFineIndices[0] = ghostedCoarseNodeCoarseIndices[0]*this->coarseRate[0];
139 if(ghostedCoarseNodeFineIndices[0] > this->gFineNodesPerDir[0] - 1) {
140 ghostedCoarseNodeFineIndices[0] = this->gFineNodesPerDir[0] - 1;
142 ghostedCoarseNodeCoarseIndices[1] = this->startGhostedCoarseNode[1] + j;
143 ghostedCoarseNodeFineIndices[1] = ghostedCoarseNodeCoarseIndices[1]*this->coarseRate[1];
144 if(ghostedCoarseNodeFineIndices[1] > this->gFineNodesPerDir[1] - 1) {
145 ghostedCoarseNodeFineIndices[1] = this->gFineNodesPerDir[1] - 1;
147 ghostedCoarseNodeCoarseIndices[2] = this->startGhostedCoarseNode[2] + k;
148 ghostedCoarseNodeFineIndices[2] = ghostedCoarseNodeCoarseIndices[2]*this->coarseRate[2];
149 if(ghostedCoarseNodeFineIndices[2] > this->gFineNodesPerDir[2] - 1) {
150 ghostedCoarseNodeFineIndices[2] = this->gFineNodesPerDir[2] - 1;
153 GO myGID = -1, myCoarseGID = -1;
154 LO myLID = -1, myPID = -1, myCoarseLID = -1;
155 getGIDLocalLexicographic(i, j, k, ghostedCoarseNodeFineIndices, myGID, myPID, myLID);
157 int rankIndex = rankIndices[myPID];
158 for(
int dim = 0; dim < 3; ++dim) {
159 if(dim < this->numDimensions) {
160 lCoarseNodeCoarseIndices[dim] = ghostedCoarseNodeCoarseIndices[dim]
161 - coarseMeshData[rankIndex][3 + 2*dim];
164 LO myRankIndexCoarseNodesInDir0 = coarseMeshData[rankIndex][4]
165 - coarseMeshData[rankIndex][3] + 1;
166 LO myRankIndexCoarseNodes10 = (coarseMeshData[rankIndex][6]
167 - coarseMeshData[rankIndex][5] + 1)
168 *myRankIndexCoarseNodesInDir0;
169 myCoarseLID = lCoarseNodeCoarseIndices[2]*myRankIndexCoarseNodes10
170 + lCoarseNodeCoarseIndices[1]*myRankIndexCoarseNodesInDir0
171 + lCoarseNodeCoarseIndices[0];
172 myCoarseGID = myCoarseLID + coarseMeshData[rankIndex][9];
174 ghostedNodeCoarseLIDs[currentIndex] = myCoarseLID;
175 ghostedNodeCoarsePIDs[currentIndex] = myPID;
176 ghostedNodeCoarseGIDs[currentIndex] = myCoarseGID;
178 if(myPID == myRank) {
179 lCoarseNodeCoarseGIDs[countCoarseNodes] = myCoarseGID;
187 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
190 Array<GO>& coarseNodeCoarseGIDs,
191 Array<GO>& coarseNodeFineGIDs)
const {
194 coarseNodeCoarseGIDs.resize(this->getNumLocalCoarseNodes());
195 coarseNodeFineGIDs.resize(this->getNumLocalCoarseNodes());
198 ArrayView<const GO> fineNodeGIDs = fineCoordinatesMap->getNodeElementList();
200 Array<GO> coarseStartIndices(3);
202 for(
int dim = 0; dim < 3; ++dim) {
203 coarseStartIndices[dim] = this->coarseMeshData[myRankIndex][2*dim + 3];
208 for(LO coarseLID = 0; coarseLID < this->getNumLocalCoarseNodes(); ++coarseLID) {
209 Array<LO> coarseIndices(3), fineIndices(3), gCoarseIndices(3);
210 this->getCoarseNodeLocalTuple(coarseLID,
214 getCoarseNodeFineLID(coarseIndices[0],coarseIndices[1],coarseIndices[2],fineLID);
215 coarseNodeFineGIDs[coarseLID] = fineNodeGIDs[fineLID];
217 LO myRankIndexCoarseNodesInDir0 = coarseMeshData[myRankIndex][4]
218 - coarseMeshData[myRankIndex][3] + 1;
219 LO myRankIndexCoarseNodes10 = (coarseMeshData[myRankIndex][6]
220 - coarseMeshData[myRankIndex][5] + 1)
221 *myRankIndexCoarseNodesInDir0;
222 LO myCoarseLID = coarseIndices[2]*myRankIndexCoarseNodes10
223 + coarseIndices[1]*myRankIndexCoarseNodesInDir0
225 GO myCoarseGID = myCoarseLID + coarseMeshData[myRankIndex][9];
226 coarseNodeCoarseGIDs[coarseLID] = myCoarseGID;
231 template<
class LocalOrdinal,
class GlobalOrdinal,
class Node>
234 const Array<LO> coarseNodeFineIndices,
235 GO& myGID, LO& myPID, LO& myLID)
const {
237 LO ni = -1, nj = -1, li = -1, lj = -1, lk = -1;
238 LO myRankGuess = myRankIndex;
240 if(iGhosted == 0 && this->ghostInterface[0]) {
242 }
else if((iGhosted == this->ghostedNodesPerDir[0] - 1) && this->ghostInterface[1]) {
245 if(jGhosted == 0 && this->ghostInterface[2]) {
247 }
else if((jGhosted == this->ghostedNodesPerDir[1] - 1) && this->ghostInterface[3]) {
250 if(kGhosted == 0 && this->ghostInterface[4]) {
251 myRankGuess -= pj*pi;
252 }
else if((kGhosted == this->ghostedNodesPerDir[2] - 1) && this->ghostInterface[5]) {
253 myRankGuess += pj*pi;
255 if(coarseNodeFineIndices[0] >= meshData[myRankGuess][3]
256 && coarseNodeFineIndices[0] <= meshData[myRankGuess][4]
257 && coarseNodeFineIndices[1] >= meshData[myRankGuess][5]
258 && coarseNodeFineIndices[1] <= meshData[myRankGuess][6]
259 && coarseNodeFineIndices[2] >= meshData[myRankGuess][7]
260 && coarseNodeFineIndices[2] <= meshData[myRankGuess][8]
261 && myRankGuess < numRanks - 1) {
262 myPID = meshData[myRankGuess][0];
263 ni = meshData[myRankGuess][4] - meshData[myRankGuess][3] + 1;
264 nj = meshData[myRankGuess][6] - meshData[myRankGuess][5] + 1;
265 li = coarseNodeFineIndices[0] - meshData[myRankGuess][3];
266 lj = coarseNodeFineIndices[1] - meshData[myRankGuess][5];
267 lk = coarseNodeFineIndices[2] - meshData[myRankGuess][7];
268 myLID = lk*nj*ni + lj*ni + li;
269 myGID = meshData[myRankGuess][9] + myLID;
273 auto nodeRank = std::find_if(myBlockStart, myBlockEnd,
274 [coarseNodeFineIndices](
const std::vector<GO>& vec){
275 if(coarseNodeFineIndices[0] >= vec[3]
276 && coarseNodeFineIndices[0] <= vec[4]
277 && coarseNodeFineIndices[1] >= vec[5]
278 && coarseNodeFineIndices[1] <= vec[6]
279 && coarseNodeFineIndices[2] >= vec[7]
280 && coarseNodeFineIndices[2] <= vec[8]) {
286 myPID = (*nodeRank)[0];
287 ni = (*nodeRank)[4] - (*nodeRank)[3] + 1;
288 nj = (*nodeRank)[6] - (*nodeRank)[5] + 1;
289 li = coarseNodeFineIndices[0] - (*nodeRank)[3];
290 lj = coarseNodeFineIndices[1] - (*nodeRank)[5];
291 lk = coarseNodeFineIndices[2] - (*nodeRank)[7];
292 myLID = lk*nj*ni + lj*ni + li;
293 myGID = (*nodeRank)[9] + myLID;
297 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
301 std::sort(meshData.begin(), meshData.end(),
302 [](
const std::vector<GO>& a,
const std::vector<GO>& b)->
bool {
306 }
else if(a[2] == b[2]) {
309 }
else if(a[7] == b[7]) {
312 }
else if(a[5] == b[5]) {
313 if(a[3] < b[3]) {
return true;}
320 numBlocks = meshData[numRanks - 1][2] + 1;
322 myBlockStart = std::lower_bound(meshData.begin(), meshData.end(), myBlock - 1,
323 [] (
const std::vector<GO>& vec,
const GO val)->
bool {
324 return (vec[2] < val) ? true :
false;
326 myBlockEnd = std::upper_bound(meshData.begin(), meshData.end(), myBlock,
327 [] (
const GO val,
const std::vector<GO>& vec)->
bool {
328 return (val < vec[2]) ? true :
false;
333 auto myKEnd = std::upper_bound(myBlockStart, myBlockEnd, (*myBlockStart)[3],
334 [] (
const GO val,
const std::vector<GO>& vec)->
bool {
335 return (val < vec[7]) ?
true :
false;
337 auto myJEnd = std::upper_bound(myBlockStart, myKEnd, (*myBlockStart)[3],
338 [] (
const GO val,
const std::vector<GO>& vec)->
bool {
339 return (val < vec[5]) ?
true :
false;
341 pi = std::distance(myBlockStart, myJEnd);
342 pj = std::distance(myBlockStart, myKEnd) / pi;
343 pk = std::distance(myBlockStart, myBlockEnd) / (pj*pi);
346 const int MyRank = myRank;
347 myRankIndex = std::distance(meshData.begin(),
348 std::find_if(myBlockStart, myBlockEnd,
349 [MyRank] (
const std::vector<GO>& vec)->
bool {
350 return (vec[0] == MyRank) ?
true :
false;
355 for(
int rankIndex = 0; rankIndex < numRanks; ++rankIndex) {
356 rankIndices[meshData[rankIndex][0]] = rankIndex;
360 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
363 Array<LO> rankOffset(3);
364 for(
int rank = 0; rank < numRanks; ++rank) {
365 coarseMeshData[rank].resize(10);
366 coarseMeshData[rank][0] = meshData[rank][0];
367 coarseMeshData[rank][1] = meshData[rank][1];
368 coarseMeshData[rank][2] = meshData[rank][2];
369 for(
int dim = 0; dim < 3; ++dim) {
370 coarseMeshData[rank][3 + 2*dim] = meshData[rank][3 + 2*dim] / this->coarseRate[dim];
371 if(meshData[rank][3 + 2*dim] % this->coarseRate[dim] > 0) {
372 ++coarseMeshData[rank][3 + 2*dim];
374 coarseMeshData[rank][3 + 2*dim + 1] = meshData[rank][3 + 2*dim + 1] / this->coarseRate[dim];
375 if(meshData[rank][3 + 2*dim + 1] == this->gFineNodesPerDir[dim] - 1 &&
376 meshData[rank][3 + 2*dim + 1] % this->coarseRate[dim] > 0) {
378 ++coarseMeshData[rank][3 + 2*dim + 1];
382 coarseMeshData[rank][9] = coarseMeshData[rank - 1][9]
383 + (coarseMeshData[rank - 1][8] - coarseMeshData[rank - 1][7] + 1)
384 * (coarseMeshData[rank - 1][6] - coarseMeshData[rank - 1][5] + 1)
385 * (coarseMeshData[rank - 1][4] - coarseMeshData[rank - 1][3] + 1);
390 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
394 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
399 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
403 k = myLID / this->lNumFineNodes10;
404 tmp = myLID % this->lNumFineNodes10;
405 j = tmp / this->lFineNodesPerDir[0];
406 i = tmp % this->lFineNodesPerDir[0];
409 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
413 k = myLID / this->lNumFineNodes10;
414 tmp = myLID % this->lNumFineNodes10;
415 j = tmp / this->lFineNodesPerDir[0];
416 i = tmp % this->lFineNodesPerDir[0];
418 k += this->offsets[2];
419 j += this->offsets[1];
420 i += this->offsets[0];
423 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
428 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
433 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
438 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
442 k = myLID / this->lNumCoarseNodes10;
443 tmp = myLID % this->lNumCoarseNodes10;
444 j = tmp / this->lCoarseNodesPerDir[0];
445 i = tmp % this->lCoarseNodesPerDir[0];
448 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
453 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
458 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
461 myLID = k*this->numGhostedNodes10 + j*this->ghostedNodesPerDir[0] + i;
464 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
469 const GO multiplier[3] = {1, this->lFineNodesPerDir[0], this->lNumFineNodes10};
470 const LO indices[3] = {i, j, k};
473 for(
int dim = 0; dim < 3; ++dim) {
474 if((indices[dim] == this->getLocalCoarseNodesInDir(dim) - 1) && this->meshEdge[2*dim + 1]) {
477 myLID += (this->getLocalFineNodesInDir(dim) - 1)*multiplier[dim];
479 myLID += (indices[dim]*this->getCoarseningRate(dim) + this->getCoarseNodeOffset(dim))
485 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
490 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
const bool coupled_
Flag for coupled vs uncoupled aggregation mode, if true aggregation is coupled.
void getGhostedNodeFineLID(const LO i, const LO j, const LO k, LO &myLID) const
void sortLocalLexicographicData()
std::vector< std::vector< GO > > getCoarseMeshData() const
void getFineNodeLID(const LO i, const LO j, const LO k, LO &myLID) const
int myRankIndex
local process index for record in meshData after sorting.
Array< GO > startIndices
lowest global tuple (i,j,k) of a node on the local process
void getCoarseNodeGID(const GO i, const GO j, const GO k, GO &myGID) const
void getCoarseNodeGlobalTuple(const GO myGID, GO &i, GO &j, GO &k) const
std::vector< std::vector< GO > > meshData
layout of indices accross all processes.
void getCoarseNodesData(const RCP< const Map > fineCoordinatesMap, Array< GO > &coarseNodeCoarseGIDs, Array< GO > &coarseNodeFineGIDs) const
void getCoarseNodeLID(const LO i, const LO j, const LO k, LO &myLID) const
void getFineNodeGhostedTuple(const LO myLID, LO &i, LO &j, LO &k) const
Namespace for MueLu classes and methods.
void getFineNodeLocalTuple(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 getCoarseNodeLocalTuple(const LO myLID, LO &i, LO &j, LO &k) const
int myBlock
local mesh block ID.
void getGhostedNodeCoarseLID(const LO i, const LO j, const LO k, LO &myLID) const
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.
const int numRanks
Number of ranks used to decompose the problem.
void computeGlobalCoarseParameters()
void getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO &myLID) const
void getFineNodeGID(const GO i, const GO j, const GO k, GO &myGID) const
void getCoarseNodeGhostedLID(const LO i, const LO j, const LO k, LO &myLID) const
LocalLexicographicIndexManager()=default
void computeCoarseLocalLexicographicData()
void computeMeshParameters()
void getGIDLocalLexicographic(const LO iGhosted, const LO jGhosted, const LO kGhosted, const Array< LO > coarseNodeFineIndices, GO &myGID, LO &myPID, LO &myLID) const
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.