All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 <Kokkos_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 
61 
66 namespace Xpetra {
67 
68  typedef std::string viewLabel_t;
69 
70  template <class Scalar,
71  class LocalOrdinal,
72  class GlobalOrdinal,
75  public BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
76  public:
77  typedef Scalar scalar_type;
78  typedef LocalOrdinal local_ordinal_type;
79  typedef GlobalOrdinal global_ordinal_type;
80  typedef Node node_type;
81 
82  private:
83 #undef XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
84 #include "Xpetra_UseShortNames.hpp"
85 
86  public:
87 
89 
90 
92 
103  size_t npr,
107  : Xpetra::BlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(rangeMaps, domainMaps, npr,pftype) {
108  brm_ = brm;
109  fullOp_ = bmat;
110  }
111 
112  //protected:
113 
116 
118 
119  private:
121  RCP<const MapExtractor> fullRangeMapExtractor = fullOp_->getRangeMapExtractor();
122 
123  // number of sub blocks
124  size_t numBlocks = brm->GetNumBlocks();
125 
126  Teuchos::RCP<const Map> map = Teuchos::null;
127 
128  if(numBlocks == 0) {
129  // it is a leaf node
130  Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
131 
132  // never extract Thyra style maps (since we have to merge them)
133  map = fullRangeMapExtractor->getMap(Teuchos::as<size_t>(leaf->GetIndex()), false);
134  } else {
135  // initialize vector for sub maps
136  std::vector<Teuchos::RCP<const Map> > subMaps (numBlocks, Teuchos::null);
137 
138  for(size_t i = 0; i < numBlocks; i++) {
139  Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
140  subMaps[i] = mergeSubBlockMaps(blkMgr);
141  TEUCHOS_ASSERT(subMaps[i].is_null()==false);
142  }
143 
144  map = MapUtils::concatenateMaps(subMaps);
145  }
146  TEUCHOS_ASSERT(map.is_null()==false);
147  return map;
148  }
149 
150  public:
152 
153 
155 
158  virtual void apply(const MultiVector& X, MultiVector& Y,
160  Scalar alpha = ScalarTraits<Scalar>::one(),
161  Scalar beta = ScalarTraits<Scalar>::zero()) const
162  {
163 
164  // Nested sub-operators should just use the provided X and B vectors
165  if(fullOp_->getNodeNumRows() != this->getNodeNumRows()) {
167  return;
168  }
169 
170  // Special handling for the top level of the nested operator
171 
172  // check whether input parameters are blocked or not
173  RCP<const MultiVector> refX = rcpFromRef(X);
174  RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(refX);
175  RCP<MultiVector> tmpY = rcpFromRef(Y);
176  RCP<BlockedMultiVector> tmpbY = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(tmpY);
177 
178 
179  bool bCopyResultX = false;
180  bool bCopyResultY = false;
181 
182  // TODO create a nested ReorderedBlockedMultiVector out of a nested BlockedMultiVector!
183  // probably not necessary, is it?
184  // check whether X and B are blocked but not ReorderedBlocked operators
185  /*if (refbX != Teuchos::null && fullOp_->getNodeNumRows() == this->getNodeNumRows()) {
186  RCP<const ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<const ReorderedBlockedMultiVector>(refbX);
187  if(rbCheck == Teuchos::null) {
188  RCP<const BlockedMultiVector> bX =
189  Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, refbX));
190  TEUCHOS_ASSERT(bX.is_null()==false);
191  refbX.swap(bX);
192  }
193  }
194  if (tmpbY != Teuchos::null && fullOp_->getNodeNumRows() == this->getNodeNumRows()) {
195  RCP<ReorderedBlockedMultiVector> rbCheck = Teuchos::rcp_dynamic_cast<ReorderedBlockedMultiVector>(tmpbY);
196  if(rbCheck == Teuchos::null) {
197  RCP<BlockedMultiVector> bY =
198  Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbY));
199  TEUCHOS_ASSERT(bY.is_null()==false);
200  tmpbY.swap(bY);
201  }
202  }*/
203 
204  // if X and B are not blocked, create a blocked version here and use the blocked vectors
205  // for the internal (nested) apply call.
206 
207  // Check whether "this" operator is the reordered variant of the underlying fullOp_.
208  // Note, that nested ReorderedBlockedCrsMatrices always have the same full operator "fullOp_"
209  // stored underneath for being able to "translate" the block ids.
210  if (refbX == Teuchos::null && fullOp_->getNodeNumRows() == this->getNodeNumRows())
211  {
212  // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
213  RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
214  TEUCHOS_ASSERT(blkRgMap.is_null()==false);
215  RCP<const BlockedMultiVector> bXtemp = Teuchos::rcp(new BlockedMultiVector(blkRgMap, refX));
216  TEUCHOS_ASSERT(bXtemp.is_null()==false);
218  Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, bXtemp));
219  TEUCHOS_ASSERT(bX.is_null()==false);
220  refbX.swap(bX);
221  bCopyResultX = true;
222  }
223 
224  if (tmpbY == Teuchos::null && fullOp_->getNodeNumRows() == this->getNodeNumRows()) {
225  // create a new (non-nested) blocked multi vector (using the blocked range map of fullOp_)
226  RCP<const BlockedMap> blkRgMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(fullOp_->getRangeMap());
227  TEUCHOS_ASSERT(blkRgMap.is_null()==false);
228  RCP<BlockedMultiVector> tmpbYtemp = Teuchos::rcp(new BlockedMultiVector(blkRgMap, tmpY));
229  TEUCHOS_ASSERT(tmpbYtemp.is_null()==false);
231  Teuchos::rcp_dynamic_cast<BlockedMultiVector>(Xpetra::buildReorderedBlockedMultiVector(brm_, tmpbYtemp));
232  TEUCHOS_ASSERT(bY.is_null()==false);
233  tmpbY.swap(bY);
234  bCopyResultY = true;
235  }
236 
237  TEUCHOS_ASSERT(refbX.is_null()==false);
238  TEUCHOS_ASSERT(tmpbY.is_null()==false);
239 
241 
242  if (bCopyResultX == true) {
243  RCP<const MultiVector> Xmerged = refbX->Merge();
244  RCP<MultiVector> nonconstX = Teuchos::rcp_const_cast<MultiVector>(refX);
246  }
247  if (bCopyResultY == true) {
248  RCP< MultiVector> Ymerged = tmpbY->Merge();
250  }
251 
252  }
253 
254  // @}
255 
256 
257 
259 
260 
263 
264  // @}
265 
267 
268 
270  std::string description() const { return "ReorderedBlockedCrsMatrix"; }
271 
275 
276  out << "Xpetra::ReorderedBlockedCrsMatrix: " << BlockedCrsMatrix::Rows() << " x " << BlockedCrsMatrix::Cols() << std::endl;
277 
279  out << "ReorderedBlockMatrix is fillComplete" << std::endl;
280 
281  out << "fullRowMap" << std::endl;
282  BlockedCrsMatrix::getRangeMap(0,false)->describe(out,verbLevel);
283 
284  //out << "fullColMap" << std::endl;
285  //fullcolmap_->describe(out,verbLevel);
286 
287  } else {
288  out << "Xpetra::ReorderedBlockedCrsMatrix is NOT fillComplete" << std::endl;
289  }
290 
291  for (size_t r = 0; r < BlockedCrsMatrix::Rows(); ++r)
292  for (size_t c = 0; c < BlockedCrsMatrix::Cols(); ++c) {
293  out << "Block(" << r << "," << c << ")" << std::endl;
294  BlockedCrsMatrix::getMatrix(r,c)->describe(out,verbLevel);
295  }
296  }
297 
299 
300  private:
303 
304 
305 };
306 
307 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
310 
311  // TODO distinguish between range and domain map extractor! provide MapExtractor as parameter!
312  RCP<const Xpetra::MapExtractor<Scalar,LocalOrdinal,GlobalOrdinal,Node> > fullRangeMapExtractor = bmat->getRangeMapExtractor();
313 
314  // number of sub blocks
315  size_t numBlocks = brm->GetNumBlocks();
316 
318 
319  if(numBlocks == 0) {
320  // it is a leaf node
321  Teuchos::RCP<const Xpetra::BlockReorderLeaf> leaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(brm);
322 
323  map = fullRangeMapExtractor->getMap(Teuchos::as<size_t>(leaf->GetIndex()), bThyraMode);
324  } else {
325  // initialize vector for sub maps
326  std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > > subMaps (numBlocks, Teuchos::null);
327 
328  for(size_t i = 0; i < numBlocks; i++) {
329  Teuchos::RCP<const Xpetra::BlockReorderManager> blkMgr = brm->GetBlock(Teuchos::as<int>(i));
330  subMaps[i] = mergeSubBlockMaps(blkMgr,bmat,bThyraMode);
331  TEUCHOS_ASSERT(subMaps[i].is_null()==false);
332  }
333 
334 #if 1
335  // concatenate submaps
336  // for Thyra mode this map isn't important
338 
339  // create new BlockedMap (either in Thyra Mode or Xpetra mode)
340  map = Teuchos::rcp(new Xpetra::BlockedMap<LocalOrdinal,GlobalOrdinal,Node>(fullMap, subMaps, bThyraMode));
341 #else
342  // TAW: 11/27/16 we just concatenate the submaps to one monolithic Map object.
343  // Alternatively, we could create a new BlockedMap using the concatenated map and the submaps
344  // However, the block smoothers only need the concatenated map for creating MultiVectors...
345  // But for the Thyra mode version concatenating would not be ok for the whole map
346  map = MapUtils::concatenateMaps(subMaps);
347 #endif
348  }
349  TEUCHOS_ASSERT(map.is_null()==false);
350  return map;
351 }
352 
353 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
355 
362 
363  // number of sub blocks
364  size_t rowSz = rowMgr->GetNumBlocks();
365  size_t colSz = colMgr->GetNumBlocks();
366 
367  Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
368 
369  if(rowSz == 0 && colSz == 0) {
370  // it is a leaf node
371  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
372  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
373 
374  // extract leaf node
375  Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
376 
377  if (mat == Teuchos::null) return Teuchos::null;
378 
379  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
381  if(matwrap != Teuchos::null) {
382  // If the leaf node is of type Xpetra::CrsMatrixWrap wrap it into a 1x1 ReorderedBlockMatrix
383  // with the corresponding MapExtractors for translating Thyra to Xpetra GIDs if necessary
384  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
385  Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(),false);
386  std::vector<Teuchos::RCP<const Map> > rowSubMaps (1, submap);
387  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
388 
389  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
390  Teuchos::RCP<const Map> submap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(),false);
391  std::vector<Teuchos::RCP<const Map> > colSubMaps (1, submap2);
392  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(submap2, colSubMaps, false));
393 
394  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor,doMapExtractor, 33, rowMgr,bmat));
395  rbmat->setMatrix(0,0,mat);
396  } else {
397  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
398  rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
399  TEUCHOS_ASSERT(rbmat != Teuchos::null);
400  }
401  TEUCHOS_ASSERT(mat->getNodeNumEntries() == rbmat->getNodeNumEntries());
402  } else {
403  // create the map extractors
404  // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
405  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
406  if(rowSz > 0) {
407  std::vector<Teuchos::RCP<const Map> > rowSubMaps (rowSz, Teuchos::null);
408  for(size_t i = 0; i < rowSz; i++) {
409  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
410  rowSubMaps[i] = mergeSubBlockMaps(rowSubMgr,bmat,false /*xpetra*/);
411  TEUCHOS_ASSERT(rowSubMaps[i].is_null()==false);
412  }
413  Teuchos::RCP<const Map> rgMergedSubMaps = MapUtils::concatenateMaps(rowSubMaps);
414  rgMapExtractor = Teuchos::rcp(new MapExtractor(rgMergedSubMaps, rowSubMaps, false));
415  } else {
416  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
417  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
418  // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
419  // The GIDs might not start with 0 and may not be consecutive!
420  Teuchos::RCP<const Map> submap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(),false);
421  std::vector<Teuchos::RCP<const Map> > rowSubMaps (1, submap);
422  rgMapExtractor = Teuchos::rcp(new MapExtractor(submap, rowSubMaps, false));
423  }
424 
425  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
426  if(colSz > 0) {
427  std::vector<Teuchos::RCP<const Map> > colSubMaps (colSz, Teuchos::null);
428  for(size_t j = 0; j < colSz; j++) {
429  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
430  colSubMaps[j] = mergeSubBlockMaps(colSubMgr,bmat,false/*xpetra*/);
431  TEUCHOS_ASSERT(colSubMaps[j].is_null()==false);
432  }
433  Teuchos::RCP<const Map> doMergedSubMaps = MapUtils::concatenateMaps(colSubMaps);
434  doMapExtractor = Teuchos::rcp(new MapExtractor(doMergedSubMaps, colSubMaps, false));
435  } else {
436  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
437  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
438  // TODO think about Thyra style maps: we cannot use thyra style maps when recombining several blocks!!!
439  // The GIDs might not start with 0 and may not be consecutive!
440  Teuchos::RCP<const Map> submap = fullDomainMapExtractor->getMap(colleaf->GetIndex(),false);
441  std::vector<Teuchos::RCP<const Map> > colSubMaps (1, submap);
442  doMapExtractor = Teuchos::rcp(new MapExtractor(submap, colSubMaps, false));
443  }
444 
445  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor,doMapExtractor, 33, rowMgr,bmat));
446 
447  size_t cntNNZ = 0;
448 
449  if (rowSz == 0 && colSz > 0) {
450  for(size_t j = 0; j < colSz; j++) {
451  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
452  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowMgr, colSubMgr, bmat);
453  rbmat->setMatrix(0,j,Teuchos::rcp_const_cast<Matrix>(submat));
454  if(submat != Teuchos::null) cntNNZ += submat->getNodeNumEntries();
455  }
456  } else if (rowSz > 0 && colSz == 0) {
457  for(size_t i = 0; i < rowSz; i++) {
458  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
459  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colMgr, bmat);
460  rbmat->setMatrix(i,0,Teuchos::rcp_const_cast<Matrix>(submat));
461  if(submat != Teuchos::null) cntNNZ += submat->getNodeNumEntries();
462  }
463  } else {
464  for(size_t i = 0; i < rowSz; i++) {
465  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
466  for(size_t j = 0; j < colSz; j++) {
467  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
468  Teuchos::RCP<const Matrix> submat = mergeSubBlocks(rowSubMgr, colSubMgr, bmat);
469  rbmat->setMatrix(i,j,Teuchos::rcp_const_cast<Matrix>(submat));
470  if(submat != Teuchos::null) cntNNZ += submat->getNodeNumEntries();
471  }
472  }
473  }
474  TEUCHOS_ASSERT(rbmat->getNodeNumEntries() == cntNNZ);
475  }
476  rbmat->fillComplete();
477  return rbmat;
478 }
479 
480  //MapExtractor(const std::vector<RCP<const Map> >& maps, const std::vector<RCP<const Map> >& thyramaps);
481 
482 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
484 
490 
491  TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == true);
492  TEUCHOS_ASSERT(bmat->getDomainMapExtractor()->getThyraMode() == true);
493 
494  // number of sub blocks
495  size_t rowSz = rowMgr->GetNumBlocks();
496  size_t colSz = colMgr->GetNumBlocks();
497 
498  Teuchos::RCP<BlockedCrsMatrix> rbmat = Teuchos::null;
499 
500  if(rowSz == 0 && colSz == 0) {
501  // it is a leaf node
502  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
503  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
504 
505  // this matrix uses Thyra style GIDs as global row, range, domain and column indices
506  Teuchos::RCP<Matrix> mat = bmat->getMatrix(rowleaf->GetIndex(), colleaf->GetIndex());
507 
508  if(mat == Teuchos::null) return Teuchos::null; //std::cout << "Block " << rowleaf->GetIndex() << "," << colleaf->GetIndex() << " is zero" << std::endl;
509 
510  // check, whether leaf node is of type Xpetra::CrsMatrixWrap
512  if(matwrap != Teuchos::null) {
514  // build map extractors
515  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
516  // extract Xpetra and Thyra based GIDs
517  Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(),false);
518  Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(),true);
519  std::vector<Teuchos::RCP<const Map> > rowXpSubMaps (1, xpsubmap);
520  std::vector<Teuchos::RCP<const Map> > rowTySubMaps (1, thysubmap);
521  // use expert constructor
522  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
523 
524  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
525  // extract Xpetra and Thyra based GIDs
526  Teuchos::RCP<const Map> xpsubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(),false);
527  Teuchos::RCP<const Map> tysubmap2 = fullDomainMapExtractor->getMap(colleaf->GetIndex(),true);
528  std::vector<Teuchos::RCP<const Map> > colXpSubMaps (1, xpsubmap2);
529  std::vector<Teuchos::RCP<const Map> > colTySubMaps (1, tysubmap2);
530  // use expert constructor
531  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
532 
534  // build reordered block operator
535  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor,doMapExtractor, 33, rowMgr,bmat));
536  rbmat->setMatrix(0,0,mat);
537  } else {
538  // If leaf node is already wrapped into a blocked matrix do not wrap it again.
539  rbmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
540  TEUCHOS_ASSERT(rbmat != Teuchos::null);
541  }
542  TEUCHOS_ASSERT(mat->getNodeNumEntries() == rbmat->getNodeNumEntries());
543  } else {
544  // create the map extractors
545  // we cannot create block matrix in thyra mode since merged maps might not start with 0 GID
546  Teuchos::RCP<const MapExtractor> rgMapExtractor = Teuchos::null;
547  if(rowSz > 0) {
548  std::vector<Teuchos::RCP<const Map> > rowXpSubMaps (rowSz, Teuchos::null);
549  std::vector<Teuchos::RCP<const Map> > rowTySubMaps (rowSz, Teuchos::null);
550  for(size_t i = 0; i < rowSz; i++) {
551  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
552  // extract Xpetra and Thyra based merged GIDs
553  rowXpSubMaps[i] = mergeSubBlockMaps(rowSubMgr,bmat,false);
554  rowTySubMaps[i] = mergeSubBlockMaps(rowSubMgr,bmat,true);
555  TEUCHOS_ASSERT(rowXpSubMaps[i].is_null()==false);
556  TEUCHOS_ASSERT(rowTySubMaps[i].is_null()==false);
557  }
558  // use expert constructor
559  rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
560  } else {
561  Teuchos::RCP<const Xpetra::BlockReorderLeaf> rowleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(rowMgr);
562  RCP<const MapExtractor> fullRangeMapExtractor = bmat->getRangeMapExtractor();
563  // extract Xpetra and Thyra based GIDs
564  Teuchos::RCP<const Map> xpsubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(),false);
565  Teuchos::RCP<const Map> thysubmap = fullRangeMapExtractor->getMap(rowleaf->GetIndex(),true);
566  std::vector<Teuchos::RCP<const Map> > rowXpSubMaps (1, xpsubmap);
567  std::vector<Teuchos::RCP<const Map> > rowTySubMaps (1, thysubmap);
568  // use expert constructor
569  rgMapExtractor = Teuchos::rcp(new MapExtractor(rowXpSubMaps, rowTySubMaps));
570  }
571 
572  Teuchos::RCP<const MapExtractor> doMapExtractor = Teuchos::null;
573  if(colSz > 0) {
574  std::vector<Teuchos::RCP<const Map> > colXpSubMaps (colSz, Teuchos::null);
575  std::vector<Teuchos::RCP<const Map> > colTySubMaps (colSz, Teuchos::null);
576  for(size_t j = 0; j < colSz; j++) {
577  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
578  // extract Xpetra and Thyra based merged GIDs
579  colXpSubMaps[j] = mergeSubBlockMaps(colSubMgr,bmat,false);
580  colTySubMaps[j] = mergeSubBlockMaps(colSubMgr,bmat,true);
581  TEUCHOS_ASSERT(colXpSubMaps[j].is_null()==false);
582  TEUCHOS_ASSERT(colTySubMaps[j].is_null()==false);
583  }
584  // use expert constructor
585  doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps,colTySubMaps));
586  } else {
587  Teuchos::RCP<const Xpetra::BlockReorderLeaf> colleaf = Teuchos::rcp_dynamic_cast<const Xpetra::BlockReorderLeaf>(colMgr);
588  RCP<const MapExtractor> fullDomainMapExtractor = bmat->getDomainMapExtractor();
589  // extract Xpetra and Thyra based GIDs
590  Teuchos::RCP<const Map> xpsubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(),false);
591  Teuchos::RCP<const Map> tysubmap = fullDomainMapExtractor->getMap(colleaf->GetIndex(),true);
592  std::vector<Teuchos::RCP<const Map> > colXpSubMaps (1, xpsubmap);
593  std::vector<Teuchos::RCP<const Map> > colTySubMaps (1, tysubmap);
594  // use expert constructor
595  doMapExtractor = Teuchos::rcp(new MapExtractor(colXpSubMaps, colTySubMaps));
596  }
597 
598  // TODO matrix should have both rowMgr and colMgr??
599  rbmat = Teuchos::rcp(new ReorderedBlockedCrsMatrix(rgMapExtractor,doMapExtractor, 33, rowMgr,bmat));
600 
601  size_t cntNNZ = 0;
602 
603  if (rowSz == 0 && colSz > 0) {
604  for(size_t j = 0; j < colSz; j++) {
605  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
606  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowMgr, colSubMgr, bmat);
607  rbmat->setMatrix(0,j,Teuchos::rcp_const_cast<Matrix>(submat));
608  if(submat != Teuchos::null) cntNNZ += submat->getNodeNumEntries();
609  }
610  } else if (rowSz > 0 && colSz == 0) {
611  for(size_t i = 0; i < rowSz; i++) {
612  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
613  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colMgr, bmat);
614  rbmat->setMatrix(i,0,Teuchos::rcp_const_cast<Matrix>(submat));
615  if(submat != Teuchos::null) cntNNZ += submat->getNodeNumEntries();
616  }
617  } else {
618  for(size_t i = 0; i < rowSz; i++) {
619  Teuchos::RCP<const Xpetra::BlockReorderManager> rowSubMgr = rowMgr->GetBlock(Teuchos::as<int>(i));
620  for(size_t j = 0; j < colSz; j++) {
621  Teuchos::RCP<const Xpetra::BlockReorderManager> colSubMgr = colMgr->GetBlock(Teuchos::as<int>(j));
622  Teuchos::RCP<const Matrix> submat = mergeSubBlocksThyra(rowSubMgr, colSubMgr, bmat);
623  rbmat->setMatrix(i,j,Teuchos::rcp_const_cast<Matrix>(submat));
624  if(submat != Teuchos::null) cntNNZ += submat->getNodeNumEntries();
625  }
626  }
627  }
628  TEUCHOS_ASSERT(rbmat->getNodeNumEntries() == cntNNZ);
629  }
630 
631  rbmat->fillComplete();
632  return rbmat;
633 }
634 
635 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
637  TEUCHOS_ASSERT(bmat->getRangeMapExtractor()->getThyraMode() == bmat->getDomainMapExtractor()->getThyraMode());
639  if(bmat->getRangeMapExtractor()->getThyraMode() == false) {
640  rbmat = mergeSubBlocks(brm, brm, bmat);
641  } else {
642  rbmat = mergeSubBlocksThyra(brm, brm, bmat);
643  }
644 
645  // TAW, 6/7/2016: rbmat might be Teuchos::null for empty blocks!
646  return rbmat;
647 }
648 
649 } //namespace Xpetra
650 
651 #define XPETRA_REORDEREDBLOCKEDCRSMATRIX_SHORT
652 #endif /* XPETRA_REORDEREDBLOCKEDCRSMATRIX_HPP */
virtual size_t getNodeNumEntries() const =0
Returns the local number of entries in this matrix.
bool is_null(const boost::shared_ptr< T > &p)
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)
bool isFillComplete() const
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
void fillComplete(const RCP< const Map > &domainMap, const RCP< const Map > &rangeMap, const RCP< ParameterList > &params=null)
Signal that data entry is complete.
RCP< const Map > getRangeMap() const
Returns the Map associated with the range of this operator.
Teuchos::RCP< const Xpetra::BlockedCrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > fullOp_
void swap(RCP< T > &r_ptr)
size_t getNodeNumEntries() const
Returns the local number of entries in this matrix.
Xpetra utility class for common map-related routines.
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.
Teuchos::RCP< const Xpetra::BlockReorderManager > getBlockReorderManager()
Returns internal BlockReorderManager 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.
BlockedCrsMatrix(const Teuchos::RCP< const BlockedMap > &rangeMaps, const Teuchos::RCP< const BlockedMap > &domainMaps, size_t npr, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
Constructor.
int GetIndex() const
Get the index that is stored in this block/leaf.
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 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.
virtual size_t GetNumBlocks() const
Returns number of subblocks.
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_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
virtual const Teuchos::RCP< BlockReorderManager > GetBlock(int blockIndex)
Get a particular block. If there is no block at this index location return a new one.
virtual size_t Cols() const
number of column blocks
std::string viewLabel_t
static const EVerbosityLevel verbLevel_default
std::string description() const
Return a simple one-line description of this object.
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)
Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > mergeSubBlockMaps(Teuchos::RCP< const Xpetra::BlockReorderManager > brm)
void setMatrix(size_t r, size_t c, Teuchos::RCP< Matrix > mat)
set matrix block
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.
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, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
Constructor.
virtual size_t Rows() const
number of row blocks
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)
#define TEUCHOS_ASSERT(assertion_test)
const RCP< const Map > getMap(size_t i, bool bThyraMode=false) const
size_t getNodeNumRows() const
Returns the number of matrix rows owned on the calling node.
Xpetra-specific matrix class.
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.
Teuchos::RCP< const Xpetra::BlockReorderManager > brm_
bool is_null() const