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, 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);
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>
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->getNodeElementList();
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>
392  std::vector<std::vector<GlobalOrdinal> > LocalLexicographicIndexManager<LocalOrdinal, GlobalOrdinal, 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_ */
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
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 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.