MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_GlobalLexicographicIndexManager_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef MUELU_GLOBALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
11 #define MUELU_GLOBALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
12 
14 #include <Xpetra_MapFactory.hpp>
15 
16 namespace MueLu {
17 
18 template <class LocalOrdinal, class GlobalOrdinal, class Node>
20  GlobalLexicographicIndexManager(const RCP<const Teuchos::Comm<int> > comm, const bool coupled,
21  const int NumDimensions, const int interpolationOrder,
22  const Array<GO> GFineNodesPerDir,
23  const Array<LO> LFineNodesPerDir, const Array<LO> CoarseRate,
24  const GO MinGlobalIndex)
25  : IndexManager(comm, coupled, false, NumDimensions, interpolationOrder, GFineNodesPerDir, LFineNodesPerDir) {
26  // Load coarse rate, being careful about formating.
27  for (int dim = 0; dim < 3; ++dim) {
28  if (dim < this->numDimensions) {
29  if (CoarseRate.size() == 1) {
30  this->coarseRate[dim] = CoarseRate[0];
31  } else if (CoarseRate.size() == this->numDimensions) {
32  this->coarseRate[dim] = CoarseRate[dim];
33  }
34  } else {
35  this->coarseRate[dim] = 1;
36  }
37  }
38 
39  {
40  GO tmp = 0;
41  this->startIndices[2] = MinGlobalIndex / (this->gFineNodesPerDir[1] * this->gFineNodesPerDir[0]);
42  tmp = MinGlobalIndex % (this->gFineNodesPerDir[1] * this->gFineNodesPerDir[0]);
43  this->startIndices[1] = tmp / this->gFineNodesPerDir[0];
44  this->startIndices[0] = tmp % this->gFineNodesPerDir[0];
45 
46  for (int dim = 0; dim < 3; ++dim) {
47  this->startIndices[dim + 3] = this->startIndices[dim] + this->lFineNodesPerDir[dim] - 1;
48  }
49  }
50 
51  this->computeMeshParameters();
53 }
54 
55 template <class LocalOrdinal, class GlobalOrdinal, class Node>
58  this->gNumCoarseNodes10 = this->gCoarseNodesPerDir[0] * this->gCoarseNodesPerDir[1];
59  this->gNumCoarseNodes = this->gNumCoarseNodes10 * this->gCoarseNodesPerDir[2];
60 }
61 
62 template <class LocalOrdinal, class GlobalOrdinal, class Node>
65  Array<LO>& ghostedNodeCoarseLIDs, Array<int>& ghostedNodeCoarsePIDs, Array<GO>& ghostedNodeCoarseGIDs) const {
66  ghostedNodeCoarseLIDs.resize(this->getNumLocalGhostedNodes());
67  ghostedNodeCoarsePIDs.resize(this->getNumLocalGhostedNodes());
68  ghostedNodeCoarseGIDs.resize(this->numGhostedNodes);
69 
70  // Find the GIDs, LIDs and PIDs of the coarse points on the fine mesh and coarse
71  // mesh as this data will be used to fill vertex2AggId and procWinner vectors.
72  Array<GO> lCoarseNodeCoarseGIDs(this->lNumCoarseNodes),
73  lCoarseNodeFineGIDs(this->lNumCoarseNodes);
74  Array<GO> ghostedCoarseNodeFineGIDs(this->numGhostedNodes);
75  Array<LO> ghostedCoarseNodeCoarseIndices(3), ghostedCoarseNodeFineIndices(3), ijk(3);
76  LO currentIndex = -1, currentCoarseIndex = -1;
77  for (ijk[2] = 0; ijk[2] < this->ghostedNodesPerDir[2]; ++ijk[2]) {
78  for (ijk[1] = 0; ijk[1] < this->ghostedNodesPerDir[1]; ++ijk[1]) {
79  for (ijk[0] = 0; ijk[0] < this->ghostedNodesPerDir[0]; ++ijk[0]) {
80  currentIndex = ijk[2] * this->numGhostedNodes10 + ijk[1] * this->ghostedNodesPerDir[0] + ijk[0];
81  ghostedCoarseNodeCoarseIndices[0] = this->startGhostedCoarseNode[0] + ijk[0];
82  ghostedCoarseNodeCoarseIndices[1] = this->startGhostedCoarseNode[1] + ijk[1];
83  ghostedCoarseNodeCoarseIndices[2] = this->startGhostedCoarseNode[2] + ijk[2];
84  GO myCoarseGID = ghostedCoarseNodeCoarseIndices[0] + ghostedCoarseNodeCoarseIndices[1] * this->gCoarseNodesPerDir[0] + ghostedCoarseNodeCoarseIndices[2] * this->gNumCoarseNodes10;
85  ghostedNodeCoarseGIDs[currentIndex] = myCoarseGID;
86  GO myGID = 0, factor[3] = {};
87  factor[2] = this->gNumFineNodes10;
88  factor[1] = this->gFineNodesPerDir[0];
89  factor[0] = 1;
90  for (int dim = 0; dim < 3; ++dim) {
91  if (dim < this->numDimensions) {
92  if (this->startIndices[dim] - this->offsets[dim] + ijk[dim] * this->coarseRate[dim] < this->gFineNodesPerDir[dim] - 1) {
93  myGID += (this->startIndices[dim] - this->offsets[dim] + ijk[dim] * this->coarseRate[dim]) * factor[dim];
94  } else {
95  myGID += (this->startIndices[dim] - this->offsets[dim] + (ijk[dim] - 1) * this->coarseRate[dim] + this->endRate[dim]) * factor[dim];
96  }
97  }
98  }
99  // lbv 02-08-2018:
100  // This check is simplistic and should be replaced by a condition that checks
101  // if the local tuple of the current index is wihin the range of local nodes
102  // or not in the range of ghosted nodes.
103  if ((!this->ghostInterface[0] || ijk[0] != 0) &&
104  (!this->ghostInterface[2] || ijk[1] != 0) &&
105  (!this->ghostInterface[4] || ijk[2] != 0) &&
106  (!this->ghostInterface[1] || ijk[0] != this->ghostedNodesPerDir[0] - 1) &&
107  (!this->ghostInterface[3] || ijk[1] != this->ghostedNodesPerDir[1] - 1) &&
108  (!this->ghostInterface[5] || ijk[2] != this->ghostedNodesPerDir[2] - 1)) {
109  // this->getGhostedNodeFineLID(ijk[0], ijk[1], ijk[2], coarseNodeFineLID);
110  if (this->interpolationOrder_ == 0) {
111  currentCoarseIndex = 0;
112  if (this->ghostInterface[4]) {
113  currentCoarseIndex += (ijk[2] - 1) * this->lNumCoarseNodes10;
114  } else {
115  currentCoarseIndex += ijk[2] * this->lNumCoarseNodes10;
116  }
117  if (this->ghostInterface[2]) {
118  currentCoarseIndex += (ijk[1] - 1) * this->getLocalCoarseNodesInDir(0);
119  } else {
120  currentCoarseIndex += ijk[1] * this->getLocalCoarseNodesInDir(0);
121  }
122  if (this->ghostInterface[0]) {
123  currentCoarseIndex += ijk[0] - 1;
124  } else {
125  currentCoarseIndex += ijk[0];
126  }
127  } else {
128  this->getGhostedNodeCoarseLID(ijk[0], ijk[1], ijk[2], currentCoarseIndex);
129  }
130 
131  lCoarseNodeCoarseGIDs[currentCoarseIndex] = myCoarseGID;
132  lCoarseNodeFineGIDs[currentCoarseIndex] = myGID;
133  }
134  ghostedCoarseNodeFineGIDs[currentIndex] = myGID;
135  }
136  }
137  }
138 
139  RCP<const Map> coarseMap = Xpetra::MapFactory<LO, GO, NO>::Build(fineMap->lib(),
140  this->gNumCoarseNodes,
141  lCoarseNodeCoarseGIDs(),
142  fineMap->getIndexBase(),
143  fineMap->getComm());
144 
145  coarseMap->getRemoteIndexList(ghostedNodeCoarseGIDs(),
146  ghostedNodeCoarsePIDs(),
147  ghostedNodeCoarseLIDs());
148 
149 } // End getGhostedMeshData
150 
151 template <class LocalOrdinal, class GlobalOrdinal, class Node>
153  getCoarseNodesData(const RCP<const Map> fineCoordinatesMap,
154  Array<GO>& coarseNodeCoarseGIDs,
155  Array<GO>& coarseNodeFineGIDs) const {
156  // Allocate sufficient storage space for outputs
157  coarseNodeCoarseGIDs.resize(this->getNumLocalCoarseNodes());
158  coarseNodeFineGIDs.resize(this->getNumLocalCoarseNodes());
159 
160  // Load all the GIDs on the fine mesh
161  ArrayView<const GO> fineNodeGIDs = fineCoordinatesMap->getLocalElementList();
162 
163  Array<GO> coarseStartIndices(3);
164  GO tmp;
165  for (int dim = 0; dim < 3; ++dim) {
166  coarseStartIndices[dim] = this->startIndices[dim] / this->coarseRate[dim];
167  tmp = this->startIndices[dim] % this->coarseRate[dim];
168  if (tmp > 0) {
169  ++coarseStartIndices[dim];
170  }
171  }
172 
173  // Extract the fine LIDs of the coarse nodes and store the corresponding GIDs
174  LO fineLID;
175  Array<LO> lCoarseIndices(3);
176  Array<GO> gCoarseIndices(3);
177  for (LO coarseLID = 0; coarseLID < this->getNumLocalCoarseNodes(); ++coarseLID) {
178  this->getCoarseNodeLocalTuple(coarseLID,
179  lCoarseIndices[0],
180  lCoarseIndices[1],
181  lCoarseIndices[2]);
182  getCoarseNodeFineLID(lCoarseIndices[0], lCoarseIndices[1], lCoarseIndices[2], fineLID);
183  coarseNodeFineGIDs[coarseLID] = fineNodeGIDs[fineLID];
184 
185  // Get Coarse Global IJK
186  for (int dim = 0; dim < 3; dim++) {
187  gCoarseIndices[dim] = coarseStartIndices[dim] + lCoarseIndices[dim];
188  }
189  getCoarseNodeGID(gCoarseIndices[0],
190  gCoarseIndices[1],
191  gCoarseIndices[2],
192  coarseNodeCoarseGIDs[coarseLID]);
193  }
194 }
195 
196 template <class LocalOrdinal, class GlobalOrdinal, class Node>
197 std::vector<std::vector<GlobalOrdinal> > GlobalLexicographicIndexManager<LocalOrdinal, GlobalOrdinal, Node>::
199  std::vector<std::vector<GO> > coarseMeshData;
200  return coarseMeshData;
201 }
202 
203 template <class LocalOrdinal, class GlobalOrdinal, class Node>
205  getFineNodeGlobalTuple(const GO myGID, GO& i, GO& j, GO& k) const {
206  GO tmp;
207  k = myGID / this->gNumFineNodes10;
208  tmp = myGID % this->gNumFineNodes10;
209  j = tmp / this->gFineNodesPerDir[0];
210  i = tmp % this->gFineNodesPerDir[0];
211 }
212 
213 template <class LocalOrdinal, class GlobalOrdinal, class Node>
215  getFineNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
216  LO tmp;
217  k = myLID / this->lNumFineNodes10;
218  tmp = myLID % this->lNumFineNodes10;
219  j = tmp / this->lFineNodesPerDir[0];
220  i = tmp % this->lFineNodesPerDir[0];
221 }
222 
223 template <class LocalOrdinal, class GlobalOrdinal, class Node>
225  getFineNodeGhostedTuple(const LO myLID, LO& i, LO& j, LO& k) const {
226  LO tmp;
227  k = myLID / this->lNumFineNodes10;
228  tmp = myLID % this->lNumFineNodes10;
229  j = tmp / this->lFineNodesPerDir[0];
230  i = tmp % this->lFineNodesPerDir[0];
231 
232  k += this->offsets[2];
233  j += this->offsets[1];
234  i += this->offsets[0];
235 }
236 
237 template <class LocalOrdinal, class GlobalOrdinal, class Node>
239  getFineNodeGID(const GO i, const GO j, const GO k, GO& myGID) const {
240  myGID = k * this->gNumFineNodes10 + j * this->gFineNodesPerDir[0] + i;
241 }
242 
243 template <class LocalOrdinal, class GlobalOrdinal, class Node>
245  getFineNodeLID(const LO i, const LO j, const LO k, LO& myLID) const {
246  myLID = k * this->lNumFineNodes10 + j * this->lFineNodesPerDir[0] + i;
247 }
248 
249 template <class LocalOrdinal, class GlobalOrdinal, class Node>
251  getCoarseNodeGlobalTuple(const GO myGID, GO& i, GO& j, GO& k) const {
252  GO tmp;
253  k = myGID / this->gNumCoarseNodes10;
254  tmp = myGID % this->gNumCoarseNodes10;
255  j = tmp / this->gCoarseNodesPerDir[0];
256  i = tmp % this->gCoarseNodesPerDir[0];
257 }
258 
259 template <class LocalOrdinal, class GlobalOrdinal, class Node>
261  getCoarseNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
262  LO tmp;
263  k = myLID / this->lNumCoarseNodes10;
264  tmp = myLID % this->lNumCoarseNodes10;
265  j = tmp / this->lCoarseNodesPerDir[0];
266  i = tmp % this->lCoarseNodesPerDir[0];
267 }
268 
269 template <class LocalOrdinal, class GlobalOrdinal, class Node>
271  getCoarseNodeGID(const GO i, const GO j, const GO k, GO& myGID) const {
272  myGID = k * this->gNumCoarseNodes10 + j * this->gCoarseNodesPerDir[0] + i;
273 }
274 
275 template <class LocalOrdinal, class GlobalOrdinal, class Node>
277  getCoarseNodeLID(const LO i, const LO j, const LO k, LO& myLID) const {
278  myLID = k * this->lNumCoarseNodes10 + j * this->lCoarseNodesPerDir[0] + i;
279 }
280 
281 template <class LocalOrdinal, class GlobalOrdinal, class Node>
283  getCoarseNodeGhostedLID(const LO i, const LO j, const LO k, LO& myLID) const {
284  myLID = k * this->numGhostedNodes10 + j * this->ghostedNodesPerDir[0] + i;
285 }
286 
287 template <class LocalOrdinal, class GlobalOrdinal, class Node>
289  getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO& myLID) const {
290  // Assumptions: (i,j,k) is a tuple on the coarse mesh
291  // myLID is the corresponding local ID on the fine mesh
292  const LO multiplier[3] = {1, this->lFineNodesPerDir[0], this->lNumFineNodes10};
293  const LO indices[3] = {i, j, k};
294 
295  myLID = 0;
296  for (int dim = 0; dim < 3; ++dim) {
297  if ((indices[dim] == this->getLocalCoarseNodesInDir(dim) - 1) && this->meshEdge[2 * dim + 1]) {
298  // We are dealing with the last node on the mesh in direction dim
299  // so we can simply use the number of nodes on the fine mesh in that direction
300  myLID += (this->getLocalFineNodesInDir(dim) - 1) * multiplier[dim];
301  } else {
302  myLID += (indices[dim] * this->getCoarseningRate(dim) + this->getCoarseNodeOffset(dim)) * multiplier[dim];
303  }
304  }
305 }
306 
307 template <class LocalOrdinal, class GlobalOrdinal, class Node>
309  getGhostedNodeFineLID(const LO i, const LO j, const LO k, LO& myLID) const {
310  LO itmp = i - (this->offsets[0] > 0 ? 1 : 0);
311  LO jtmp = j - (this->offsets[1] > 0 ? 1 : 0);
312  LO ktmp = k - (this->offsets[2] > 0 ? 1 : 0);
313  myLID = 0;
314  if (ktmp * this->coarseRate[2] < this->lFineNodesPerDir[2]) {
315  myLID += ktmp * this->coarseRate[2] * this->lNumCoarseNodes10;
316  } else {
317  myLID += (this->lFineNodesPerDir[2] - 1) * this->lNumCoarseNodes10;
318  }
319 
320  if (jtmp * this->coarseRate[1] < this->lFineNodesPerDir[1]) {
321  myLID += jtmp * this->coarseRate[1] * this->lFineNodesPerDir[0];
322  } else {
323  myLID += (this->lFineNodesPerDir[1] - 1) * this->lFineNodesPerDir[1];
324  }
325 
326  if (itmp * this->coarseRate[0] < this->lFineNodesPerDir[0]) {
327  myLID += itmp * this->coarseRate[0];
328  } else {
329  myLID += this->lFineNodesPerDir[0] - 1;
330  }
331 }
332 
333 template <class LocalOrdinal, class GlobalOrdinal, class Node>
335  getGhostedNodeCoarseLID(const LO i, const LO j, const LO k, LO& myLID) const {
336  LO itmp = i - (this->offsets[0] > 0 ? 1 : 0);
337  LO jtmp = j - (this->offsets[1] > 0 ? 1 : 0);
338  LO ktmp = k - (this->offsets[2] > 0 ? 1 : 0);
339  myLID = ktmp * this->lNumCoarseNodes10 + jtmp * this->lCoarseNodesPerDir[0] + itmp;
340 }
341 
342 } // namespace MueLu
343 
344 #endif /* MUELU_GLOBALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_ */
void getCoarseNodesData(const RCP< const Map > fineCoordinatesMap, Array< GO > &coarseNodeCoarseGIDs, Array< GO > &coarseNodeFineGIDs) const
void getGhostedNodesData(const RCP< const Map > fineMap, Array< LO > &ghostedNodeCoarseLIDs, Array< int > &ghostedNodeCoarsePIDs, Array< GO > &ghostedNodeCoarseGIDs) const
void getCoarseNodeLID(const LO i, const LO j, const LO k, LO &myLID) const
GlobalOrdinal GO
Array< GO > startIndices
lowest global tuple (i,j,k) of a node on the local process
LocalOrdinal LO
void getCoarseNodeGID(const GO i, const GO j, const GO k, GO &myGID) const
const Array< GO > gFineNodesPerDir
global number of nodes per direction.
const Array< LO > lFineNodesPerDir
local number of nodes per direction.
void getGhostedNodeFineLID(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
Array< int > coarseRate
coarsening rate in each direction
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
void getFineNodeGlobalTuple(const GO myGID, GO &i, GO &j, GO &k) const
const int numDimensions
Number of spacial dimensions in the problem.
void getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO &myLID) const
std::vector< std::vector< GO > > getCoarseMeshData() const
void getCoarseNodeLocalTuple(const LO myLID, LO &i, LO &j, LO &k) const
void getCoarseNodeGhostedLID(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 getCoarseNodeGlobalTuple(const GO myGID, GO &i, GO &j, GO &k) const
void getFineNodeLocalTuple(const LO myLID, LO &i, LO &j, LO &k) const
size_type size() const
void getGhostedNodeCoarseLID(const LO i, const LO j, const LO k, LO &myLID) const
void getFineNodeGhostedTuple(const LO myLID, LO &i, LO &j, LO &k) const
void getFineNodeLID(const LO i, const LO j, const LO k, LO &myLID) const
Container class for mesh layout and indices calculation.