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 // Xpetra: A linear algebra interface package
4 //
5 // Copyright 2012 NTESS and the Xpetra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef XPETRA_REORDEREDBLOCKEDCRSMATRIX_HPP
11 #define XPETRA_REORDEREDBLOCKEDCRSMATRIX_HPP
12 
13 #include <Tpetra_KokkosCompat_DefaultNode.hpp>
14 
15 #include "Xpetra_ConfigDefs.hpp"
16 #include "Xpetra_Exceptions.hpp"
17 
18 #include "Xpetra_MapUtils.hpp"
19 
20 #include "Xpetra_BlockedMultiVector.hpp"
22 #include "Xpetra_CrsMatrixWrap.hpp"
23 #include "Xpetra_BlockedCrsMatrix.hpp"
24 
29 namespace Xpetra {
30 
31 typedef std::string viewLabel_t;
32 
33 template <class Scalar,
34  class LocalOrdinal,
35  class GlobalOrdinal,
36  class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
37 class ReorderedBlockedCrsMatrix : public BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
38  public:
39  typedef Scalar scalar_type;
40  typedef LocalOrdinal local_ordinal_type;
41  typedef GlobalOrdinal global_ordinal_type;
42  typedef Node node_type;
43 
44  private:
45 #undef XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
46 #include "Xpetra_UseShortNames.hpp"
47 
48  public:
50 
51 
53 
60  ReorderedBlockedCrsMatrix(Teuchos::RCP<const MapExtractor>& rangeMaps,
61  Teuchos::RCP<const MapExtractor>& domainMaps,
62  size_t npr,
63  Teuchos::RCP<const Xpetra::BlockReorderManager> brm,
65  : Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>(rangeMaps, domainMaps, npr) {
66  brm_ = brm;
67  fullOp_ = bmat;
68  }
69 
70  // protected:
71 
74 
76 
77  private:
78  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> mergeSubBlockMaps(Teuchos::RCP<const Xpetra::BlockReorderManager> brm) {
79  RCP<const MapExtractor> fullRangeMapExtractor = fullOp_->getRangeMapExtractor();
80 
81  // number of sub blocks
82  size_t numBlocks = brm->GetNumBlocks();
83 
84  Teuchos::RCP<const Map> map = Teuchos::null;
85 
86  if (numBlocks == 0) {
87  // it is a leaf node
88  Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
89 
90  // never extract Thyra style maps (since we have to merge them)
91  map = fullRangeMapExtractor->getMap(Teuchos::as<size_t>(leaf->GetIndex()), false);
92  } else {
93  // initialize vector for sub maps
94  std::vector<Teuchos::RCP<const Map>> subMaps(numBlocks, Teuchos::null);
95 
96  for (size_t i = 0; i < numBlocks; i++) {
97  Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
98  subMaps[i] = mergeSubBlockMaps(blkMgr);
99  TEUCHOS_ASSERT(subMaps[i].is_null() == false);
100  }
101 
102  map = MapUtils::concatenateMaps(subMaps);
103  }
104  TEUCHOS_ASSERT(map.is_null() == false);
105  return map;
106  }
107 
108  public:
110 
111 
113  virtual void apply(const MultiVector& X, MultiVector& Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues,
114  const RCP<Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node>>& regionInterfaceImporter,
115  const Teuchos::ArrayRCP<LocalOrdinal>& regionInterfaceLIDs) const {}
117 
120  virtual void apply(const MultiVector& X, MultiVector& Y,
121  Teuchos::ETransp mode = Teuchos::NO_TRANS,
122  Scalar alpha = ScalarTraits<Scalar>::one(),
123  Scalar beta = ScalarTraits<Scalar>::zero()) const {
124  // Nested sub-operators should just use the provided X and B vectors
125  if (fullOp_->getLocalNumRows() != this->getLocalNumRows()) {
127  return;
128  }
129 
130  // Special handling for the top level of the nested operator
131 
132  // check whether input parameters are blocked or not
133  RCP<const MultiVector> refX = rcpFromRef(X);
134  RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(refX);
135  RCP<MultiVector> tmpY = rcpFromRef(Y);
136  RCP<BlockedMultiVector> tmpbY = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(tmpY);
137 
138  bool bCopyResultX = false;
139  bool bCopyResultY = false;
140 
141  // TODO create a nested ReorderedBlockedMultiVector out of a nested BlockedMultiVector!
142  // probably not necessary, is it?
143  // check whether X and B are blocked but not ReorderedBlocked operators
144  /*if (refbX != Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
145  RCP<const ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<const ReorderedBlockedMultiVector>(refbX);
146  if(rbCheck == Teuchos::null) {
147  RCP<const BlockedMultiVector> bX =
148  Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, refbX));
149  TEUCHOS_ASSERT(bX.is_null()==false);
150  refbX.swap(bX);
151  }
152  }
153  if (tmpbY != Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
154  RCP<ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<ReorderedBlockedMultiVector>(tmpbY);
155  if(rbCheck == Teuchos::null) {
156  RCP<BlockedMultiVector> bY =
157  Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbY));
158  TEUCHOS_ASSERT(bY.is_null()==false);
159  tmpbY.swap(bY);
160  }
161  }*/
162 
163  // if X and B are not blocked, create a blocked version here and use the blocked vectors
164  // for the internal (nested) apply call.
165 
166  // Check whether "this" operator is the reordered variant of the underlying fullOp_.
167  // Note, that nested ReorderedBlockedCrsMatrices always have the same full operator "fullOp_"
168  // stored underneath for being able to "translate" the block ids.
169  if (refbX == Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
170  // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
171  RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
172  TEUCHOS_ASSERT(blkRgMap.is_null() == false);
173  RCP<const BlockedMultiVector> bXtemp = Teuchos::rcp(new BlockedMultiVector(blkRgMap, refX));
174  TEUCHOS_ASSERT(bXtemp.is_null() == false);
175  RCP<const BlockedMultiVector> bX =
176  Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, bXtemp));
177  TEUCHOS_ASSERT(bX.is_null() == false);
178  refbX.swap(bX);
179  bCopyResultX = true;
180  }
181 
182  if (tmpbY == Teuchos::null && fullOp_->getLocalNumRows() == this->getLocalNumRows()) {
183  // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
184  RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
185  TEUCHOS_ASSERT(blkRgMap.is_null() == false);
186  RCP<BlockedMultiVector> tmpbYtemp = Teuchos::rcp(new BlockedMultiVector(blkRgMap, tmpY));
187  TEUCHOS_ASSERT(tmpbYtemp.is_null() == false);
188  RCP<BlockedMultiVector> bY =
189  Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbYtemp));
190  TEUCHOS_ASSERT(bY.is_null() == false);
191  tmpbY.swap(bY);
192  bCopyResultY = true;
193  }
194 
195  TEUCHOS_ASSERT(refbX.is_null() == false);
196  TEUCHOS_ASSERT(tmpbY.is_null() == false);
197 
199 
200  if (bCopyResultX == true) {
201  RCP<const MultiVector> Xmerged = refbX->Merge();
202  RCP<MultiVector> nonconstX = Teuchos::rcp_const_cast<MultiVector>(refX);
203  nonconstX->update(Teuchos::ScalarTraits<Scalar>::one(), *Xmerged, Teuchos::ScalarTraits<Scalar>::zero());
204  }
205  if (bCopyResultY == true) {
206  RCP<MultiVector> Ymerged = tmpbY->Merge();
207  Y.update(Teuchos::ScalarTraits<Scalar>::one(), *Ymerged, Teuchos::ScalarTraits<Scalar>::zero());
208  }
209  }
210 
211  // @}
212 
214 
215 
217  Teuchos::RCP<const Xpetra::BlockReorderManager> getBlockReorderManager() { return brm_; }
218 
220  Teuchos::RCP<const Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> getBlockedCrsMatrix() { return fullOp_; }
221 
222  // @}
223 
225 
226 
228  std::string description() const { return "ReorderedBlockedCrsMatrix"; }
229 
231  void describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default) const {
232  out << "Xpetra::ReorderedBlockedCrsMatrix: " << BlockedCrsMatrix::Rows() << " x " << BlockedCrsMatrix::Cols() << std::endl;
233 
235  out << "ReorderedBlockMatrix is fillComplete" << std::endl;
236 
237  out << "fullRowMap" << std::endl;
238  BlockedCrsMatrix::getRangeMap(0, false)->describe(out, verbLevel);
239 
240  // out << "fullColMap" << std::endl;
241  // fullcolmap_->describe(out,verbLevel);
242 
243  } else {
244  out << "Xpetra::ReorderedBlockedCrsMatrix is NOT fillComplete" << std::endl;
245  }
246 
247  for (size_t r = 0; r < BlockedCrsMatrix::Rows(); ++r)
248  for (size_t c = 0; c < BlockedCrsMatrix::Cols(); ++c) {
249  out << "Block(" << r << "," << c << ")" << std::endl;
250  BlockedCrsMatrix::getMatrix(r, c)->describe(out, verbLevel);
251  }
252  }
253 
255 
256  private:
257  Teuchos::RCP<const Xpetra::BlockReorderManager> brm_;
258  Teuchos::RCP<const Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> fullOp_;
259 };
260 
261 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
262 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) {
264 
265  // TODO distinguish between range and domain map extractor! provide MapExtractor as parameter!
266  RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>> fullRangeMapExtractor = bmat->getRangeMapExtractor();
267 
268  // number of sub blocks
269  size_t numBlocks = brm->GetNumBlocks();
270 
271  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> map = Teuchos::null;
272 
273  if (numBlocks == 0) {
274  // it is a leaf node
275  Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
276 
277  map = fullRangeMapExtractor->getMap(Teuchos::as<size_t>(leaf->GetIndex()), bThyraMode);
278  } else {
279  // initialize vector for sub maps
280  std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>> subMaps(numBlocks, Teuchos::null);
281 
282  for (size_t i = 0; i < numBlocks; i++) {
283  Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
284  subMaps[i] = mergeSubBlockMaps(blkMgr, bmat, bThyraMode);
285  TEUCHOS_ASSERT(subMaps[i].is_null() == false);
286  }
287 
288 #if 1
289  // concatenate submaps
290  // for Thyra mode this map isn't important
291  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> fullMap = MapUtils::concatenateMaps(subMaps);
292 
293  // create new BlockedMap (either in Thyra Mode or Xpetra mode)
294  map = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>(fullMap, subMaps, bThyraMode));
295 #else
296  // TAW: 11/27/16 we just concatenate the submaps to one monolithic Map object.
297  // Alternatively, we could create a new BlockedMap using the concatenated map and the submaps
298  // However, the block smoothers only need the concatenated map for creating MultiVectors...
299  // But for the Thyra mode version concatenating would not be ok for the whole map
300  map = MapUtils::concatenateMaps(subMaps);
301 #endif
302  }
303  TEUCHOS_ASSERT(map.is_null() == false);
304  return map;
305 }
306 
307 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
308 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) {
315 
316  // number of sub blocks
317  size_t rowSz = rowMgr->GetNumBlocks();
318  size_t colSz = colMgr->GetNumBlocks();
319 
320  Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
321 
322  if (rowSz == 0 && colSz == 0) {
323  // it is a leaf node
324  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
325  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
326 
327  // extract leaf node
328  Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
329 
330  if (mat == Teuchos::null) return Teuchos::null;
331 
332  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
333  Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>> matwrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(mat);
334  if (matwrap != Teuchos::null) {
335  // If the leaf node is of type Xpetra::CrsMatrixWrap wrap it into a 1x1 ReorderedBlockMatrix
336  // with the corresponding MapExtractors for translating Thyra to Xpetra GIDs if necessary
337  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
338  Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
339  std::vector<Teuchos::RCP<const Map>> rowSubMaps(1, submap);
340  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
341 
342  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
343  Teuchos::RCP<const Map> submap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
344  std::vector<Teuchos::RCP<const Map>> colSubMaps(1, submap2);
345  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(submap2, colSubMaps, false));
346 
347  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
348  rbmat->setMatrix(0, 0, mat);
349  } else {
350  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
351  rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
352  TEUCHOS_ASSERT(rbmat != Teuchos::null);
353  }
354  TEUCHOS_ASSERT(mat->getLocalNumEntries() == rbmat->getLocalNumEntries());
355  } else {
356  // create the map extractors
357  // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
358  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
359  if (rowSz > 0) {
360  std::vector<Teuchos::RCP<const Map>> rowSubMaps(rowSz, Teuchos::null);
361  for (size_t i = 0; i < rowSz; i++) {
362  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
363  rowSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, false /*xpetra*/);
364  TEUCHOS_ASSERT(rowSubMaps[i].is_null() == false);
365  }
366  Teuchos::RCP<const Map> rgMergedSubMaps = MapUtils::concatenateMaps(rowSubMaps);
367  rgMapExtractor = Teuchos::rcp(new MapExtractor(rgMergedSubMaps, rowSubMaps, false));
368  } else {
369  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
370  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
371  // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
372  // The GIDs might not start with 0 and may not be consecutive!
373  Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
374  std::vector<Teuchos::RCP<const Map>> rowSubMaps(1, submap);
375  rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
376  }
377 
378  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
379  if (colSz > 0) {
380  std::vector<Teuchos::RCP<const Map>> colSubMaps(colSz, Teuchos::null);
381  for (size_t j = 0; j < colSz; j++) {
382  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
383  colSubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, false /*xpetra*/);
384  TEUCHOS_ASSERT(colSubMaps[j].is_null() == false);
385  }
386  Teuchos::RCP<const Map> doMergedSubMaps = MapUtils::concatenateMaps(colSubMaps);
387  doMapExtractor = Teuchos::rcp(new MapExtractor(doMergedSubMaps, colSubMaps, false));
388  } else {
389  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
390  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
391  // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
392  // The GIDs might not start with 0 and may not be consecutive!
393  Teuchos::RCP<const Map> submap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
394  std::vector<Teuchos::RCP<const Map>> colSubMaps(1, submap);
395  doMapExtractor = Teuchos::rcp(new MapExtractor(submap, colSubMaps, false));
396  }
397 
398  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
399 
400  size_t cntNNZ = 0;
401 
402  if (rowSz == 0 && colSz > 0) {
403  for (size_t j = 0; j < colSz; j++) {
404  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
405  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowMgr, colSubMgr, bmat);
406  rbmat->setMatrix(0, j, Teuchos::rcp_const_cast<Matrix>(submat));
407  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
408  }
409  } else if (rowSz > 0 && colSz == 0) {
410  for (size_t i = 0; i < rowSz; i++) {
411  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
412  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colMgr, bmat);
413  rbmat->setMatrix(i, 0, Teuchos::rcp_const_cast<Matrix>(submat));
414  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
415  }
416  } else {
417  for (size_t i = 0; i < rowSz; i++) {
418  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
419  for (size_t j = 0; j < colSz; j++) {
420  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
421  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colSubMgr, bmat);
422  rbmat->setMatrix(i, j, Teuchos::rcp_const_cast<Matrix>(submat));
423  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
424  }
425  }
426  }
427  TEUCHOS_ASSERT(rbmat->getLocalNumEntries() == cntNNZ);
428  }
429  rbmat->fillComplete();
430  return rbmat;
431 }
432 
433 // MapExtractor(const std::vector<RCP<const Map> >& maps, const std::vector<RCP<const Map> >& thyramaps);
434 
435 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
436 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) {
442 
443  TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == true);
444  TEUCHOS_ASSERT(bmat->getDomainMapExtractor()->getThyraMode() == true);
445 
446  // number of sub blocks
447  size_t rowSz = rowMgr->GetNumBlocks();
448  size_t colSz = colMgr->GetNumBlocks();
449 
450  Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
451 
452  if (rowSz == 0 && colSz == 0) {
453  // it is a leaf node
454  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
455  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
456 
457  // this matrix uses Thyra style GIDs as global row, range, domain and column indices
458  Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
459 
460  if (mat == Teuchos::null) return Teuchos::null; // std::cout << "Block " << rowleaf->GetIndex() << "," << colleaf->GetIndex() << " is zero" << std::endl;
461 
462  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
463  Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>> matwrap = Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(mat);
464  if (matwrap != Teuchos::null) {
466  // build map extractors
467  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
468  // extract Xpetra and Thyra based GIDs
469  Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
470  Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), true);
471  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(1, xpsubmap);
472  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(1, thysubmap);
473  // use expert constructor
474  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
475 
476  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
477  // extract Xpetra and Thyra based GIDs
478  Teuchos::RCP<const Map> xpsubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
479  Teuchos::RCP<const Map> tysubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(), true);
480  std::vector<Teuchos::RCP<const Map>> colXpSubMaps(1, xpsubmap2);
481  std::vector<Teuchos::RCP<const Map>> colTySubMaps(1, tysubmap2);
482  // use expert constructor
483  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
484 
486  // build reordered block operator
487  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
488  rbmat->setMatrix(0, 0, mat);
489  } else {
490  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
491  rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
492  TEUCHOS_ASSERT(rbmat != Teuchos::null);
493  }
494  TEUCHOS_ASSERT(mat->getLocalNumEntries() == rbmat->getLocalNumEntries());
495  } else {
496  // create the map extractors
497  // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
498  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
499  if (rowSz > 0) {
500  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(rowSz, Teuchos::null);
501  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(rowSz, Teuchos::null);
502  for (size_t i = 0; i < rowSz; i++) {
503  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
504  // extract Xpetra and Thyra based merged GIDs
505  rowXpSubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, false);
506  rowTySubMaps[i] = mergeSubBlockMaps(rowSubMgr, bmat, true);
507  TEUCHOS_ASSERT(rowXpSubMaps[i].is_null() == false);
508  TEUCHOS_ASSERT(rowTySubMaps[i].is_null() == false);
509  }
510  // use expert constructor
511  rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
512  } else {
513  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
514  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
515  // extract Xpetra and Thyra based GIDs
516  Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), false);
517  Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(), true);
518  std::vector<Teuchos::RCP<const Map>> rowXpSubMaps(1, xpsubmap);
519  std::vector<Teuchos::RCP<const Map>> rowTySubMaps(1, thysubmap);
520  // use expert constructor
521  rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
522  }
523 
524  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
525  if (colSz > 0) {
526  std::vector<Teuchos::RCP<const Map>> colXpSubMaps(colSz, Teuchos::null);
527  std::vector<Teuchos::RCP<const Map>> colTySubMaps(colSz, Teuchos::null);
528  for (size_t j = 0; j < colSz; j++) {
529  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
530  // extract Xpetra and Thyra based merged GIDs
531  colXpSubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, false);
532  colTySubMaps[j] = mergeSubBlockMaps(colSubMgr, bmat, true);
533  TEUCHOS_ASSERT(colXpSubMaps[j].is_null() == false);
534  TEUCHOS_ASSERT(colTySubMaps[j].is_null() == false);
535  }
536  // use expert constructor
537  doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
538  } else {
539  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
540  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
541  // extract Xpetra and Thyra based GIDs
542  Teuchos::RCP<const Map> xpsubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), false);
543  Teuchos::RCP<const Map> tysubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(), true);
544  std::vector<Teuchos::RCP<const Map>> colXpSubMaps(1, xpsubmap);
545  std::vector<Teuchos::RCP<const Map>> colTySubMaps(1, tysubmap);
546  // use expert constructor
547  doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
548  }
549 
550  // TODO matrix should have both rowMgr and colMgr??
551  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor, doMapExtractor, 33, rowMgr, bmat));
552 
553  size_t cntNNZ = 0;
554 
555  if (rowSz == 0 && colSz > 0) {
556  for (size_t j = 0; j < colSz; j++) {
557  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
558  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowMgr, colSubMgr, bmat);
559  rbmat->setMatrix(0, j, Teuchos::rcp_const_cast<Matrix>(submat));
560  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
561  }
562  } else if (rowSz > 0 && colSz == 0) {
563  for (size_t i = 0; i < rowSz; i++) {
564  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
565  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colMgr, bmat);
566  rbmat->setMatrix(i, 0, Teuchos::rcp_const_cast<Matrix>(submat));
567  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
568  }
569  } else {
570  for (size_t i = 0; i < rowSz; i++) {
571  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
572  for (size_t j = 0; j < colSz; j++) {
573  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
574  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colSubMgr, bmat);
575  rbmat->setMatrix(i, j, Teuchos::rcp_const_cast<Matrix>(submat));
576  if (submat != Teuchos::null) cntNNZ += submat->getLocalNumEntries();
577  }
578  }
579  }
580  TEUCHOS_ASSERT(rbmat->getLocalNumEntries() == cntNNZ);
581  }
582 
583  rbmat->fillComplete();
584  return rbmat;
585 }
586 
587 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
588 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) {
589  TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == bmat->getDomainMapExtractor()->getThyraMode());
590  Teuchos::RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> rbmat = Teuchos::null;
591  if (bmat->getRangeMapExtractor()->getThyraMode() == false) {
592  rbmat = mergeSubBlocks(brm, brm, bmat);
593  } else {
594  rbmat = mergeSubBlocksThyra(brm, brm, bmat);
595  }
596 
597  // TAW, 6/7/2016: rbmat might be Teuchos::null for empty blocks!
598  return rbmat;
599 }
600 
601 } // namespace Xpetra
602 
603 #define XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
604 #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...
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.
virtual size_t Cols() const
number of column blocks
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< 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)
virtual size_t Rows() const
number of row blocks
const RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
std::string description() const
Return a simple one-line description of this object.
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
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 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.