MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_LocalLexicographicIndexManager_def.hpp
Go to the documentation of this file.
1// @HEADER
2//
3// ***********************************************************************
4//
5// MueLu: A package for multigrid based preconditioning
6// Copyright 2012 Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact
39// Jonathan Hu (jhu@sandia.gov)
40// Ray Tuminaro (rstumin@sandia.gov)
41// Luc Berger-Vergoat (lberge@sandia.gov)
42//
43// ***********************************************************************
44//
45// @HEADER
46#ifndef MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
47#define MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
48
50#include <Xpetra_MapFactory.hpp>
51
52namespace MueLu {
53
54 template <class LocalOrdinal, class GlobalOrdinal, class Node>
56 LocalLexicographicIndexManager(const RCP<const Teuchos::Comm<int> > comm, const bool coupled,
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, false, NumDimensions, interpolationOrder, GFineNodesPerDir, LFineNodesPerDir),
62 myRank(MyRank), numRanks(NumRanks) {
63
64 // Allocate data based on user input
65 meshData.resize(numRanks);
66 rankIndices.resize(numRanks);
68
69 // Load coarse rate, being careful about formating
70 for(int dim = 0; dim < 3; ++dim) {
71 if(dim < this->numDimensions) {
72 if(CoarseRate.size() == 1) {
73 this->coarseRate[dim] = CoarseRate[0];
74 } else if(CoarseRate.size() == this->numDimensions) {
75 this->coarseRate[dim] = CoarseRate[dim];
76 }
77 } else {
78 this->coarseRate[dim] = 1;
79 }
80 }
81
82 // Load meshData for local lexicographic case
83 for(int rank = 0; rank < numRanks; ++rank) {
84 meshData[rank].resize(10);
85 for(int entry = 0; entry < 10; ++entry) {
86 meshData[rank][entry] = MeshData[10*rank + entry];
87 }
88 }
89
90 if(this->coupled_) {
93 }
94
95 // Start simple parameter calculation
97 for(int dim = 0; dim < 3; ++dim) {
98 this->startIndices[dim] = meshData[myRankIndex][2*dim + 3];
99 this->startIndices[dim + 3] = meshData[myRankIndex][2*dim + 4];
100 }
101
102 this->computeMeshParameters();
105 } // Constructor
106
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];
112 }
113
114 template <class LocalOrdinal, class GlobalOrdinal, class Node>
116 getGhostedNodesData(const RCP<const Map>/* fineMap */,
117 Array<LO>& ghostedNodeCoarseLIDs,
118 Array<int>& ghostedNodeCoarsePIDs,
119 Array<GO>& ghostedNodeCoarseGIDs) const {
120
121 // First we allocated memory for the outputs
122 ghostedNodeCoarseLIDs.resize(this->getNumLocalGhostedNodes());
123 ghostedNodeCoarsePIDs.resize(this->getNumLocalGhostedNodes());
124 ghostedNodeCoarseGIDs.resize(this->numGhostedNodes);
125
126 // Now the tricky part starts, the coarse nodes / ghosted coarse nodes need to be imported.
127 // This requires finding what their GID on the fine mesh is. They need to be ordered
128 // lexicographically to allow for fast sweeps through the mesh.
129
130 // We loop over all ghosted coarse nodes by increasing global lexicographic order
131 Array<LO> ghostedCoarseNodeCoarseIndices(3), ghostedCoarseNodeFineIndices(3);
132 Array<LO> lCoarseNodeCoarseIndices(3);
133 Array<GO> lCoarseNodeCoarseGIDs(this->lNumCoarseNodes);
134 LO currentIndex = -1, countCoarseNodes = 0;
135 for(int k = 0; k < this->ghostedNodesPerDir[2]; ++k) {
136 for(int j = 0; j < this->ghostedNodesPerDir[1]; ++j) {
137 for(int i = 0; i < this->ghostedNodesPerDir[0]; ++i) {
138 currentIndex = k*this->numGhostedNodes10 + j*this->ghostedNodesPerDir[0] + i;
139 ghostedCoarseNodeCoarseIndices[0] = this->startGhostedCoarseNode[0] + i;
140 ghostedCoarseNodeFineIndices[0] = ghostedCoarseNodeCoarseIndices[0]*this->coarseRate[0];
141 if(ghostedCoarseNodeFineIndices[0] > this->gFineNodesPerDir[0] - 1) {
142 ghostedCoarseNodeFineIndices[0] = this->gFineNodesPerDir[0] - 1;
143 }
144 ghostedCoarseNodeCoarseIndices[1] = this->startGhostedCoarseNode[1] + j;
145 ghostedCoarseNodeFineIndices[1] = ghostedCoarseNodeCoarseIndices[1]*this->coarseRate[1];
146 if(ghostedCoarseNodeFineIndices[1] > this->gFineNodesPerDir[1] - 1) {
147 ghostedCoarseNodeFineIndices[1] = this->gFineNodesPerDir[1] - 1;
148 }
149 ghostedCoarseNodeCoarseIndices[2] = this->startGhostedCoarseNode[2] + k;
150 ghostedCoarseNodeFineIndices[2] = ghostedCoarseNodeCoarseIndices[2]*this->coarseRate[2];
151 if(ghostedCoarseNodeFineIndices[2] > this->gFineNodesPerDir[2] - 1) {
152 ghostedCoarseNodeFineIndices[2] = this->gFineNodesPerDir[2] - 1;
153 }
154
155 GO myGID = -1, myCoarseGID = -1;
156 LO myLID = -1, myPID = -1, myCoarseLID = -1;
157 getGIDLocalLexicographic(i, j, k, ghostedCoarseNodeFineIndices, myGID, myPID, myLID);
158
159 int rankIndex = rankIndices[myPID];
160 for(int dim = 0; dim < 3; ++dim) {
161 if(dim < this->numDimensions) {
162 lCoarseNodeCoarseIndices[dim] = ghostedCoarseNodeCoarseIndices[dim]
163 - coarseMeshData[rankIndex][3 + 2*dim];
164 }
165 }
166 LO myRankIndexCoarseNodesInDir0 = coarseMeshData[rankIndex][4]
167 - coarseMeshData[rankIndex][3] + 1;
168 LO myRankIndexCoarseNodes10 = (coarseMeshData[rankIndex][6]
169 - coarseMeshData[rankIndex][5] + 1)
170 *myRankIndexCoarseNodesInDir0;
171 myCoarseLID = lCoarseNodeCoarseIndices[2]*myRankIndexCoarseNodes10
172 + lCoarseNodeCoarseIndices[1]*myRankIndexCoarseNodesInDir0
173 + lCoarseNodeCoarseIndices[0];
174 myCoarseGID = myCoarseLID + coarseMeshData[rankIndex][9];
175
176 ghostedNodeCoarseLIDs[currentIndex] = myCoarseLID;
177 ghostedNodeCoarsePIDs[currentIndex] = myPID;
178 ghostedNodeCoarseGIDs[currentIndex] = myCoarseGID;
179
180 if(myPID == myRank) {
181 lCoarseNodeCoarseGIDs[countCoarseNodes] = myCoarseGID;
182 ++countCoarseNodes;
183 }
184 }
185 }
186 }
187 }
188
189 template<class LocalOrdinal, class GlobalOrdinal, class Node>
191 getCoarseNodesData(const RCP<const Map> fineCoordinatesMap,
192 Array<GO>& coarseNodeCoarseGIDs,
193 Array<GO>& coarseNodeFineGIDs) const {
194
195 // Allocate sufficient storage space for outputs
196 coarseNodeCoarseGIDs.resize(this->getNumLocalCoarseNodes());
197 coarseNodeFineGIDs.resize(this->getNumLocalCoarseNodes());
198
199 // Load all the GIDs on the fine mesh
200 ArrayView<const GO> fineNodeGIDs = fineCoordinatesMap->getLocalElementList();
201
202 Array<GO> coarseStartIndices(3);
203 for(int dim = 0; dim < 3; ++dim) {
204 coarseStartIndices[dim] = this->coarseMeshData[myRankIndex][2*dim + 3];
205 }
206
207 // Extract the fine LIDs of the coarse nodes and store the corresponding GIDs
208 LO fineLID;
209 for(LO coarseLID = 0; coarseLID < this->getNumLocalCoarseNodes(); ++coarseLID) {
210 Array<LO> coarseIndices(3), fineIndices(3), gCoarseIndices(3);
211 this->getCoarseNodeLocalTuple(coarseLID,
212 coarseIndices[0],
213 coarseIndices[1],
214 coarseIndices[2]);
215 getCoarseNodeFineLID(coarseIndices[0],coarseIndices[1],coarseIndices[2],fineLID);
216 coarseNodeFineGIDs[coarseLID] = fineNodeGIDs[fineLID];
217
218 LO myRankIndexCoarseNodesInDir0 = coarseMeshData[myRankIndex][4]
219 - coarseMeshData[myRankIndex][3] + 1;
220 LO myRankIndexCoarseNodes10 = (coarseMeshData[myRankIndex][6]
221 - coarseMeshData[myRankIndex][5] + 1)
222 *myRankIndexCoarseNodesInDir0;
223 LO myCoarseLID = coarseIndices[2]*myRankIndexCoarseNodes10
224 + coarseIndices[1]*myRankIndexCoarseNodesInDir0
225 + coarseIndices[0];
226 GO myCoarseGID = myCoarseLID + coarseMeshData[myRankIndex][9];
227 coarseNodeCoarseGIDs[coarseLID] = myCoarseGID;
228 }
229
230 }
231
232 template<class LocalOrdinal, class GlobalOrdinal, class Node>
234 getGIDLocalLexicographic(const LO iGhosted, const LO jGhosted, const LO kGhosted,
235 const Array<LO> coarseNodeFineIndices,
236 GO& myGID, LO& myPID, LO& myLID) const {
237
238 LO ni = -1, nj = -1, li = -1, lj = -1, lk = -1;
239 LO myRankGuess = myRankIndex;
240 // We try to make a logical guess as to which PID owns the current coarse node
241 if(iGhosted == 0 && this->ghostInterface[0]) {
242 --myRankGuess;
243 } else if((iGhosted == this->ghostedNodesPerDir[0] - 1) && this->ghostInterface[1]) {
244 ++myRankGuess;
245 }
246 if(jGhosted == 0 && this->ghostInterface[2]) {
247 myRankGuess -= pi;
248 } else if((jGhosted == this->ghostedNodesPerDir[1] - 1) && this->ghostInterface[3]) {
249 myRankGuess += pi;
250 }
251 if(kGhosted == 0 && this->ghostInterface[4]) {
252 myRankGuess -= pj*pi;
253 } else if((kGhosted == this->ghostedNodesPerDir[2] - 1) && this->ghostInterface[5]) {
254 myRankGuess += pj*pi;
255 }
256 if(coarseNodeFineIndices[0] >= meshData[myRankGuess][3]
257 && coarseNodeFineIndices[0] <= meshData[myRankGuess][4]
258 && coarseNodeFineIndices[1] >= meshData[myRankGuess][5]
259 && coarseNodeFineIndices[1] <= meshData[myRankGuess][6]
260 && coarseNodeFineIndices[2] >= meshData[myRankGuess][7]
261 && coarseNodeFineIndices[2] <= meshData[myRankGuess][8]
262 && myRankGuess < numRanks - 1) {
263 myPID = meshData[myRankGuess][0];
264 ni = meshData[myRankGuess][4] - meshData[myRankGuess][3] + 1;
265 nj = meshData[myRankGuess][6] - meshData[myRankGuess][5] + 1;
266 li = coarseNodeFineIndices[0] - meshData[myRankGuess][3];
267 lj = coarseNodeFineIndices[1] - meshData[myRankGuess][5];
268 lk = coarseNodeFineIndices[2] - meshData[myRankGuess][7];
269 myLID = lk*nj*ni + lj*ni + li;
270 myGID = meshData[myRankGuess][9] + myLID;
271 } else { // The guess failed, let us use the heavy artilery: std::find_if()
272 // It could be interesting to monitor how many times this branch of the code gets
273 // used as it is far more expensive than the above one...
274 auto nodeRank = std::find_if(myBlockStart, myBlockEnd,
275 [coarseNodeFineIndices](const std::vector<GO>& vec){
276 if(coarseNodeFineIndices[0] >= vec[3]
277 && coarseNodeFineIndices[0] <= vec[4]
278 && coarseNodeFineIndices[1] >= vec[5]
279 && coarseNodeFineIndices[1] <= vec[6]
280 && coarseNodeFineIndices[2] >= vec[7]
281 && coarseNodeFineIndices[2] <= vec[8]) {
282 return true;
283 } else {
284 return false;
285 }
286 });
287 myPID = (*nodeRank)[0];
288 ni = (*nodeRank)[4] - (*nodeRank)[3] + 1;
289 nj = (*nodeRank)[6] - (*nodeRank)[5] + 1;
290 li = coarseNodeFineIndices[0] - (*nodeRank)[3];
291 lj = coarseNodeFineIndices[1] - (*nodeRank)[5];
292 lk = coarseNodeFineIndices[2] - (*nodeRank)[7];
293 myLID = lk*nj*ni + lj*ni + li;
294 myGID = (*nodeRank)[9] + myLID;
295 }
296 }
297
298 template <class LocalOrdinal, class GlobalOrdinal, class Node>
301
302 std::sort(meshData.begin(), meshData.end(),
303 [](const std::vector<GO>& a, const std::vector<GO>& b)->bool {
304 // The below function sorts ranks by blockID, kmin, jmin and imin
305 if(a[2] < b[2]) {
306 return true;
307 } else if(a[2] == b[2]) {
308 if(a[7] < b[7]) {
309 return true;
310 } else if(a[7] == b[7]) {
311 if(a[5] < b[5]) {
312 return true;
313 } else if(a[5] == b[5]) {
314 if(a[3] < b[3]) {return true;}
315 }
316 }
317 }
318 return false;
319 });
320
321 numBlocks = meshData[numRanks - 1][2] + 1;
322 // Find the range of the current block
323 myBlockStart = std::lower_bound(meshData.begin(), meshData.end(), myBlock - 1,
324 [] (const std::vector<GO>& vec, const GO val)->bool {
325 return (vec[2] < val) ? true : false;
326 });
327 myBlockEnd = std::upper_bound(meshData.begin(), meshData.end(), myBlock,
328 [] (const GO val, const std::vector<GO>& vec)->bool {
329 return (val < vec[2]) ? true : false;
330 });
331 // Assuming that i,j,k and ranges are split in pi, pj and pk processors
332 // we search for these numbers as they will allow us to find quickly the PID of processors
333 // owning ghost nodes.
334 auto myKEnd = std::upper_bound(myBlockStart, myBlockEnd, (*myBlockStart)[3],
335 [] (const GO val, const std::vector<GO>& vec)->bool {
336 return (val < vec[7]) ? true : false;
337 });
338 auto myJEnd = std::upper_bound(myBlockStart, myKEnd, (*myBlockStart)[3],
339 [] (const GO val, const std::vector<GO>& vec)->bool {
340 return (val < vec[5]) ? true : false;
341 });
342 pi = std::distance(myBlockStart, myJEnd);
343 pj = std::distance(myBlockStart, myKEnd) / pi;
344 pk = std::distance(myBlockStart, myBlockEnd) / (pj*pi);
345
346 // We also look for the index of the local rank in the current block.
347 const int MyRank = myRank;
348 myRankIndex = std::distance(meshData.begin(),
349 std::find_if(myBlockStart, myBlockEnd,
350 [MyRank] (const std::vector<GO>& vec)->bool {
351 return (vec[0] == MyRank) ? true : false;
352 })
353 );
354 // We also construct a mapping of rank to rankIndex in the meshData vector,
355 // this will allow us to access data quickly later on.
356 for(int rankIndex = 0; rankIndex < numRanks; ++rankIndex) {
357 rankIndices[meshData[rankIndex][0]] = rankIndex;
358 }
359 }
360
361 template <class LocalOrdinal, class GlobalOrdinal, class Node>
364 Array<LO> rankOffset(3);
365 for(int rank = 0; rank < numRanks; ++rank) {
366 coarseMeshData[rank].resize(10);
367 coarseMeshData[rank][0] = meshData[rank][0];
368 coarseMeshData[rank][1] = meshData[rank][1];
369 coarseMeshData[rank][2] = meshData[rank][2];
370 for(int dim = 0; dim < 3; ++dim) {
371 coarseMeshData[rank][3 + 2*dim] = meshData[rank][3 + 2*dim] / this->coarseRate[dim];
372 if(meshData[rank][3 + 2*dim] % this->coarseRate[dim] > 0) {
373 ++coarseMeshData[rank][3 + 2*dim];
374 }
375 coarseMeshData[rank][3 + 2*dim + 1] = meshData[rank][3 + 2*dim + 1] / this->coarseRate[dim];
376 if(meshData[rank][3 + 2*dim + 1] == this->gFineNodesPerDir[dim] - 1 &&
377 meshData[rank][3 + 2*dim + 1] % this->coarseRate[dim] > 0) {
378 //this->endRate[dim] < this->coarseRate[dim]) {
379 ++coarseMeshData[rank][3 + 2*dim + 1];
380 }
381 }
382 if(rank > 0) {
383 coarseMeshData[rank][9] = coarseMeshData[rank - 1][9]
384 + (coarseMeshData[rank - 1][8] - coarseMeshData[rank - 1][7] + 1)
385 * (coarseMeshData[rank - 1][6] - coarseMeshData[rank - 1][5] + 1)
386 * (coarseMeshData[rank - 1][4] - coarseMeshData[rank - 1][3] + 1);
387 }
388 }
389 }
390
391 template <class LocalOrdinal, class GlobalOrdinal, class Node>
393 getCoarseMeshData() const {return coarseMeshData;}
394
395 template <class LocalOrdinal, class GlobalOrdinal, class Node>
397 getFineNodeGlobalTuple(const GO /* myGID */, GO& /* i */, GO& /* j */, GO& /* k */) const {
398 }
399
400 template <class LocalOrdinal, class GlobalOrdinal, class Node>
402 getFineNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
403 LO tmp;
404 k = myLID / this->lNumFineNodes10;
405 tmp = myLID % this->lNumFineNodes10;
406 j = tmp / this->lFineNodesPerDir[0];
407 i = tmp % this->lFineNodesPerDir[0];
408 }
409
410 template <class LocalOrdinal, class GlobalOrdinal, class Node>
412 getFineNodeGhostedTuple(const LO myLID, LO& i, LO& j, LO& k) const {
413 LO tmp;
414 k = myLID / this->lNumFineNodes10;
415 tmp = myLID % this->lNumFineNodes10;
416 j = tmp / this->lFineNodesPerDir[0];
417 i = tmp % this->lFineNodesPerDir[0];
418
419 k += this->offsets[2];
420 j += this->offsets[1];
421 i += this->offsets[0];
422 }
423
424 template <class LocalOrdinal, class GlobalOrdinal, class Node>
426 getFineNodeGID(const GO /* i */, const GO /* j */, const GO /* k */, GO& /* myGID */) const {
427 }
428
429 template <class LocalOrdinal, class GlobalOrdinal, class Node>
431 getFineNodeLID(const LO /* i */, const LO /* j */, const LO /* k */, LO& /* myLID */) const {
432 }
433
434 template <class LocalOrdinal, class GlobalOrdinal, class Node>
436 getCoarseNodeGlobalTuple(const GO /* myGID */, GO& /* i */, GO& /* j */, GO& /* k */) const {
437 }
438
439 template <class LocalOrdinal, class GlobalOrdinal, class Node>
441 getCoarseNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
442 LO tmp;
443 k = myLID / this->lNumCoarseNodes10;
444 tmp = myLID % this->lNumCoarseNodes10;
445 j = tmp / this->lCoarseNodesPerDir[0];
446 i = tmp % this->lCoarseNodesPerDir[0];
447 }
448
449 template <class LocalOrdinal, class GlobalOrdinal, class Node>
451 getCoarseNodeGID(const GO /* i */, const GO /* j */, const GO /* k */, GO& /* myGID */) const {
452 }
453
454 template <class LocalOrdinal, class GlobalOrdinal, class Node>
456 getCoarseNodeLID(const LO /* i */, const LO /* j */, const LO /* k */, LO& /* myLID */) const {
457 }
458
459 template <class LocalOrdinal, class GlobalOrdinal, class Node>
461 getCoarseNodeGhostedLID(const LO i, const LO j, const LO k, LO& myLID) const {
462 myLID = k*this->numGhostedNodes10 + j*this->ghostedNodesPerDir[0] + i;
463 }
464
465 template <class LocalOrdinal, class GlobalOrdinal, class Node>
467 getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO& myLID) const {
468 // Assumptions: (i,j,k) is a tuple on the coarse mesh
469 // myLID is the corresponding local ID on the fine mesh
470 const LO multiplier[3] = {1, this->lFineNodesPerDir[0], this->lNumFineNodes10};
471 const LO indices[3] = {i, j, k};
472
473 myLID = 0;
474 for(int dim = 0; dim < 3; ++dim) {
475 if((indices[dim] == this->getLocalCoarseNodesInDir(dim) - 1) && this->meshEdge[2*dim + 1]) {
476 // We are dealing with the last node on the mesh in direction dim
477 // so we can simply use the number of nodes on the fine mesh in that direction
478 myLID += (this->getLocalFineNodesInDir(dim) - 1)*multiplier[dim];
479 } else {
480 myLID += (indices[dim]*this->getCoarseningRate(dim) + this->getCoarseNodeOffset(dim))
481 *multiplier[dim];
482 }
483 }
484 }
485
486 template <class LocalOrdinal, class GlobalOrdinal, class Node>
488 getGhostedNodeFineLID(const LO /* i */, const LO /* j */, const LO /* k */, LO& /* myLID */) const {
489 }
490
491 template <class LocalOrdinal, class GlobalOrdinal, class Node>
493 getGhostedNodeCoarseLID(const LO /* i */, const LO /* j */, const LO /* k */, LO& /* myLID */) const {
494 }
495
496} //namespace MueLu
497
498#endif /* MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_ */
Container class for mesh layout and indices calculation.
const bool coupled_
Flag for coupled vs uncoupled aggregation mode, if true aggregation is coupled.
Array< GO > startIndices
lowest global tuple (i,j,k) of a node on the local process
Array< int > coarseRate
coarsening rate in each direction
const int numDimensions
Number of spacial dimensions in the problem.
void getGhostedNodesData(const RCP< const Map > fineMap, Array< LO > &ghostedNodeCoarseLIDs, Array< int > &ghostedNodeCoarsePIDs, Array< GO > &ghostedNodeCoarseGIDs) const
const int numRanks
Number of ranks used to decompose the problem.
int myRankIndex
local process index for record in meshData after sorting.
void getGIDLocalLexicographic(const LO iGhosted, const LO jGhosted, const LO kGhosted, const Array< LO > coarseNodeFineIndices, GO &myGID, LO &myPID, LO &myLID) const
std::vector< std::vector< GO > > meshData
layout of indices accross all processes.
std::vector< std::vector< GO > > coarseMeshData
layout of indices accross all processes after coarsening.
Array< int > rankIndices
mapping between rank ID and reordered rank ID.
void getCoarseNodesData(const RCP< const Map > fineCoordinatesMap, Array< GO > &coarseNodeCoarseGIDs, Array< GO > &coarseNodeFineGIDs) const
Namespace for MueLu classes and methods.