MueLu  Version of the Day
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 
52 namespace 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, NumDimensions, interpolationOrder, GFineNodesPerDir, LFineNodesPerDir),
62  myRank(MyRank), numRanks(NumRanks) {
63 
64  // Allocate data based on user input
65  meshData.resize(numRanks);
67  coarseMeshData.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_) {
91  myBlock = meshData[myRank][2];
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>
117  Array<LO>& ghostedNodeCoarseLIDs, Array<int>& ghostedNodeCoarsePIDs, Array<GO>& ghostedNodeCoarseGIDs) const {
118 
119  // First we allocated memory for the outputs
120  ghostedNodeCoarseLIDs.resize(this->getNumLocalGhostedNodes());
121  ghostedNodeCoarsePIDs.resize(this->getNumLocalGhostedNodes());
122  ghostedNodeCoarseGIDs.resize(this->numGhostedNodes);
123 
124  // Now the tricky part starts, the coarse nodes / ghosted coarse nodes need to be imported.
125  // This requires finding what their GID on the fine mesh is. They need to be ordered
126  // lexicographically to allow for fast sweeps through the mesh.
127 
128  // We loop over all ghosted coarse nodes by increasing global lexicographic order
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;
141  }
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;
146  }
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;
151  }
152 
153  GO myGID = -1, myCoarseGID = -1;
154  LO myLID = -1, myPID = -1, myCoarseLID = -1;
155  getGIDLocalLexicographic(i, j, k, ghostedCoarseNodeFineIndices, myGID, myPID, myLID);
156 
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];
162  }
163  }
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];
173 
174  ghostedNodeCoarseLIDs[currentIndex] = myCoarseLID;
175  ghostedNodeCoarsePIDs[currentIndex] = myPID;
176  ghostedNodeCoarseGIDs[currentIndex] = myCoarseGID;
177 
178  if(myPID == myRank) {
179  lCoarseNodeCoarseGIDs[countCoarseNodes] = myCoarseGID;
180  ++countCoarseNodes;
181  }
182  }
183  }
184  }
185  }
186 
187  template<class LocalOrdinal, class GlobalOrdinal, class Node>
189  getCoarseNodesData(const RCP<const Map> fineCoordinatesMap,
190  Array<GO>& coarseNodeCoarseGIDs,
191  Array<GO>& coarseNodeFineGIDs) const {
192 
193  // Allocate sufficient storage space for outputs
194  coarseNodeCoarseGIDs.resize(this->getNumLocalCoarseNodes());
195  coarseNodeFineGIDs.resize(this->getNumLocalCoarseNodes());
196 
197  // Load all the GIDs on the fine mesh
198  ArrayView<const GO> fineNodeGIDs = fineCoordinatesMap->getNodeElementList();
199 
200  Array<GO> coarseStartIndices(3);
201  GO tmp;
202  for(int dim = 0; dim < 3; ++dim) {
203  coarseStartIndices[dim] = this->coarseMeshData[myRankIndex][2*dim + 3];
204  }
205 
206  // Extract the fine LIDs of the coarse nodes and store the corresponding GIDs
207  LO fineLID;
208  for(LO coarseLID = 0; coarseLID < this->getNumLocalCoarseNodes(); ++coarseLID) {
209  Array<LO> coarseIndices(3), fineIndices(3), gCoarseIndices(3);
210  this->getCoarseNodeLocalTuple(coarseLID,
211  coarseIndices[0],
212  coarseIndices[1],
213  coarseIndices[2]);
214  getCoarseNodeFineLID(coarseIndices[0],coarseIndices[1],coarseIndices[2],fineLID);
215  coarseNodeFineGIDs[coarseLID] = fineNodeGIDs[fineLID];
216 
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
224  + coarseIndices[0];
225  GO myCoarseGID = myCoarseLID + coarseMeshData[myRankIndex][9];
226  coarseNodeCoarseGIDs[coarseLID] = myCoarseGID;
227  }
228 
229  }
230 
231  template<class LocalOrdinal, class GlobalOrdinal, class Node>
233  getGIDLocalLexicographic(const LO iGhosted, const LO jGhosted, const LO kGhosted,
234  const Array<LO> coarseNodeFineIndices,
235  GO& myGID, LO& myPID, LO& myLID) const {
236 
237  LO ni = -1, nj = -1, li = -1, lj = -1, lk = -1;
238  LO myRankGuess = myRankIndex;
239  // We try to make a logical guess as to which PID owns the current coarse node
240  if(iGhosted == 0 && this->ghostInterface[0]) {
241  --myRankGuess;
242  } else if((iGhosted == this->ghostedNodesPerDir[0] - 1) && this->ghostInterface[1]) {
243  ++myRankGuess;
244  }
245  if(jGhosted == 0 && this->ghostInterface[2]) {
246  myRankGuess -= pi;
247  } else if((jGhosted == this->ghostedNodesPerDir[1] - 1) && this->ghostInterface[3]) {
248  myRankGuess += pi;
249  }
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;
254  }
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;
270  } else { // The guess failed, let us use the heavy artilery: std::find_if()
271  // It could be interesting to monitor how many times this branch of the code gets
272  // used as it is far more expensive than the above one...
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]) {
281  return true;
282  } else {
283  return false;
284  }
285  });
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;
294  }
295  }
296 
297  template <class LocalOrdinal, class GlobalOrdinal, class Node>
300 
301  std::sort(meshData.begin(), meshData.end(),
302  [](const std::vector<GO>& a, const std::vector<GO>& b)->bool {
303  // The below function sorts ranks by blockID, kmin, jmin and imin
304  if(a[2] < b[2]) {
305  return true;
306  } else if(a[2] == b[2]) {
307  if(a[7] < b[7]) {
308  return true;
309  } else if(a[7] == b[7]) {
310  if(a[5] < b[5]) {
311  return true;
312  } else if(a[5] == b[5]) {
313  if(a[3] < b[3]) {return true;}
314  }
315  }
316  }
317  return false;
318  });
319 
320  numBlocks = meshData[numRanks - 1][2] + 1;
321  // Find the range of the current block
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;
325  });
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;
329  });
330  // Assuming that i,j,k and ranges are split in pi, pj and pk processors
331  // we search for these numbers as they will allow us to find quickly the PID of processors
332  // owning ghost nodes.
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;
336  });
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;
340  });
341  pi = std::distance(myBlockStart, myJEnd);
342  pj = std::distance(myBlockStart, myKEnd) / pi;
343  pk = std::distance(myBlockStart, myBlockEnd) / (pj*pi);
344 
345  // We also look for the index of the local rank in the current block.
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;
351  })
352  );
353  // We also construct a mapping of rank to rankIndex in the meshData vector,
354  // this will allow us to access data quickly later on.
355  for(int rankIndex = 0; rankIndex < numRanks; ++rankIndex) {
356  rankIndices[meshData[rankIndex][0]] = rankIndex;
357  }
358  }
359 
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];
373  }
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) {
377  //this->endRate[dim] < this->coarseRate[dim]) {
378  ++coarseMeshData[rank][3 + 2*dim + 1];
379  }
380  }
381  if(rank > 0) {
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);
386  }
387  }
388  }
389 
390  template <class LocalOrdinal, class GlobalOrdinal, class Node>
391  std::vector<std::vector<GlobalOrdinal> > LocalLexicographicIndexManager<LocalOrdinal, GlobalOrdinal, Node>::
392  getCoarseMeshData() const {return coarseMeshData;}
393 
394  template <class LocalOrdinal, class GlobalOrdinal, class Node>
396  getFineNodeGlobalTuple(const GO myGID, GO& i, GO& j, GO& k) const {
397  }
398 
399  template <class LocalOrdinal, class GlobalOrdinal, class Node>
401  getFineNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
402  LO tmp;
403  k = myLID / this->lNumFineNodes10;
404  tmp = myLID % this->lNumFineNodes10;
405  j = tmp / this->lFineNodesPerDir[0];
406  i = tmp % this->lFineNodesPerDir[0];
407  }
408 
409  template <class LocalOrdinal, class GlobalOrdinal, class Node>
411  getFineNodeGhostedTuple(const LO myLID, LO& i, LO& j, LO& k) const {
412  LO tmp;
413  k = myLID / this->lNumFineNodes10;
414  tmp = myLID % this->lNumFineNodes10;
415  j = tmp / this->lFineNodesPerDir[0];
416  i = tmp % this->lFineNodesPerDir[0];
417 
418  k += this->offsets[2];
419  j += this->offsets[1];
420  i += this->offsets[0];
421  }
422 
423  template <class LocalOrdinal, class GlobalOrdinal, class Node>
425  getFineNodeGID(const GO i, const GO j, const GO k, GO& myGID) const {
426  }
427 
428  template <class LocalOrdinal, class GlobalOrdinal, class Node>
430  getFineNodeLID(const LO i, const LO j, const LO k, LO& myLID) const {
431  }
432 
433  template <class LocalOrdinal, class GlobalOrdinal, class Node>
435  getCoarseNodeGlobalTuple(const GO myGID, GO& i, GO& j, GO& k) const {
436  }
437 
438  template <class LocalOrdinal, class GlobalOrdinal, class Node>
440  getCoarseNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
441  LO tmp;
442  k = myLID / this->lNumCoarseNodes10;
443  tmp = myLID % this->lNumCoarseNodes10;
444  j = tmp / this->lCoarseNodesPerDir[0];
445  i = tmp % this->lCoarseNodesPerDir[0];
446  }
447 
448  template <class LocalOrdinal, class GlobalOrdinal, class Node>
450  getCoarseNodeGID(const GO i, const GO j, const GO k, GO& myGID) const {
451  }
452 
453  template <class LocalOrdinal, class GlobalOrdinal, class Node>
455  getCoarseNodeLID(const LO i, const LO j, const LO k, LO& myLID) const {
456  }
457 
458  template <class LocalOrdinal, class GlobalOrdinal, class Node>
460  getCoarseNodeGhostedLID(const LO i, const LO j, const LO k, LO& myLID) const {
461  myLID = k*this->numGhostedNodes10 + j*this->ghostedNodesPerDir[0] + i;
462  }
463 
464  template <class LocalOrdinal, class GlobalOrdinal, class Node>
466  getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO& myLID) const {
467  // Assumptions: (i,j,k) is a tuple on the coarse mesh
468  // myLID is the corresponding local ID on the fine mesh
469  const GO multiplier[3] = {1, this->lFineNodesPerDir[0], this->lNumFineNodes10};
470  const LO indices[3] = {i, j, k};
471 
472  myLID = 0;
473  for(int dim = 0; dim < 3; ++dim) {
474  if((indices[dim] == this->getLocalCoarseNodesInDir(dim) - 1) && this->meshEdge[2*dim + 1]) {
475  // We are dealing with the last node on the mesh in direction dim
476  // so we can simply use the number of nodes on the fine mesh in that direction
477  myLID += (this->getLocalFineNodesInDir(dim) - 1)*multiplier[dim];
478  } else {
479  myLID += (indices[dim]*this->getCoarseningRate(dim) + this->getCoarseNodeOffset(dim))
480  *multiplier[dim];
481  }
482  }
483  }
484 
485  template <class LocalOrdinal, class GlobalOrdinal, class Node>
487  getGhostedNodeFineLID(const LO i, const LO j, const LO k, LO& myLID) const {
488  }
489 
490  template <class LocalOrdinal, class GlobalOrdinal, class Node>
492  getGhostedNodeCoarseLID(const LO i, const LO j, const LO k, LO& myLID) const {
493  }
494 
495 } //namespace MueLu
496 
497 #endif /* MUELU_LOCALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_ */
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
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
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
size_type size() 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 getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO &myLID) const
void resize(size_type new_size, const value_type &x=value_type())
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
void getGIDLocalLexicographic(const LO iGhosted, const LO jGhosted, const LO kGhosted, const Array< LO > coarseNodeFineIndices, GO &myGID, LO &myPID, LO &myLID) const
Container class for mesh layout and indices calculation.
std::vector< std::vector< GO > > coarseMeshData
layout of indices accross all processes after coarsening.