Xpetra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Xpetra_ReorderedBlockedCrsMatrix.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_REORDEREDBLOCKEDCRSMATRIX_HPP
47 #define XPETRA_REORDEREDBLOCKEDCRSMATRIX_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 
56 #include "Xpetra_BlockedMultiVector.hpp"
58 #include "Xpetra_CrsMatrixWrap.hpp"
60 
65 namespace Xpetra {
66 
67 typedef std::string viewLabel_t;
68 
69 template <class Scalar,
70  class LocalOrdinal,
71  class GlobalOrdinal,
72  class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
73 class ReorderedBlockedCrsMatrix : public BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
74  public:
75  typedef Scalar scalar_type;
76  typedef LocalOrdinal local_ordinal_type;
77  typedef GlobalOrdinal global_ordinal_type;
78  typedef Node node_type;
79 
80  private:
81 #undef XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
82 #include "Xpetra_UseShortNames.hpp"
83 
84  public:
86 
87 
89 
96  ReorderedBlockedCrsMatrix(Teuchos::RCP<const MapExtractor>& rangeMaps,
97  Teuchos::RCP<const MapExtractor>& domainMaps,
98  size_t npr,
99  Teuchos::RCP<const Xpetra::BlockReorderManager> brm,
101  : Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>(rangeMaps, domainMaps, npr) {
102  brm_ = brm;
103  fullOp_ = bmat;
104  }
105 
106  // protected:
107 
110 
112 
113  private:
114  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> mergeSubBlockMaps(Teuchos::RCP<const Xpetra::BlockReorderManager> brm) {
115  RCP<const MapExtractor> fullRangeMapExtractor = fullOp_->getRangeMapExtractor();
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 = fullRangeMapExtractor->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  virtual void apply(const MultiVector& X, MultiVector& Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues,
150  const RCP<Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node>>& regionInterfaceImporter,
151  const Teuchos::ArrayRCP<LocalOrdinal>& regionInterfaceLIDs) const {}
153 
156  virtual void apply(const MultiVector& X, MultiVector& Y,
157  Teuchos::ETransp mode = Teuchos::NO_TRANS,
158  Scalar alpha = ScalarTraits<Scalar>::one(),
159  Scalar beta = ScalarTraits<Scalar>::zero()) const {
160  // Nested sub-operators should just use the provided X and B vectors
161  if (fullOp_->getLocalNumRows() != this->getLocalNumRows()) {
163  return;
164  }
165 
166  // Special handling for the top level of the nested operator
167 
168  // check whether input parameters are blocked or not
169  RCP<const MultiVector> refX = rcpFromRef(X);
170  RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(refX);
171  RCP<MultiVector> tmpY = rcpFromRef(Y);
172  RCP<BlockedMultiVector> tmpbY = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(tmpY);
173 
174  bool bCopyResultX = false;
175  bool bCopyResultY = false;
176 
177  // TODO create a nested ReorderedBlockedMultiVector out of a nested BlockedMultiVector!
178  // probably not necessary, is it?
179  // check whether X and B are blocked but not ReorderedBlocked operators
180  /*if (refbX != Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
181  RCP<const ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<const ReorderedBlockedMultiVector>(refbX);
182  if(rbCheck == Teuchos::null) {
183  RCP<const BlockedMultiVector> bX =
184  Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, refbX));
185  TEUCHOS_ASSERT(bX.is_null()==false);
186  refbX.swap(bX);
187  }
188  }
189  if (tmpbY != Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
190  RCP<ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<ReorderedBlockedMultiVector>(tmpbY);
191  if(rbCheck == Teuchos::null) {
192  RCP<BlockedMultiVector> bY =
193  Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbY));
194  TEUCHOS_ASSERT(bY.is_null()==false);
195  tmpbY.swap(bY);
196  }
197  }*/
198 
199  // if X and B are not blocked, create a blocked version here and use the blocked vectors
200  // for the internal (nested) apply call.
201 
202  // Check whether "this" operator is the reordered variant of the underlying fullOp_.
203  // Note, that nested ReorderedBlockedCrsMatrices always have the same full operator "fullOp_"
204  // stored underneath for being able to "translate" the block ids.
205  if (refbX == Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
206  // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
207  RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
208  TEUCHOS_ASSERT(blkRgMap.is_null() == false);
209  RCP<const BlockedMultiVector> bXtemp = Teuchos::rcp(new BlockedMultiVector(blkRgMap, refX));
210  TEUCHOS_ASSERT(bXtemp.is_null() == false);
211  RCP<const BlockedMultiVector> bX =
212  Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, bXtemp));
213  TEUCHOS_ASSERT(bX.is_null() == false);
214  refbX.swap(bX);
215  bCopyResultX = true;
216  }
217 
218  if (tmpbY == Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
219  // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
220  RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
221  TEUCHOS_ASSERT(blkRgMap.is_null() == false);
222  RCP<BlockedMultiVector> tmpbYtemp = Teuchos::rcp(new BlockedMultiVector(blkRgMap, tmpY));
223  TEUCHOS_ASSERT(tmpbYtemp.is_null() == false);
224  RCP<BlockedMultiVector> bY =
225  Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbYtemp));
226  TEUCHOS_ASSERT(bY.is_null() == false);
227  tmpbY.swap(bY);
228  bCopyResultY = true;
229  }
230 
231  TEUCHOS_ASSERT(refbX.is_null() == false);
232  TEUCHOS_ASSERT(tmpbY.is_null() == false);
233 
235 
236  if (bCopyResultX == true) {
237  RCP<const MultiVector> Xmerged = refbX->Merge();
238  RCP<MultiVector> nonconstX = Teuchos::rcp_const_cast<MultiVector>(refX);
239  nonconstX->update(Teuchos::ScalarTraits<Scalar>::one(), *Xmerged, Teuchos::ScalarTraits<Scalar>::zero());
240  }
241  if (bCopyResultY == true) {
242  RCP<MultiVector> Ymerged = tmpbY->Merge();
243  Y.update(Teuchos::ScalarTraits<Scalar>::one(), *Ymerged, Teuchos::ScalarTraits<Scalar>::zero());
244  }
245  }
246 
247  // @}
248 
250 
251 
253  Teuchos::RCP<const Xpetra::BlockReorderManager> getBlockReorderManager() { return brm_; }
254 
256  Teuchos::RCP<const Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> getBlockedCrsMatrix() { return fullOp_; }
257 
258  // @}
259 
261 
262 
264  std::string description() const { return "ReorderedBlockedCrsMatrix"; }
265 
267  void describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default) const {
268  out << "Xpetra::ReorderedBlockedCrsMatrix: " << BlockedCrsMatrix::Rows() << " x " << BlockedCrsMatrix::Cols() << std::endl;
269 
271  out << "ReorderedBlockMatrix is fillComplete" << std::endl;
272 
273  out << "fullRowMap" << std::endl;
274  BlockedCrsMatrix::getRangeMap(0, false)->describe(out, verbLevel);
275 
276  // out << "fullColMap" << std::endl;
277  // fullcolmap_->describe(out,verbLevel);
278 
279  } else {
280  out << "Xpetra::ReorderedBlockedCrsMatrix is NOT fillComplete" << std::endl;
281  }
282 
283  for (size_t r = 0; r < BlockedCrsMatrix::Rows(); ++r)
284  for (size_t c = 0; c < BlockedCrsMatrix::Cols(); ++c) {
285  out << "Block(" << r << "," << c << ")" << std::endl;
286  BlockedCrsMatrix::getMatrix(r, c)->describe(out, verbLevel);
287  }
288  }
289 
291 
292  private:
293  Teuchos::RCP<const Xpetra::BlockReorderManager> brm_;
294  Teuchos::RCP<const Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> fullOp_;
295 };
296 
297 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
298 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) {
300 
301  // TODO distinguish between range and domain map extractor! provide MapExtractor as parameter!
302  RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>> fullRangeMapExtractor = bmat->getRangeMapExtractor();
303 
304  // number of sub blocks
305  size_t numBlocks = brm->GetNumBlocks();
306 
307  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> map = Teuchos::null;
308 
309  if (numBlocks == 0) {
310  // it is a leaf node
311  Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
312 
313  map = fullRangeMapExtractor->getMap(Teuchos::as<size_t>(leaf->GetIndex()), bThyraMode);
314  } else {
315  // initialize vector for sub maps
316  std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>> subMaps(numBlocks, Teuchos::null);
317 
318  for (size_t i = 0; i < numBlocks; i++) {
319  Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
320  subMaps[i] = mergeSubBlockMaps(blkMgr, bmat, bThyraMode);
321  TEUCHOS_ASSERT(subMaps[i].is_null() == false);
322  }
323 
324 #if 1
325  // concatenate submaps
326  // for Thyra mode this map isn't important
327  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> fullMap = MapUtils::concatenateMaps(subMaps);
328 
329  // create new BlockedMap (either in Thyra Mode or Xpetra mode)
330  map = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>(fullMap, subMaps, bThyraMode));
331 #else
332  // TAW: 11/27/16 we just concatenate the submaps to one monolithic Map object.
333  // Alternatively, we could create a new BlockedMap using the concatenated map and the submaps
334  // However, the block smoothers only need the concatenated map for creating MultiVectors...
335  // But for the Thyra mode version concatenating would not be ok for the whole map
336  map = MapUtils::concatenateMaps(subMaps);
337 #endif
338  }
339  TEUCHOS_ASSERT(map.is_null() == false);
340  return map;
341 }
342 
343 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
344 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) {
351 
352  // number of sub blocks
353  size_t rowSz = rowMgr->GetNumBlocks();
354  size_t colSz = colMgr->GetNumBlocks();
355 
356  Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
357 
358  if (rowSz == 0 && colSz == 0) {
359  // it is a leaf node
360  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
361  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
362 
363  // extract leaf node
364  Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
365 
366  if (mat == Teuchos::null) return Teuchos::null;
367 
368  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
369  Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>> matwrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(mat);
370  if (matwrap != Teuchos::null) {
371  // If the leaf node is of type Xpetra::CrsMatrixWrap wrap it into a 1x1 ReorderedBlockMatrix
372  // with the corresponding MapExtractors for translating Thyra to Xpetra GIDs if necessary
373  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
374  Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
375  std::vector<Teuchos::RCP<const Map>> rowSubMaps(1, submap);
376  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
377 
378  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
379  Teuchos::RCP<const Map> submap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
380  std::vector<Teuchos::RCP<const Map>> colSubMaps(1, submap2);
381  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(submap2, colSubMaps, false));
382 
383  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
384  rbmat->setMatrix(0, 0, mat);
385  } else {
386  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
387  rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
388  TEUCHOS_ASSERT(rbmat != Teuchos::null);
389  }
390  TEUCHOS_ASSERT(mat->getLocalNumEntries() == rbmat->getLocalNumEntries());
391  } else {
392  // create the map extractors
393  // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
394  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
395  if (rowSz > 0) {
396  std::vector<Teuchos::RCP<const Map>> rowSubMaps(rowSz, Teuchos::null);
397  for (size_t i = 0; i < rowSz; i++) {
398  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
399  rowSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, false /*xpetra*/);
400  TEUCHOS_ASSERT(rowSubMaps[i].is_null() == false);
401  }
402  Teuchos::RCP<const Map> rgMergedSubMaps = MapUtils::concatenateMaps(rowSubMaps);
403  rgMapExtractor = Teuchos::rcp(new MapExtractor(rgMergedSubMaps, rowSubMaps, false));
404  } else {
405  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
406  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
407  // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
408  // The GIDs might not start with 0 and may not be consecutive!
409  Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
410  std::vector<Teuchos::RCP<const Map>> rowSubMaps(1, submap);
411  rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
412  }
413 
414  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
415  if (colSz > 0) {
416  std::vector<Teuchos::RCP<const Map>> colSubMaps(colSz, Teuchos::null);
417  for (size_t j = 0; j < colSz; j++) {
418  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
419  colSubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, false /*xpetra*/);
420  TEUCHOS_ASSERT(colSubMaps[j].is_null() == false);
421  }
422  Teuchos::RCP<const Map> doMergedSubMaps = MapUtils::concatenateMaps(colSubMaps);
423  doMapExtractor = Teuchos::rcp(new MapExtractor(doMergedSubMaps, colSubMaps, false));
424  } else {
425  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
426  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
427  // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
428  // The GIDs might not start with 0 and may not be consecutive!
429  Teuchos::RCP<const Map> submap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
430  std::vector<Teuchos::RCP<const Map>> colSubMaps(1, submap);
431  doMapExtractor = Teuchos::rcp(new MapExtractor(submap, colSubMaps, false));
432  }
433 
434  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
435 
436  size_t cntNNZ = 0;
437 
438  if (rowSz == 0 && colSz > 0) {
439  for (size_t j = 0; j < colSz; j++) {
440  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
441  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowMgr, colSubMgr, bmat);
442  rbmat->setMatrix(0, j, Teuchos::rcp_const_cast<Matrix>(submat));
443  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
444  }
445  } else if (rowSz > 0 && colSz == 0) {
446  for (size_t i = 0; i < rowSz; i++) {
447  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
448  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colMgr, bmat);
449  rbmat->setMatrix(i, 0, Teuchos::rcp_const_cast<Matrix>(submat));
450  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
451  }
452  } else {
453  for (size_t i = 0; i < rowSz; i++) {
454  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
455  for (size_t j = 0; j < colSz; j++) {
456  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
457  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colSubMgr, bmat);
458  rbmat->setMatrix(i, j, Teuchos::rcp_const_cast<Matrix>(submat));
459  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
460  }
461  }
462  }
463  TEUCHOS_ASSERT(rbmat->getLocalNumEntries() == cntNNZ);
464  }
465  rbmat->fillComplete();
466  return rbmat;
467 }
468 
469 // MapExtractor(const std::vector<RCP<const Map> >& maps, const std::vector<RCP<const Map> >& thyramaps);
470 
471 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
472 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) {
478 
479  TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == true);
480  TEUCHOS_ASSERT(bmat->getDomainMapExtractor()->getThyraMode() == true);
481 
482  // number of sub blocks
483  size_t rowSz = rowMgr->GetNumBlocks();
484  size_t colSz = colMgr->GetNumBlocks();
485 
486  Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
487 
488  if (rowSz == 0 && colSz == 0) {
489  // it is a leaf node
490  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
491  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
492 
493  // this matrix uses Thyra style GIDs as global row, range, domain and column indices
494  Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
495 
496  if (mat == Teuchos::null) return Teuchos::null; // std::cout << "Block " << rowleaf->GetIndex() << "," << colleaf->GetIndex() << " is zero" << std::endl;
497 
498  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
499  Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>> matwrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(mat);
500  if (matwrap != Teuchos::null) {
502  // build map extractors
503  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
504  // extract Xpetra and Thyra based GIDs
505  Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
506  Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), true);
507  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(1, xpsubmap);
508  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(1, thysubmap);
509  // use expert constructor
510  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
511 
512  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
513  // extract Xpetra and Thyra based GIDs
514  Teuchos::RCP<const Map> xpsubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
515  Teuchos::RCP<const Map> tysubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), true);
516  std::vector<Teuchos::RCP<const Map>> colXpSubMaps(1, xpsubmap2);
517  std::vector<Teuchos::RCP<const Map>> colTySubMaps(1, tysubmap2);
518  // use expert constructor
519  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
520 
522  // build reordered block operator
523  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
524  rbmat->setMatrix(0, 0, mat);
525  } else {
526  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
527  rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
528  TEUCHOS_ASSERT(rbmat != Teuchos::null);
529  }
530  TEUCHOS_ASSERT(mat->getLocalNumEntries() == rbmat->getLocalNumEntries());
531  } else {
532  // create the map extractors
533  // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
534  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
535  if (rowSz > 0) {
536  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(rowSz, Teuchos::null);
537  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(rowSz, Teuchos::null);
538  for (size_t i = 0; i < rowSz; i++) {
539  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
540  // extract Xpetra and Thyra based merged GIDs
541  rowXpSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, false);
542  rowTySubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, true);
543  TEUCHOS_ASSERT(rowXpSubMaps[i].is_null() == false);
544  TEUCHOS_ASSERT(rowTySubMaps[i].is_null() == false);
545  }
546  // use expert constructor
547  rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
548  } else {
549  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
550  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
551  // extract Xpetra and Thyra based GIDs
552  Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
553  Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), true);
554  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(1, xpsubmap);
555  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(1, thysubmap);
556  // use expert constructor
557  rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
558  }
559 
560  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
561  if (colSz > 0) {
562  std::vector<Teuchos::RCP<const Map>> colXpSubMaps(colSz, Teuchos::null);
563  std::vector<Teuchos::RCP<const Map>> colTySubMaps(colSz, Teuchos::null);
564  for (size_t j = 0; j < colSz; j++) {
565  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
566  // extract Xpetra and Thyra based merged GIDs
567  colXpSubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, false);
568  colTySubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, true);
569  TEUCHOS_ASSERT(colXpSubMaps[j].is_null() == false);
570  TEUCHOS_ASSERT(colTySubMaps[j].is_null() == false);
571  }
572  // use expert constructor
573  doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
574  } else {
575  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
576  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
577  // extract Xpetra and Thyra based GIDs
578  Teuchos::RCP<const Map> xpsubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
579  Teuchos::RCP<const Map> tysubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), true);
580  std::vector<Teuchos::RCP<const Map>> colXpSubMaps(1, xpsubmap);
581  std::vector<Teuchos::RCP<const Map>> colTySubMaps(1, tysubmap);
582  // use expert constructor
583  doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
584  }
585 
586  // TODO matrix should have both rowMgr and colMgr??
587  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
588 
589  size_t cntNNZ = 0;
590 
591  if (rowSz == 0 && colSz > 0) {
592  for (size_t j = 0; j < colSz; j++) {
593  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
594  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowMgr, colSubMgr, bmat);
595  rbmat->setMatrix(0, j, Teuchos::rcp_const_cast<Matrix>(submat));
596  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
597  }
598  } else if (rowSz > 0 && colSz == 0) {
599  for (size_t i = 0; i < rowSz; i++) {
600  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
601  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colMgr, bmat);
602  rbmat->setMatrix(i, 0, Teuchos::rcp_const_cast<Matrix>(submat));
603  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
604  }
605  } else {
606  for (size_t i = 0; i < rowSz; i++) {
607  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
608  for (size_t j = 0; j < colSz; j++) {
609  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
610  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colSubMgr, bmat);
611  rbmat->setMatrix(i, j, Teuchos::rcp_const_cast<Matrix>(submat));
612  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
613  }
614  }
615  }
616  TEUCHOS_ASSERT(rbmat->getLocalNumEntries() == cntNNZ);
617  }
618 
619  rbmat->fillComplete();
620  return rbmat;
621 }
622 
623 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
624 Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> buildReorderedBlockedCrsMatrix(Teuchos::RCP<const Xpetra::BlockReorderManager> brm, Teuchos::RCP<const Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> bmat) {
625  TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == bmat->getDomainMapExtractor()->getThyraMode());
626  Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> rbmat = Teuchos::null;
627  if (bmat->getRangeMapExtractor()->getThyraMode() == false) {
628  rbmat = mergeSubBlocks(brm, brm, bmat);
629  } else {
630  rbmat = mergeSubBlocksThyra(brm, brm, bmat);
631  }
632 
633  // TAW, 6/7/2016: rbmat might be Teuchos::null for empty blocks!
634  return rbmat;
635 }
636 
637 } // namespace Xpetra
638 
639 #define XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
640 #endif /* XPETRA_REORDEREDBLOCKEDCRSMATRIX_HPP */
Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > fullOp_
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)
size_t getLocalNumRows() const
Returns the number of matrix rows owned on the calling node.
Teuchos::RCP< const Xpetra::BlockReorderManager > getBlockReorderManager()
Returns internal BlockReorderManager object.
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues, const RCP< Xpetra::Import< LocalOrdinal, GlobalOrdinal, Node > > &regionInterfaceImporter, const Teuchos::ArrayRCP< LocalOrdinal > &regionInterfaceLIDs) const
sparse matrix-multivector multiplication for the region layout matrices (currently no blocked impleme...
const RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
Teuchos::RCP< const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > buildReorderedBlockedCrsMatrix(Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> bmat)
const Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const
Implements DistObject interface.
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)
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.
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.
virtual void update(const Scalar &alpha, const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta)=0
Update multi-vector values with scaled values of A, this = beta*this + alpha*A.
Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > getBlockedCrsMatrix()
Returns internal unmodified BlockedCrsMatrix object.
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlockMaps(Teuchos::RCP< const Xpetra::BlockReorderManager > brm)
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
virtual size_t Cols() const
number of column blocks
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)
std::string viewLabel_t
std::string description() const
Return a simple one-line description of this object.
Teuchos::RCP< const Xpetra::BlockReorderManager > brm_
ReorderedBlockedCrsMatrix(Teuchos::RCP< const MapExtractor > &rangeMaps, Teuchos::RCP< const MapExtractor > &domainMaps, size_t npr, Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> bmat)
Constructor.
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)
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=ScalarTraits< Scalar >::one(), Scalar beta=ScalarTraits< Scalar >::zero()) const
Computes the sparse matrix-multivector multiplication.
Concrete implementation of Xpetra::Matrix.
virtual size_t Rows() const
number of row blocks
virtual void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues, const RCP< Xpetra::Import< LocalOrdinal, GlobalOrdinal, Node >> &regionInterfaceImporter, const Teuchos::ArrayRCP< LocalOrdinal > &regionInterfaceLIDs) const
sparse matrix-multivector multiplication for the region layout matrices (currently no blocked impleme...
Xpetra-specific matrix class.