Xpetra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Xpetra_ReorderedBlockedMultiVector.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Xpetra: A linear algebra interface package
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 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef XPETRA_REORDEREDBLOCKEDMULTIVECTOR_HPP
47 #define XPETRA_REORDEREDBLOCKEDMULTIVECTOR_HPP
48 
49 #include <Tpetra_KokkosCompat_DefaultNode.hpp>
50 
51 #include "Xpetra_ConfigDefs.hpp"
52 #include "Xpetra_Exceptions.hpp"
53 
54 #include "Xpetra_MapUtils.hpp"
55 
57 #include "Xpetra_BlockedMap.hpp"
58 #include "Xpetra_BlockedMultiVector.hpp"
59 
64 namespace Xpetra {
65 
66 typedef std::string viewLabel_t;
67 
68 template <class Scalar,
69  class LocalOrdinal,
70  class GlobalOrdinal,
71  class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
72 class ReorderedBlockedMultiVector : public BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
73  public:
74  typedef Scalar scalar_type;
75  typedef LocalOrdinal local_ordinal_type;
76  typedef GlobalOrdinal global_ordinal_type;
77  typedef Node node_type;
78 
79  private:
80 #undef XPETRA_REORDEREDBLOCKEDMULTIVECTOR_SHORT
81 #include "Xpetra_UseShortNames.hpp"
82 
83  public:
85 
86 
88 
95  ReorderedBlockedMultiVector(Teuchos::RCP<const BlockedMap>& rangeMap,
96  Teuchos::RCP<const Xpetra::BlockReorderManager> brm,
98  : Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>(rangeMap, bvec->getNumVectors(), false) {
99  brm_ = brm;
100  fullVec_ = bvec;
101  }
102 
103  // protected:
104 
107  brm_ = Teuchos::null;
108  fullVec_ = Teuchos::null;
109  }
110 
112 
113  private:
114  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> mergeSubBlockMaps(Teuchos::RCP<const Xpetra::BlockReorderManager> brm) {
115  RCP<const BlockedMap> bmap = fullVec_->getBlockedMap();
116 
117  // number of sub blocks
118  size_t numBlocks = brm->GetNumBlocks();
119 
120  Teuchos::RCP<const Map> map = Teuchos::null;
121 
122  if (numBlocks == 0) {
123  // it is a leaf node
124  Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
125 
126  // never extract Thyra style maps (since we have to merge them)
127  map = bmap->getMap(Teuchos::as<size_t>(leaf->GetIndex()), false);
128  } else {
129  // initialize vector for sub maps
130  std::vector<Teuchos::RCP<const Map>> subMaps(numBlocks, Teuchos::null);
131 
132  for (size_t i = 0; i < numBlocks; i++) {
133  Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
134  subMaps[i] = mergeSubBlockMaps(blkMgr);
135  TEUCHOS_ASSERT(subMaps[i].is_null() == false);
136  }
137 
138  map = MapUtils::concatenateMaps(subMaps);
139  }
140  TEUCHOS_ASSERT(map.is_null() == false);
141  return map;
142  }
143 
144  public:
146 
147 
149  std::string description() const { return "ReorderedBlockedMultiVector"; }
150 
152  void describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default) const {
153  TEUCHOS_ASSERT(brm_ != Teuchos::null);
154  out << description() << ": " << brm_->toString() << std::endl;
155  fullVec_->describe(out, verbLevel);
156  }
157 
159 
160  private:
161  Teuchos::RCP<const Xpetra::BlockReorderManager> brm_;
162  Teuchos::RCP<const Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> fullVec_;
163 };
164 
165 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
166 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> mergeSubBlockMaps(Teuchos::RCP<const Xpetra::BlockReorderManager> brm, Teuchos::RCP<const Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bvec, bool bThyraMode) {
168 
169  // TODO distinguish between range and domain map extractor! provide MapExtractor as parameter!
170  RCP<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>> bmap = bvec->getBlockedMap();
171 
172  // number of sub blocks
173  size_t numBlocks = brm->GetNumBlocks();
174 
175  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> map = Teuchos::null;
176 
177  if (numBlocks == 0) {
178  // it is a leaf node
179  Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
180 
181  map = bmap->getMap(Teuchos::as<size_t>(leaf->GetIndex()), bThyraMode);
182  } else {
183  // initialize vector for sub maps
184  std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>> subMaps(numBlocks, Teuchos::null);
185 
186  for (size_t i = 0; i < numBlocks; i++) {
187  Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
188  subMaps[i] = mergeSubBlockMaps(blkMgr, bvec, bThyraMode);
189  TEUCHOS_ASSERT(subMaps[i].is_null() == false);
190  }
191 #if 1
192  // concatenate submaps
193  // for Thyra mode this map isn't important
194  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> fullMap = MapUtils::concatenateMaps(subMaps);
195 
196  // create new BlockedMap (either in Thyra Mode or Xpetra mode)
197  map = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>(fullMap, subMaps, bThyraMode));
198 #else
199  // TAW: 11/27/16 we just concatenate the submaps to one monolithic Map object.
200  // Alternatively, we could create a new BlockedMap using the concatenated map and the submaps
201  // However, the block smoothers only need the concatenated map for creating MultiVectors...
202  // But for the Thyra mode version concatenating would not be ok for the whole map
203  map = MapUtils::concatenateMaps(subMaps);
204 #endif
205  }
206  TEUCHOS_ASSERT(map.is_null() == false);
207  return map;
208 }
209 
210 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
211 Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> mergeSubBlocks(Teuchos::RCP<const Xpetra::BlockReorderManager> rowMgr, Teuchos::RCP<const Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bvec) {
218 
219  // number of sub blocks
220  size_t rowSz = rowMgr->GetNumBlocks();
221 
222  Teuchos::RCP<BlockedMultiVector> rbvec = Teuchos::null;
223 
224  if (rowSz == 0) {
225  // it is a leaf node
226  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
227 
228  // extract leaf node
229  Teuchos::RCP<MultiVector> vec = bvec->getMultiVector(rowleaf->GetIndex(), false);
230 
231  TEUCHOS_ASSERT(vec != Teuchos::null);
232 
233  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
234  Teuchos::RCP<BlockedMultiVector> subBVec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(vec);
235  if (subBVec == Teuchos::null) {
236  // DEBUG
237  /*{
238  std::cout << "MultiVector:" << std::endl;
239  Teuchos::ArrayRCP<const Scalar> vData = vec->getData(0);
240  for(size_t j=0; j< vec->getMap()->getLocalNumElements(); j++) {
241  std::cout << j << ": " << vec->getMap()->getGlobalElement(j) << ": " << vData[j] << std::endl;
242  }
243  }*/
244  // END DEBUG
245 
246  // If the leaf node is of type Xpetra::MultiVector. Wrap it into a ReorderedBlockMultiVector
247  // with the corresponding MapExtractors for translating Thyra to Xpetra GIDs if necessary
248  RCP<const BlockedMap> fullBlockedMap = bvec->getBlockedMap();
249  Teuchos::RCP<const Map> submap = fullBlockedMap->getMap(rowleaf->GetIndex(), false);
250  std::vector<Teuchos::RCP<const Map>> rowSubMaps(1, submap);
251  Teuchos::RCP<const BlockedMap> bbmap = Teuchos::rcp(new BlockedMap(submap, rowSubMaps, false));
252 
253  rbvec = Teuchos::rcp(new ReorderedBlockedMultiVector(bbmap, rowMgr, bvec));
254  rbvec->setMultiVector(0, Teuchos::rcp_const_cast<MultiVector>(vec), false);
255 
256  } else {
257  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
258  rbvec = subBVec;
259  TEUCHOS_ASSERT(rbvec != Teuchos::null);
260  }
261  } else {
262  // create the map extractors
263  // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
264  Teuchos::RCP<const BlockedMap> rgBlockedMap = Teuchos::null;
265  std::vector<Teuchos::RCP<const Map>> rowSubMaps(rowSz, Teuchos::null);
266  for (size_t i = 0; i < rowSz; i++) {
267  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
268  rowSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bvec, false /*xpetra*/);
269  TEUCHOS_ASSERT(rowSubMaps[i].is_null() == false);
270  }
271  Teuchos::RCP<const Map> rgMergedSubMaps = MapUtils::concatenateMaps(rowSubMaps);
272  rgBlockedMap = Teuchos::rcp(new BlockedMap(rgMergedSubMaps, rowSubMaps, false));
273  rbvec = Teuchos::rcp(new ReorderedBlockedMultiVector(rgBlockedMap, rowMgr, bvec));
274 
275  for (size_t i = 0; i < rowSz; i++) {
276  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
277  Teuchos::RCP<const MultiVector> subvec = mergeSubBlocks(rowSubMgr, bvec);
278  rbvec->setMultiVector(i, Teuchos::rcp_const_cast<MultiVector>(subvec), false);
279  }
280  }
281  return rbvec;
282 }
283 
284 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
285 Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> mergeSubBlocksThyra(Teuchos::RCP<const Xpetra::BlockReorderManager> rowMgr, Teuchos::RCP<const Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bvec) {
291 
292  TEUCHOS_ASSERT(bvec->getBlockedMap()->getThyraMode() == true);
293 
294  // number of sub blocks
295  size_t rowSz = rowMgr->GetNumBlocks();
296 
297  Teuchos::RCP<BlockedMultiVector> rbvec = Teuchos::null;
298 
299  if (rowSz == 0) {
300  // it is a leaf node
301  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
302 
303  // this MultiVector uses Thyra style GIDs as global row indices
304  Teuchos::RCP<MultiVector> vec = bvec->getMultiVector(rowleaf->GetIndex(), true);
305 
306  TEUCHOS_ASSERT(vec.is_null() == false);
307 
308  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
309  Teuchos::RCP<BlockedMultiVector> bbvec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(vec);
310  if (bbvec == Teuchos::null) {
312  // build blocked map
313  RCP<const BlockedMap> fullBlockedRangeMap = bvec->getBlockedMap();
314  // extract Xpetra and Thyra based GIDs
315  Teuchos::RCP<const Map> xpsubmap = fullBlockedRangeMap->getMap(rowleaf->GetIndex(), false);
316  Teuchos::RCP<const Map> thysubmap = fullBlockedRangeMap->getMap(rowleaf->GetIndex(), true);
317  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(1, xpsubmap);
318  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(1, thysubmap);
319  // use expert constructor
320  Teuchos::RCP<const BlockedMap> rgBlockedMap = Teuchos::rcp(new BlockedMap(rowXpSubMaps, rowTySubMaps));
321 
323  // build reordered blocked multi vector
324  rbvec = Teuchos::rcp(new ReorderedBlockedMultiVector(rgBlockedMap, rowMgr, bvec));
325  rbvec->setMultiVector(0, vec, true);
326  } else {
327  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
328  rbvec = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(vec);
329  }
330  } else {
331  // create the blocked map
332  // we cannot create block multivector in thyra mode since merged maps might not start with 0 GID
333 
334  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(rowSz, Teuchos::null);
335  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(rowSz, Teuchos::null);
336  for (size_t i = 0; i < rowSz; i++) {
337  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
338  // extract Xpetra and Thyra based merged GIDs
339  rowXpSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bvec, false);
340  rowTySubMaps[i] = mergeSubBlockMaps(rowSubMgr, bvec, true);
341  TEUCHOS_ASSERT(rowXpSubMaps[i].is_null() == false);
342  TEUCHOS_ASSERT(rowTySubMaps[i].is_null() == false);
343  }
344  // use expert constructor
345  Teuchos::RCP<const BlockedMap> rgBlockedMap = Teuchos::rcp(new BlockedMap(rowXpSubMaps, rowTySubMaps));
346 
347  rbvec = Teuchos::rcp(new ReorderedBlockedMultiVector(rgBlockedMap, rowMgr, bvec));
348 
349  for (size_t i = 0; i < rowSz; i++) {
350  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
351  Teuchos::RCP<const MultiVector> subvec = mergeSubBlocksThyra(rowSubMgr, bvec);
352  rbvec->setMultiVector(i, Teuchos::rcp_const_cast<MultiVector>(subvec), true);
353  }
354  }
355  return rbvec;
356 }
357 
358 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
359 Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> buildReorderedBlockedMultiVector(Teuchos::RCP<const Xpetra::BlockReorderManager> brm, Teuchos::RCP<const Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bvec) {
360  Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> rbvec = Teuchos::null;
361  if (bvec->getBlockedMap()->getThyraMode() == false) {
362  rbvec = mergeSubBlocks(brm, bvec);
363  } else {
364  rbvec = mergeSubBlocksThyra(brm, bvec);
365  }
366  TEUCHOS_ASSERT(rbvec.is_null() == false);
367  return rbvec;
368 }
369 
370 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
371 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> buildReorderedBlockedMultiVector(Teuchos::RCP<const Xpetra::BlockReorderManager> brm, Teuchos::RCP<Xpetra::BlockedMultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bvec) {
374  Teuchos::RCP<const MultiVector> rbvec = Teuchos::null;
375  if (bvec->getBlockedMap()->getThyraMode() == false) {
376  rbvec = mergeSubBlocks(brm, Teuchos::rcp_const_cast<const BlockedMultiVector>(bvec));
377  } else {
378  rbvec = mergeSubBlocksThyra(brm, Teuchos::rcp_const_cast<const BlockedMultiVector>(bvec));
379  }
380  TEUCHOS_ASSERT(rbvec.is_null() == false);
381  return Teuchos::rcp_const_cast<MultiVector>(rbvec);
382 }
383 
384 } // namespace Xpetra
385 
386 #define XPETRA_REORDEREDBLOCKEDMULTIVECTOR_SHORT
387 #endif /* XPETRA_REORDEREDBLOCKEDMULTIVECTOR_HPP */
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlockMaps(Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> bmat, bool bThyraMode)
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlockMaps(Teuchos::RCP< const Xpetra::BlockReorderManager > brm)
Xpetra utility class for common map-related routines.
Teuchos::RCP< const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > buildReorderedBlockedMultiVector(Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node >> bvec)
static Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > concatenateMaps(const std::vector< Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > > &subMaps)
Helper function to concatenate several maps.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to an FancyOStream object.
ReorderedBlockedMultiVector(Teuchos::RCP< const BlockedMap > &rangeMap, Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node >> bvec)
Constructor.
Teuchos::RCP< const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlocks(Teuchos::RCP< const Xpetra::BlockReorderManager > rowMgr, Teuchos::RCP< const Xpetra::BlockReorderManager > colMgr, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> bmat)
Teuchos::RCP< const Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > fullVec_
std::string viewLabel_t
virtual size_t getNumVectors() const
Number of columns in the multivector.
Teuchos::RCP< const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlocksThyra(Teuchos::RCP< const Xpetra::BlockReorderManager > rowMgr, Teuchos::RCP< const Xpetra::BlockReorderManager > colMgr, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> bmat)
Teuchos::RCP< const Xpetra::BlockReorderManager > brm_
std::string description() const
Return a simple one-line description of this object.