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