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 // ***********************************************************************
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_GLOBALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
47 #define MUELU_GLOBALLEXICOGRAPHICINDEXMANAGER_DEF_HPP_
48 
50 #include <Xpetra_MapFactory.hpp>
51 
52 namespace MueLu {
53 
54 template <class LocalOrdinal, class GlobalOrdinal, class Node>
56  GlobalLexicographicIndexManager(const RCP<const Teuchos::Comm<int> > comm, const bool coupled,
57  const int NumDimensions, const int interpolationOrder,
58  const Array<GO> GFineNodesPerDir,
59  const Array<LO> LFineNodesPerDir, const Array<LO> CoarseRate,
60  const GO MinGlobalIndex)
61  : IndexManager(comm, coupled, false, NumDimensions, interpolationOrder, GFineNodesPerDir, LFineNodesPerDir) {
62  // Load coarse rate, being careful about formating.
63  for (int dim = 0; dim < 3; ++dim) {
64  if (dim < this->numDimensions) {
65  if (CoarseRate.size() == 1) {
66  this->coarseRate[dim] = CoarseRate[0];
67  } else if (CoarseRate.size() == this->numDimensions) {
68  this->coarseRate[dim] = CoarseRate[dim];
69  }
70  } else {
71  this->coarseRate[dim] = 1;
72  }
73  }
74 
75  {
76  GO tmp = 0;
77  this->startIndices[2] = MinGlobalIndex / (this->gFineNodesPerDir[1] * this->gFineNodesPerDir[0]);
78  tmp = MinGlobalIndex % (this->gFineNodesPerDir[1] * this->gFineNodesPerDir[0]);
79  this->startIndices[1] = tmp / this->gFineNodesPerDir[0];
80  this->startIndices[0] = tmp % this->gFineNodesPerDir[0];
81 
82  for (int dim = 0; dim < 3; ++dim) {
83  this->startIndices[dim + 3] = this->startIndices[dim] + this->lFineNodesPerDir[dim] - 1;
84  }
85  }
86 
87  this->computeMeshParameters();
89 }
90 
91 template <class LocalOrdinal, class GlobalOrdinal, class Node>
94  this->gNumCoarseNodes10 = this->gCoarseNodesPerDir[0] * this->gCoarseNodesPerDir[1];
95  this->gNumCoarseNodes = this->gNumCoarseNodes10 * this->gCoarseNodesPerDir[2];
96 }
97 
98 template <class LocalOrdinal, class GlobalOrdinal, class Node>
101  Array<LO>& ghostedNodeCoarseLIDs, Array<int>& ghostedNodeCoarsePIDs, Array<GO>& ghostedNodeCoarseGIDs) const {
102  ghostedNodeCoarseLIDs.resize(this->getNumLocalGhostedNodes());
103  ghostedNodeCoarsePIDs.resize(this->getNumLocalGhostedNodes());
104  ghostedNodeCoarseGIDs.resize(this->numGhostedNodes);
105 
106  // Find the GIDs, LIDs and PIDs of the coarse points on the fine mesh and coarse
107  // mesh as this data will be used to fill vertex2AggId and procWinner vectors.
108  Array<GO> lCoarseNodeCoarseGIDs(this->lNumCoarseNodes),
109  lCoarseNodeFineGIDs(this->lNumCoarseNodes);
110  Array<GO> ghostedCoarseNodeFineGIDs(this->numGhostedNodes);
111  Array<LO> ghostedCoarseNodeCoarseIndices(3), ghostedCoarseNodeFineIndices(3), ijk(3);
112  LO currentIndex = -1, currentCoarseIndex = -1;
113  for (ijk[2] = 0; ijk[2] < this->ghostedNodesPerDir[2]; ++ijk[2]) {
114  for (ijk[1] = 0; ijk[1] < this->ghostedNodesPerDir[1]; ++ijk[1]) {
115  for (ijk[0] = 0; ijk[0] < this->ghostedNodesPerDir[0]; ++ijk[0]) {
116  currentIndex = ijk[2] * this->numGhostedNodes10 + ijk[1] * this->ghostedNodesPerDir[0] + ijk[0];
117  ghostedCoarseNodeCoarseIndices[0] = this->startGhostedCoarseNode[0] + ijk[0];
118  ghostedCoarseNodeCoarseIndices[1] = this->startGhostedCoarseNode[1] + ijk[1];
119  ghostedCoarseNodeCoarseIndices[2] = this->startGhostedCoarseNode[2] + ijk[2];
120  GO myCoarseGID = ghostedCoarseNodeCoarseIndices[0] + ghostedCoarseNodeCoarseIndices[1] * this->gCoarseNodesPerDir[0] + ghostedCoarseNodeCoarseIndices[2] * this->gNumCoarseNodes10;
121  ghostedNodeCoarseGIDs[currentIndex] = myCoarseGID;
122  GO myGID = 0, factor[3] = {};
123  factor[2] = this->gNumFineNodes10;
124  factor[1] = this->gFineNodesPerDir[0];
125  factor[0] = 1;
126  for (int dim = 0; dim < 3; ++dim) {
127  if (dim < this->numDimensions) {
128  if (this->startIndices[dim] - this->offsets[dim] + ijk[dim] * this->coarseRate[dim] < this->gFineNodesPerDir[dim] - 1) {
129  myGID += (this->startIndices[dim] - this->offsets[dim] + ijk[dim] * this->coarseRate[dim]) * factor[dim];
130  } else {
131  myGID += (this->startIndices[dim] - this->offsets[dim] + (ijk[dim] - 1) * this->coarseRate[dim] + this->endRate[dim]) * factor[dim];
132  }
133  }
134  }
135  // lbv 02-08-2018:
136  // This check is simplistic and should be replaced by a condition that checks
137  // if the local tuple of the current index is wihin the range of local nodes
138  // or not in the range of ghosted nodes.
139  if ((!this->ghostInterface[0] || ijk[0] != 0) &&
140  (!this->ghostInterface[2] || ijk[1] != 0) &&
141  (!this->ghostInterface[4] || ijk[2] != 0) &&
142  (!this->ghostInterface[1] || ijk[0] != this->ghostedNodesPerDir[0] - 1) &&
143  (!this->ghostInterface[3] || ijk[1] != this->ghostedNodesPerDir[1] - 1) &&
144  (!this->ghostInterface[5] || ijk[2] != this->ghostedNodesPerDir[2] - 1)) {
145  // this->getGhostedNodeFineLID(ijk[0], ijk[1], ijk[2], coarseNodeFineLID);
146  if (this->interpolationOrder_ == 0) {
147  currentCoarseIndex = 0;
148  if (this->ghostInterface[4]) {
149  currentCoarseIndex += (ijk[2] - 1) * this->lNumCoarseNodes10;
150  } else {
151  currentCoarseIndex += ijk[2] * this->lNumCoarseNodes10;
152  }
153  if (this->ghostInterface[2]) {
154  currentCoarseIndex += (ijk[1] - 1) * this->getLocalCoarseNodesInDir(0);
155  } else {
156  currentCoarseIndex += ijk[1] * this->getLocalCoarseNodesInDir(0);
157  }
158  if (this->ghostInterface[0]) {
159  currentCoarseIndex += ijk[0] - 1;
160  } else {
161  currentCoarseIndex += ijk[0];
162  }
163  } else {
164  this->getGhostedNodeCoarseLID(ijk[0], ijk[1], ijk[2], currentCoarseIndex);
165  }
166 
167  lCoarseNodeCoarseGIDs[currentCoarseIndex] = myCoarseGID;
168  lCoarseNodeFineGIDs[currentCoarseIndex] = myGID;
169  }
170  ghostedCoarseNodeFineGIDs[currentIndex] = myGID;
171  }
172  }
173  }
174 
175  RCP<const Map> coarseMap = Xpetra::MapFactory<LO, GO, NO>::Build(fineMap->lib(),
176  this->gNumCoarseNodes,
177  lCoarseNodeCoarseGIDs(),
178  fineMap->getIndexBase(),
179  fineMap->getComm());
180 
181  coarseMap->getRemoteIndexList(ghostedNodeCoarseGIDs(),
182  ghostedNodeCoarsePIDs(),
183  ghostedNodeCoarseLIDs());
184 
185 } // End getGhostedMeshData
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  // Allocate sufficient storage space for outputs
193  coarseNodeCoarseGIDs.resize(this->getNumLocalCoarseNodes());
194  coarseNodeFineGIDs.resize(this->getNumLocalCoarseNodes());
195 
196  // Load all the GIDs on the fine mesh
197  ArrayView<const GO> fineNodeGIDs = fineCoordinatesMap->getLocalElementList();
198 
199  Array<GO> coarseStartIndices(3);
200  GO tmp;
201  for (int dim = 0; dim < 3; ++dim) {
202  coarseStartIndices[dim] = this->startIndices[dim] / this->coarseRate[dim];
203  tmp = this->startIndices[dim] % this->coarseRate[dim];
204  if (tmp > 0) {
205  ++coarseStartIndices[dim];
206  }
207  }
208 
209  // Extract the fine LIDs of the coarse nodes and store the corresponding GIDs
210  LO fineLID;
211  Array<LO> lCoarseIndices(3);
212  Array<GO> gCoarseIndices(3);
213  for (LO coarseLID = 0; coarseLID < this->getNumLocalCoarseNodes(); ++coarseLID) {
214  this->getCoarseNodeLocalTuple(coarseLID,
215  lCoarseIndices[0],
216  lCoarseIndices[1],
217  lCoarseIndices[2]);
218  getCoarseNodeFineLID(lCoarseIndices[0], lCoarseIndices[1], lCoarseIndices[2], fineLID);
219  coarseNodeFineGIDs[coarseLID] = fineNodeGIDs[fineLID];
220 
221  // Get Coarse Global IJK
222  for (int dim = 0; dim < 3; dim++) {
223  gCoarseIndices[dim] = coarseStartIndices[dim] + lCoarseIndices[dim];
224  }
225  getCoarseNodeGID(gCoarseIndices[0],
226  gCoarseIndices[1],
227  gCoarseIndices[2],
228  coarseNodeCoarseGIDs[coarseLID]);
229  }
230 }
231 
232 template <class LocalOrdinal, class GlobalOrdinal, class Node>
233 std::vector<std::vector<GlobalOrdinal> > GlobalLexicographicIndexManager<LocalOrdinal, GlobalOrdinal, Node>::
235  std::vector<std::vector<GO> > coarseMeshData;
236  return coarseMeshData;
237 }
238 
239 template <class LocalOrdinal, class GlobalOrdinal, class Node>
241  getFineNodeGlobalTuple(const GO myGID, GO& i, GO& j, GO& k) const {
242  GO tmp;
243  k = myGID / this->gNumFineNodes10;
244  tmp = myGID % this->gNumFineNodes10;
245  j = tmp / this->gFineNodesPerDir[0];
246  i = tmp % this->gFineNodesPerDir[0];
247 }
248 
249 template <class LocalOrdinal, class GlobalOrdinal, class Node>
251  getFineNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
252  LO tmp;
253  k = myLID / this->lNumFineNodes10;
254  tmp = myLID % this->lNumFineNodes10;
255  j = tmp / this->lFineNodesPerDir[0];
256  i = tmp % this->lFineNodesPerDir[0];
257 }
258 
259 template <class LocalOrdinal, class GlobalOrdinal, class Node>
261  getFineNodeGhostedTuple(const LO myLID, LO& i, LO& j, LO& k) const {
262  LO tmp;
263  k = myLID / this->lNumFineNodes10;
264  tmp = myLID % this->lNumFineNodes10;
265  j = tmp / this->lFineNodesPerDir[0];
266  i = tmp % this->lFineNodesPerDir[0];
267 
268  k += this->offsets[2];
269  j += this->offsets[1];
270  i += this->offsets[0];
271 }
272 
273 template <class LocalOrdinal, class GlobalOrdinal, class Node>
275  getFineNodeGID(const GO i, const GO j, const GO k, GO& myGID) const {
276  myGID = k * this->gNumFineNodes10 + j * this->gFineNodesPerDir[0] + i;
277 }
278 
279 template <class LocalOrdinal, class GlobalOrdinal, class Node>
281  getFineNodeLID(const LO i, const LO j, const LO k, LO& myLID) const {
282  myLID = k * this->lNumFineNodes10 + j * this->lFineNodesPerDir[0] + i;
283 }
284 
285 template <class LocalOrdinal, class GlobalOrdinal, class Node>
287  getCoarseNodeGlobalTuple(const GO myGID, GO& i, GO& j, GO& k) const {
288  GO tmp;
289  k = myGID / this->gNumCoarseNodes10;
290  tmp = myGID % this->gNumCoarseNodes10;
291  j = tmp / this->gCoarseNodesPerDir[0];
292  i = tmp % this->gCoarseNodesPerDir[0];
293 }
294 
295 template <class LocalOrdinal, class GlobalOrdinal, class Node>
297  getCoarseNodeLocalTuple(const LO myLID, LO& i, LO& j, LO& k) const {
298  LO tmp;
299  k = myLID / this->lNumCoarseNodes10;
300  tmp = myLID % this->lNumCoarseNodes10;
301  j = tmp / this->lCoarseNodesPerDir[0];
302  i = tmp % this->lCoarseNodesPerDir[0];
303 }
304 
305 template <class LocalOrdinal, class GlobalOrdinal, class Node>
307  getCoarseNodeGID(const GO i, const GO j, const GO k, GO& myGID) const {
308  myGID = k * this->gNumCoarseNodes10 + j * this->gCoarseNodesPerDir[0] + i;
309 }
310 
311 template <class LocalOrdinal, class GlobalOrdinal, class Node>
313  getCoarseNodeLID(const LO i, const LO j, const LO k, LO& myLID) const {
314  myLID = k * this->lNumCoarseNodes10 + j * this->lCoarseNodesPerDir[0] + i;
315 }
316 
317 template <class LocalOrdinal, class GlobalOrdinal, class Node>
319  getCoarseNodeGhostedLID(const LO i, const LO j, const LO k, LO& myLID) const {
320  myLID = k * this->numGhostedNodes10 + j * this->ghostedNodesPerDir[0] + i;
321 }
322 
323 template <class LocalOrdinal, class GlobalOrdinal, class Node>
325  getCoarseNodeFineLID(const LO i, const LO j, const LO k, LO& myLID) const {
326  // Assumptions: (i,j,k) is a tuple on the coarse mesh
327  // myLID is the corresponding local ID on the fine mesh
328  const LO multiplier[3] = {1, this->lFineNodesPerDir[0], this->lNumFineNodes10};
329  const LO indices[3] = {i, j, k};
330 
331  myLID = 0;
332  for (int dim = 0; dim < 3; ++dim) {
333  if ((indices[dim] == this->getLocalCoarseNodesInDir(dim) - 1) && this->meshEdge[2 * dim + 1]) {
334  // We are dealing with the last node on the mesh in direction dim
335  // so we can simply use the number of nodes on the fine mesh in that direction
336  myLID += (this->getLocalFineNodesInDir(dim) - 1) * multiplier[dim];
337  } else {
338  myLID += (indices[dim] * this->getCoarseningRate(dim) + this->getCoarseNodeOffset(dim)) * multiplier[dim];
339  }
340  }
341 }
342 
343 template <class LocalOrdinal, class GlobalOrdinal, class Node>
345  getGhostedNodeFineLID(const LO i, const LO j, const LO k, LO& myLID) const {
346  LO itmp = i - (this->offsets[0] > 0 ? 1 : 0);
347  LO jtmp = j - (this->offsets[1] > 0 ? 1 : 0);
348  LO ktmp = k - (this->offsets[2] > 0 ? 1 : 0);
349  myLID = 0;
350  if (ktmp * this->coarseRate[2] < this->lFineNodesPerDir[2]) {
351  myLID += ktmp * this->coarseRate[2] * this->lNumCoarseNodes10;
352  } else {
353  myLID += (this->lFineNodesPerDir[2] - 1) * this->lNumCoarseNodes10;
354  }
355 
356  if (jtmp * this->coarseRate[1] < this->lFineNodesPerDir[1]) {
357  myLID += jtmp * this->coarseRate[1] * this->lFineNodesPerDir[0];
358  } else {
359  myLID += (this->lFineNodesPerDir[1] - 1) * this->lFineNodesPerDir[1];
360  }
361 
362  if (itmp * this->coarseRate[0] < this->lFineNodesPerDir[0]) {
363  myLID += itmp * this->coarseRate[0];
364  } else {
365  myLID += this->lFineNodesPerDir[0] - 1;
366  }
367 }
368 
369 template <class LocalOrdinal, class GlobalOrdinal, class Node>
371  getGhostedNodeCoarseLID(const LO i, const LO j, const LO k, LO& myLID) const {
372  LO itmp = i - (this->offsets[0] > 0 ? 1 : 0);
373  LO jtmp = j - (this->offsets[1] > 0 ? 1 : 0);
374  LO ktmp = k - (this->offsets[2] > 0 ? 1 : 0);
375  myLID = ktmp * this->lNumCoarseNodes10 + jtmp * this->lCoarseNodesPerDir[0] + itmp;
376 }
377 
378 } // namespace MueLu
379 
380 #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.