Xpetra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Xpetra_BlockedCrsMatrix.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_BLOCKEDCRSMATRIX_HPP
47 #define XPETRA_BLOCKEDCRSMATRIX_HPP
48 
49 #include <Tpetra_KokkosCompat_DefaultNode.hpp>
50 
51 #include <Teuchos_SerialDenseMatrix.hpp>
52 #include <Teuchos_Hashtable.hpp>
53 
54 #include "Xpetra_ConfigDefs.hpp"
55 #include "Xpetra_Exceptions.hpp"
56 
57 #include "Xpetra_MapFactory.hpp"
58 #include "Xpetra_MultiVector.hpp"
59 #include "Xpetra_BlockedMultiVector.hpp"
60 #include "Xpetra_MultiVectorFactory.hpp"
61 #include "Xpetra_BlockedVector.hpp"
62 #include "Xpetra_CrsGraph.hpp"
63 #include "Xpetra_CrsMatrix.hpp"
65 
66 #include "Xpetra_MapExtractor.hpp"
68 
69 #include "Xpetra_Matrix.hpp"
70 #include "Xpetra_MatrixFactory.hpp"
71 #include "Xpetra_CrsMatrixWrap.hpp"
72 
73 #ifdef HAVE_XPETRA_THYRA
74 #include <Thyra_ProductVectorSpaceBase.hpp>
75 #include <Thyra_VectorSpaceBase.hpp>
76 #include <Thyra_LinearOpBase.hpp>
77 #include <Thyra_BlockedLinearOpBase.hpp>
78 #include <Thyra_PhysicallyBlockedLinearOpBase.hpp>
79 #include "Xpetra_ThyraUtils.hpp"
80 #endif
81 
82 #include "Xpetra_VectorFactory.hpp"
83 
88 namespace Xpetra {
89 
90 #ifdef HAVE_XPETRA_THYRA
91 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
92 class ThyraUtils;
93 #endif
94 
95 typedef std::string viewLabel_t;
96 
97 template <class Scalar,
98  class LocalOrdinal,
99  class GlobalOrdinal,
100  class Node = Tpetra::KokkosClassic::DefaultNode::DefaultNodeType>
101 class BlockedCrsMatrix : public Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
102  public:
103  typedef Scalar scalar_type;
104  typedef LocalOrdinal local_ordinal_type;
105  typedef GlobalOrdinal global_ordinal_type;
106  typedef Node node_type;
107 
108  private:
109 #undef XPETRA_BLOCKEDCRSMATRIX_SHORT
110 #include "Xpetra_UseShortNames.hpp"
111 
112  public:
114 
115 
117 
122  BlockedCrsMatrix(const Teuchos::RCP<const BlockedMap>& rangeMaps,
123  const Teuchos::RCP<const BlockedMap>& domainMaps,
124  size_t numEntriesPerRow)
125  : is_diagonal_(true) {
128  bRangeThyraMode_ = rangeMaps->getThyraMode();
129  bDomainThyraMode_ = domainMaps->getThyraMode();
130 
131  blocks_.reserve(Rows() * Cols());
132 
133  // add CrsMatrix objects in row,column order
134  for (size_t r = 0; r < Rows(); ++r)
135  for (size_t c = 0; c < Cols(); ++c)
136  blocks_.push_back(MatrixFactory::Build(getRangeMap(r, bRangeThyraMode_), numEntriesPerRow));
137 
138  // Default view
140  }
141 
143 
150  BlockedCrsMatrix(Teuchos::RCP<const MapExtractor>& rangeMapExtractor,
151  Teuchos::RCP<const MapExtractor>& domainMapExtractor,
152  size_t numEntriesPerRow)
153  : is_diagonal_(true)
154  , domainmaps_(domainMapExtractor)
155  , rangemaps_(rangeMapExtractor) {
156  bRangeThyraMode_ = rangeMapExtractor->getThyraMode();
157  bDomainThyraMode_ = domainMapExtractor->getThyraMode();
158 
159  blocks_.reserve(Rows() * Cols());
160 
161  // add CrsMatrix objects in row,column order
162  for (size_t r = 0; r < Rows(); ++r)
163  for (size_t c = 0; c < Cols(); ++c)
164  blocks_.push_back(MatrixFactory::Build(getRangeMap(r, bRangeThyraMode_), numEntriesPerRow));
165 
166  // Default view
168  }
169 
170 #ifdef HAVE_XPETRA_THYRA
171 
177  BlockedCrsMatrix(const Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> >& thyraOp, const Teuchos::RCP<const Teuchos::Comm<int> >& /* comm */)
178  : is_diagonal_(true)
179  , thyraOp_(thyraOp) {
180  // extract information from Thyra blocked operator and rebuilt information
181  const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productRangeSpace = thyraOp->productRange();
182  const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productDomainSpace = thyraOp->productDomain();
183 
184  int numRangeBlocks = productRangeSpace->numBlocks();
185  int numDomainBlocks = productDomainSpace->numBlocks();
186 
187  // build range map extractor from Thyra::BlockedLinearOpBase object
188  std::vector<Teuchos::RCP<const Map> > subRangeMaps(numRangeBlocks);
189  for (size_t r = 0; r < Teuchos::as<size_t>(numRangeBlocks); ++r) {
190  for (size_t c = 0; c < Teuchos::as<size_t>(numDomainBlocks); ++c) {
191  if (thyraOp->blockExists(r, c)) {
192  // we only need at least one block in each block row to extract the range map
193  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r, c); // nonConst access is not allowed.
194  Teuchos::RCP<const Xpetra::Matrix<Scalar, LO, GO, Node> > xop =
196  subRangeMaps[r] = xop->getRangeMap();
197  if (r != c) is_diagonal_ = false;
198  break;
199  }
200  }
201  }
202  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > fullRangeMap = mergeMaps(subRangeMaps);
203 
204  // check whether the underlying Thyra operator uses Thyra-style numbering (default for most applications) or
205  // Xpetra style numbering
206  bool bRangeUseThyraStyleNumbering = false;
207  size_t numAllElements = 0;
208  for (size_t v = 0; v < subRangeMaps.size(); ++v) {
209  numAllElements += subRangeMaps[v]->getGlobalNumElements();
210  }
211  if (fullRangeMap->getGlobalNumElements() != numAllElements) bRangeUseThyraStyleNumbering = true;
212  rangemaps_ = Teuchos::rcp(new Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>(fullRangeMap, subRangeMaps, bRangeUseThyraStyleNumbering));
213 
214  // build domain map extractor from Thyra::BlockedLinearOpBase object
215  std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > > subDomainMaps(numDomainBlocks);
216  for (size_t c = 0; c < Teuchos::as<size_t>(numDomainBlocks); ++c) {
217  for (size_t r = 0; r < Teuchos::as<size_t>(numRangeBlocks); ++r) {
218  if (thyraOp->blockExists(r, c)) {
219  // we only need at least one block in each block row to extract the range map
220  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r, c); // nonConst access is not allowed.
221  Teuchos::RCP<const Xpetra::Matrix<Scalar, LO, GO, Node> > xop =
223  subDomainMaps[c] = xop->getDomainMap();
224  break;
225  }
226  }
227  }
228  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > fullDomainMap = mergeMaps(subDomainMaps);
229  // plausibility check for numbering style (Xpetra or Thyra)
230  bool bDomainUseThyraStyleNumbering = false;
231  numAllElements = 0;
232  for (size_t v = 0; v < subDomainMaps.size(); ++v) {
233  numAllElements += subDomainMaps[v]->getGlobalNumElements();
234  }
235  if (fullDomainMap->getGlobalNumElements() != numAllElements) bDomainUseThyraStyleNumbering = true;
236  domainmaps_ = Teuchos::rcp(new Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node>(fullDomainMap, subDomainMaps, bDomainUseThyraStyleNumbering));
237 
238  // store numbering mode
239  bRangeThyraMode_ = bRangeUseThyraStyleNumbering;
240  bDomainThyraMode_ = bDomainUseThyraStyleNumbering;
241 
242  // add CrsMatrix objects in row,column order
243  blocks_.reserve(Rows() * Cols());
244  for (size_t r = 0; r < Rows(); ++r) {
245  for (size_t c = 0; c < Cols(); ++c) {
246  if (thyraOp->blockExists(r, c)) {
247  // TODO we do not support nested Thyra operators here!
248  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r, c); // nonConst access is not allowed.
249  Teuchos::RCP<Thyra::LinearOpBase<Scalar> > op = Teuchos::rcp_const_cast<Thyra::LinearOpBase<Scalar> >(const_op); // cast away const
250  Teuchos::RCP<Xpetra::Matrix<Scalar, LO, GO, Node> > xop =
252  Teuchos::RCP<Xpetra::CrsMatrixWrap<Scalar, LO, GO, Node> > xwrap =
253  Teuchos::rcp_dynamic_cast<Xpetra::CrsMatrixWrap<Scalar, LO, GO, Node> >(xop, true);
254  blocks_.push_back(xwrap);
255  } else {
256  // add empty block
258  }
259  }
260  }
261  // Default view
263  }
264 
265  private:
267 
274  Teuchos::RCP<const Map> mergeMaps(std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > >& subMaps) {
275  // TODO merging for Thyra mode is missing (similar to what we do in constructor of MapExtractor
276 
277  // merge submaps to global map
278  std::vector<GlobalOrdinal> gids;
279  for (size_t tt = 0; tt < subMaps.size(); ++tt) {
280  Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > subMap = subMaps[tt];
281 #if 1
282  Teuchos::ArrayView<const GlobalOrdinal> subMapGids = subMap->getLocalElementList();
283  gids.insert(gids.end(), subMapGids.begin(), subMapGids.end());
284 #else
285  size_t myNumElements = subMap->getLocalNumElements();
286  for (LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(myNumElements); ++l) {
287  GlobalOrdinal gid = subMap->getGlobalElement(l);
288  gids.push_back(gid);
289  }
290 #endif
291  }
292 
293  // we have to sort the matrix entries and get rid of the double entries
294  // since we use this to detect Thyra-style numbering or Xpetra-style
295  // numbering. In Thyra-style numbering mode, the Xpetra::MapExtractor builds
296  // the correct row maps.
297  const GO INVALID = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
298  std::sort(gids.begin(), gids.end());
299  gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
300  Teuchos::ArrayView<GO> gidsView(&gids[0], gids.size());
301  Teuchos::RCP<Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > fullMap = Xpetra::MapFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(subMaps[0]->lib(), INVALID, gidsView, subMaps[0]->getIndexBase(), subMaps[0]->getComm());
302  return fullMap;
303  }
304 
305  public:
306 #endif
307 
309  virtual ~BlockedCrsMatrix() {}
310 
312 
314 
315 
317 
342  void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView<const GlobalOrdinal>& cols, const ArrayView<const Scalar>& vals) {
343  XPETRA_MONITOR("XpetraBlockedCrsMatrix::insertGlobalValues");
344  if (Rows() == 1 && Cols() == 1) {
345  getMatrix(0, 0)->insertGlobalValues(globalRow, cols, vals);
346  return;
347  }
348  throw Xpetra::Exceptions::RuntimeError("insertGlobalValues not supported by BlockedCrsMatrix");
349  }
350 
352 
362  void insertLocalValues(LocalOrdinal localRow, const ArrayView<const LocalOrdinal>& cols, const ArrayView<const Scalar>& vals) {
363  XPETRA_MONITOR("XpetraBlockedCrsMatrix::insertLocalValues");
364  if (Rows() == 1 && Cols() == 1) {
365  getMatrix(0, 0)->insertLocalValues(localRow, cols, vals);
366  return;
367  }
368  throw Xpetra::Exceptions::RuntimeError("insertLocalValues not supported by BlockedCrsMatrix");
369  }
370 
371  void removeEmptyProcessesInPlace(const Teuchos::RCP<const Map>& newMap) {
372  XPETRA_MONITOR("XpetraBlockedCrsMatrix::removeEmptyProcessesInPlace");
373  if (Rows() == 1 && Cols() == 1) {
374  getMatrix(0, 0)->removeEmptyProcessesInPlace(newMap);
375  return;
376  }
377  throw Xpetra::Exceptions::RuntimeError("removeEmptyProcesses not supported by BlockedCrsMatrix");
378  }
379 
381 
389  void replaceGlobalValues(GlobalOrdinal globalRow,
390  const ArrayView<const GlobalOrdinal>& cols,
391  const ArrayView<const Scalar>& vals) {
392  XPETRA_MONITOR("XpetraBlockedCrsMatrix::replaceGlobalValues");
393  if (Rows() == 1 && Cols() == 1) {
394  getMatrix(0, 0)->replaceGlobalValues(globalRow, cols, vals);
395  return;
396  }
397  throw Xpetra::Exceptions::RuntimeError("replaceGlobalValues not supported by BlockedCrsMatrix");
398  }
399 
401 
405  void replaceLocalValues(LocalOrdinal localRow,
406  const ArrayView<const LocalOrdinal>& cols,
407  const ArrayView<const Scalar>& vals) {
408  XPETRA_MONITOR("XpetraBlockedCrsMatrix::replaceLocalValues");
409  if (Rows() == 1 && Cols() == 1) {
410  getMatrix(0, 0)->replaceLocalValues(localRow, cols, vals);
411  return;
412  }
413  throw Xpetra::Exceptions::RuntimeError("replaceLocalValues not supported by BlockedCrsMatrix");
414  }
415 
417  virtual void setAllToScalar(const Scalar& alpha) {
418  XPETRA_MONITOR("XpetraBlockedCrsMatrix::setAllToScalar");
419  for (size_t row = 0; row < Rows(); row++) {
420  for (size_t col = 0; col < Cols(); col++) {
421  if (!getMatrix(row, col).is_null()) {
422  getMatrix(row, col)->setAllToScalar(alpha);
423  }
424  }
425  }
426  }
427 
429  void scale(const Scalar& alpha) {
430  XPETRA_MONITOR("XpetraBlockedCrsMatrix::scale");
431  for (size_t row = 0; row < Rows(); row++) {
432  for (size_t col = 0; col < Cols(); col++) {
433  if (!getMatrix(row, col).is_null()) {
434  getMatrix(row, col)->scale(alpha);
435  }
436  }
437  }
438  }
439 
441 
443 
444 
452  void resumeFill(const RCP<ParameterList>& params = null) {
453  XPETRA_MONITOR("XpetraBlockedCrsMatrix::resumeFill");
454  for (size_t row = 0; row < Rows(); row++) {
455  for (size_t col = 0; col < Cols(); col++) {
456  if (!getMatrix(row, col).is_null()) {
457  getMatrix(row, col)->resumeFill(params);
458  }
459  }
460  }
461  }
462 
468  void fillComplete(const RCP<const Map>& domainMap, const RCP<const Map>& rangeMap, const RCP<ParameterList>& params = null) {
469  XPETRA_MONITOR("XpetraBlockedCrsMatrix::fillComplete");
470  if (Rows() == 1 && Cols() == 1) {
471  getMatrix(0, 0)->fillComplete(domainMap, rangeMap, params);
472  return;
473  }
474  fillComplete(params);
475  }
476 
491  void fillComplete(const RCP<ParameterList>& params = null) {
492  XPETRA_MONITOR("XpetraBlockedCrsMatrix::fillComplete");
493  TEUCHOS_TEST_FOR_EXCEPTION(rangemaps_ == Teuchos::null, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::fillComplete: rangemaps_ is not set. Error.");
494 
495  for (size_t r = 0; r < Rows(); ++r)
496  for (size_t c = 0; c < Cols(); ++c) {
497  if (getMatrix(r, c) != Teuchos::null) {
498  Teuchos::RCP<Matrix> Ablock = getMatrix(r, c);
499  if (r != c) is_diagonal_ = false;
500  if (Ablock != Teuchos::null && !Ablock->isFillComplete())
501  Ablock->fillComplete(getDomainMap(c, bDomainThyraMode_), getRangeMap(r, bRangeThyraMode_), params);
502  }
503  }
504 
505 #if 0
506  // get full row map
507  RCP<const Map> rangeMap = rangemaps_->getFullMap();
508  fullrowmap_ = MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getLocalElementList(), rangeMap()->getIndexBase(), rangeMap()->getComm());
509 
510  // build full col map
511  fullcolmap_ = Teuchos::null; // delete old full column map
512 
513  std::vector<GO> colmapentries;
514  for (size_t c = 0; c < Cols(); ++c) {
515  // copy all local column lids of all block rows to colset
516  std::set<GO> colset;
517  for (size_t r = 0; r < Rows(); ++r) {
518  Teuchos::RCP<CrsMatrix> Ablock = getMatrix(r,c);
519 
520  if (Ablock != Teuchos::null) {
521  Teuchos::ArrayView<const GO> colElements = Ablock->getColMap()->getLocalElementList();
522  Teuchos::RCP<const Map> colmap = Ablock->getColMap();
523  copy(colElements.getRawPtr(), colElements.getRawPtr() + colElements.size(), inserter(colset, colset.begin()));
524  }
525  }
526 
527  // remove duplicates (entries which are in column maps of more than one block row)
528  colmapentries.reserve(colmapentries.size() + colset.size());
529  copy(colset.begin(), colset.end(), back_inserter(colmapentries));
530  sort(colmapentries.begin(), colmapentries.end());
531  typename std::vector<GO>::iterator gendLocation;
532  gendLocation = std::unique(colmapentries.begin(), colmapentries.end());
533  colmapentries.erase(gendLocation,colmapentries.end());
534  }
535 
536  // sum up number of local elements
537  size_t numGlobalElements = 0;
538  Teuchos::reduceAll(*(rangeMap->getComm()), Teuchos::REDUCE_SUM, colmapentries.size(), Teuchos::outArg(numGlobalElements));
539 
540  // store global full column map
541  const Teuchos::ArrayView<const GO> aView = Teuchos::ArrayView<const GO>(colmapentries);
542  fullcolmap_ = MapFactory::Build(rangeMap->lib(), numGlobalElements, aView, 0, rangeMap->getComm());
543 #endif
544  }
545 
547 
549 
552  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getGlobalNumRows");
553  global_size_t globalNumRows = 0;
554 
555  for (size_t row = 0; row < Rows(); row++)
556  for (size_t col = 0; col < Cols(); col++)
557  if (!getMatrix(row, col).is_null()) {
558  globalNumRows += getMatrix(row, col)->getGlobalNumRows();
559  break; // we need only one non-null matrix in a row
560  }
561 
562  return globalNumRows;
563  }
564 
566 
569  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getGlobalNumCols");
570  global_size_t globalNumCols = 0;
571 
572  for (size_t col = 0; col < Cols(); col++)
573  for (size_t row = 0; row < Rows(); row++)
574  if (!getMatrix(row, col).is_null()) {
575  globalNumCols += getMatrix(row, col)->getGlobalNumCols();
576  break; // we need only one non-null matrix in a col
577  }
578 
579  return globalNumCols;
580  }
581 
583  size_t getLocalNumRows() const {
584  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getLocalNumRows");
585  global_size_t nodeNumRows = 0;
586 
587  for (size_t row = 0; row < Rows(); ++row)
588  for (size_t col = 0; col < Cols(); col++)
589  if (!getMatrix(row, col).is_null()) {
590  nodeNumRows += getMatrix(row, col)->getLocalNumRows();
591  break; // we need only one non-null matrix in a row
592  }
593 
594  return nodeNumRows;
595  }
596 
599  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getGlobalNumEntries");
600  global_size_t globalNumEntries = 0;
601 
602  for (size_t row = 0; row < Rows(); ++row)
603  for (size_t col = 0; col < Cols(); ++col)
604  if (!getMatrix(row, col).is_null())
605  globalNumEntries += getMatrix(row, col)->getGlobalNumEntries();
606 
607  return globalNumEntries;
608  }
609 
611  size_t getLocalNumEntries() const {
612  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getLocalNumEntries");
613  global_size_t nodeNumEntries = 0;
614 
615  for (size_t row = 0; row < Rows(); ++row)
616  for (size_t col = 0; col < Cols(); ++col)
617  if (!getMatrix(row, col).is_null())
618  nodeNumEntries += getMatrix(row, col)->getLocalNumEntries();
619 
620  return nodeNumEntries;
621  }
622 
624 
625  size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const {
626  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getNumEntriesInLocalRow");
627  GlobalOrdinal gid = this->getRowMap()->getGlobalElement(localRow);
628  size_t row = getBlockedRangeMap()->getMapIndexForGID(gid);
629  LocalOrdinal lid = getBlockedRangeMap()->getMap(row)->getLocalElement(gid);
630  size_t numEntriesInLocalRow = 0;
631  for (size_t col = 0; col < Cols(); ++col)
632  if (!getMatrix(row, col).is_null())
633  numEntriesInLocalRow += getMatrix(row, col)->getNumEntriesInLocalRow(lid);
634  return numEntriesInLocalRow;
635  }
636 
638 
639  size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const {
640  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getNumEntriesInGlobalRow");
641  size_t row = getBlockedRangeMap()->getMapIndexForGID(globalRow);
642  size_t numEntriesInGlobalRow = 0;
643  for (size_t col = 0; col < Cols(); ++col)
644  if (!getMatrix(row, col).is_null())
645  numEntriesInGlobalRow += getMatrix(row, col)->getNumEntriesInGlobalRow(globalRow);
646  return numEntriesInGlobalRow;
647  }
648 
650 
652  size_t getGlobalMaxNumRowEntries() const {
653  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getGlobalMaxNumRowEntries");
654  global_size_t globalMaxEntries = 0;
655 
656  for (size_t row = 0; row < Rows(); row++) {
657  global_size_t globalMaxEntriesBlockRows = 0;
658  for (size_t col = 0; col < Cols(); col++) {
659  if (!getMatrix(row, col).is_null()) {
660  globalMaxEntriesBlockRows += getMatrix(row, col)->getGlobalMaxNumRowEntries();
661  }
662  }
663  if (globalMaxEntriesBlockRows > globalMaxEntries)
664  globalMaxEntries = globalMaxEntriesBlockRows;
665  }
666  return globalMaxEntries;
667  }
668 
670 
672  size_t getLocalMaxNumRowEntries() const {
673  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getLocalMaxNumRowEntries");
674  size_t localMaxEntries = 0;
675 
676  for (size_t row = 0; row < Rows(); row++) {
677  size_t localMaxEntriesBlockRows = 0;
678  for (size_t col = 0; col < Cols(); col++) {
679  if (!getMatrix(row, col).is_null()) {
680  localMaxEntriesBlockRows += getMatrix(row, col)->getLocalMaxNumRowEntries();
681  }
682  }
683  if (localMaxEntriesBlockRows > localMaxEntries)
684  localMaxEntries = localMaxEntriesBlockRows;
685  }
686  return localMaxEntries;
687  }
688 
690 
693  bool isLocallyIndexed() const {
694  XPETRA_MONITOR("XpetraBlockedCrsMatrix::isLocallyIndexed");
695  for (size_t i = 0; i < blocks_.size(); ++i)
696  if (blocks_[i] != Teuchos::null && !blocks_[i]->isLocallyIndexed())
697  return false;
698  return true;
699  }
700 
702 
705  bool isGloballyIndexed() const {
706  XPETRA_MONITOR("XpetraBlockedCrsMatrix::isGloballyIndexed");
707  for (size_t i = 0; i < blocks_.size(); i++)
708  if (blocks_[i] != Teuchos::null && !blocks_[i]->isGloballyIndexed())
709  return false;
710  return true;
711  }
712 
714  bool isFillComplete() const {
715  XPETRA_MONITOR("XpetraBlockedCrsMatrix::isFillComplete");
716  for (size_t i = 0; i < blocks_.size(); i++)
717  if (blocks_[i] != Teuchos::null && !blocks_[i]->isFillComplete())
718  return false;
719  return true;
720  }
721 
723 
737  virtual void getLocalRowCopy(LocalOrdinal LocalRow,
738  const ArrayView<LocalOrdinal>& Indices,
739  const ArrayView<Scalar>& Values,
740  size_t& NumEntries) const {
741  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getLocalRowCopy");
742  if (Rows() == 1 && Cols() == 1) {
743  getMatrix(0, 0)->getLocalRowCopy(LocalRow, Indices, Values, NumEntries);
744  return;
745  }
746  throw Xpetra::Exceptions::RuntimeError("getLocalRowCopy not supported by BlockedCrsMatrix");
747  }
748 
750 
759  void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView<const GlobalOrdinal>& indices, ArrayView<const Scalar>& values) const {
760  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getGlobalRowView");
761  if (Rows() == 1 && Cols() == 1) {
762  getMatrix(0, 0)->getGlobalRowView(GlobalRow, indices, values);
763  return;
764  }
765  throw Xpetra::Exceptions::RuntimeError("getGlobalRowView not supported by BlockedCrsMatrix");
766  }
767 
769 
778  void getLocalRowView(LocalOrdinal LocalRow, ArrayView<const LocalOrdinal>& indices, ArrayView<const Scalar>& values) const {
779  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getLocalRowView");
780  if (Rows() == 1 && Cols() == 1) {
781  getMatrix(0, 0)->getLocalRowView(LocalRow, indices, values);
782  return;
783  } else if (is_diagonal_) {
784  GlobalOrdinal gid = this->getRowMap()->getGlobalElement(LocalRow);
785  size_t row = getBlockedRangeMap()->getMapIndexForGID(gid);
786  getMatrix(row, row)->getLocalRowView(getMatrix(row, row)->getRowMap()->getLocalElement(gid), indices, values);
787  return;
788  }
789  throw Xpetra::Exceptions::RuntimeError("getLocalRowView not supported by BlockedCrsMatrix");
790  }
791 
793 
796  void getLocalDiagCopy(Vector& diag) const {
797  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getLocalDiagCopy");
798 
799  // RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
800 
801  Teuchos::RCP<Vector> rcpdiag = Teuchos::rcpFromRef(diag);
802  Teuchos::RCP<BlockedVector> bdiag = Teuchos::rcp_dynamic_cast<BlockedVector>(rcpdiag);
803 
804  // special treatment for 1x1 block matrices
805  // ReorderedBlockedCrsMatrix object encapsulate single blocks in ReorderedBlocks
806  // BlockedVectors have Vector objects as Leaf objects.
807  if (Rows() == 1 && Cols() == 1 && bdiag.is_null() == true) {
808  Teuchos::RCP<const Matrix> rm = getMatrix(0, 0);
809  rm->getLocalDiagCopy(diag);
810  return;
811  }
812 
813  TEUCHOS_TEST_FOR_EXCEPTION(bdiag.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::getLocalDiagCopy: diag must be a Blocked(Multi)Vector.");
814  TEUCHOS_TEST_FOR_EXCEPTION(bdiag->getNumVectors() != 1, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::getLocalDiagCopy: diag must be a Blocked(Multi)Vector with exactly one vector. However, the number of stored vectors is " << bdiag->getNumVectors());
815  TEUCHOS_TEST_FOR_EXCEPTION(bdiag->getBlockedMap()->getNumMaps() != this->Rows(), Xpetra::Exceptions::RuntimeError,
816  "BlockedCrsMatrix::getLocalDiagCopy(): the number of blocks in diag differ from the number of blocks in this operator.");
817  // XPETRA_TEST_FOR_EXCEPTION(bdiag->getMap()->isSameAs(*(getMap())) == false, Xpetra::Exceptions::RuntimeError,
818  // "BlockedCrsMatrix::getLocalDiagCopy(): the map of the vector diag is not compatible with the map of the blocked operator." );
819 
820  for (size_t row = 0; row < Rows(); row++) {
821  Teuchos::RCP<const Matrix> rm = getMatrix(row, row);
822  if (!rm.is_null()) {
823  Teuchos::RCP<Vector> rv = VectorFactory::Build(bdiag->getBlockedMap()->getMap(row, bdiag->getBlockedMap()->getThyraMode()));
824  rm->getLocalDiagCopy(*rv);
825  bdiag->setMultiVector(row, rv, bdiag->getBlockedMap()->getThyraMode());
826  }
827  }
828  }
829 
831  void leftScale(const Vector& x) {
832  XPETRA_MONITOR("XpetraBlockedCrsMatrix::leftScale");
833 
834  Teuchos::RCP<const Vector> rcpx = Teuchos::rcpFromRef(x);
835  Teuchos::RCP<const BlockedVector> bx = Teuchos::rcp_dynamic_cast<const BlockedVector>(rcpx);
836 
837  // RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
838 
839  // special treatment for 1xn block matrices
840  // ReorderedBlockedCrsMatrix object encapsulate single blocks in ReorderedBlocks
841  // BlockedVectors have Vector objects as Leaf objects.
842  if (Rows() == 1 && bx.is_null() == true) {
843  for (size_t col = 0; col < Cols(); ++col) {
844  Teuchos::RCP<Matrix> rm = getMatrix(0, col);
845  rm->leftScale(x);
846  }
847  return;
848  }
849 
850  TEUCHOS_TEST_FOR_EXCEPTION(bx.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::leftScale: x must be a Blocked(Multi)Vector.");
851  TEUCHOS_TEST_FOR_EXCEPTION(bx->getNumVectors() != 1, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::leftScale: x must be a Blocked(Multi)Vector with exactly one vector. However, the number of stored vectors is " << bx->getNumVectors());
852  TEUCHOS_TEST_FOR_EXCEPTION(bx->getBlockedMap()->getNumMaps() != this->Rows(), Xpetra::Exceptions::RuntimeError,
853  "BlockedCrsMatrix::leftScale(): the number of blocks in diag differ from the number of blocks in this operator.");
854 
855  for (size_t row = 0; row < Rows(); row++) {
856  Teuchos::RCP<const MultiVector> rmv = bx->getMultiVector(row);
857  Teuchos::RCP<const Vector> rscale = rmv->getVector(0);
858  XPETRA_TEST_FOR_EXCEPTION(rscale.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::leftScale: x must be a Vector.");
859  for (size_t col = 0; col < Cols(); ++col) {
860  Teuchos::RCP<Matrix> rm = getMatrix(row, col);
861  if (!rm.is_null()) {
862  rm->leftScale(*rscale);
863  }
864  }
865  }
866  }
867 
869  void rightScale(const Vector& x) {
870  XPETRA_MONITOR("XpetraBlockedCrsMatrix::rightScale");
871 
872  Teuchos::RCP<const Vector> rcpx = Teuchos::rcpFromRef(x);
873  Teuchos::RCP<const BlockedVector> bx = Teuchos::rcp_dynamic_cast<const BlockedVector>(rcpx);
874 
875  // RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
876 
877  // special treatment for nx1 block matrices
878  // ReorderedBlockedCrsMatrix object encapsulate single blocks in ReorderedBlocks
879  // BlockedVectors have Vector objects as Leaf objects.
880  if (Cols() == 1 && bx.is_null() == true) {
881  for (size_t row = 0; row < Rows(); ++row) {
882  Teuchos::RCP<Matrix> rm = getMatrix(row, 0);
883  rm->rightScale(x);
884  }
885  return;
886  }
887 
888  TEUCHOS_TEST_FOR_EXCEPTION(bx.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::rightScale: x must be a Blocked(Multi)Vector.");
889  TEUCHOS_TEST_FOR_EXCEPTION(bx->getNumVectors() != 1, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::rightScale: x must be a Blocked(Multi)Vector with exactly one vector. However, the number of stored vectors is " << bx->getNumVectors());
890  TEUCHOS_TEST_FOR_EXCEPTION(bx->getBlockedMap()->getNumMaps() != this->Cols(), Xpetra::Exceptions::RuntimeError,
891  "BlockedCrsMatrix::rightScale(): the number of blocks in diag differ from the number of blocks in this operator.");
892 
893  for (size_t col = 0; col < Cols(); ++col) {
894  Teuchos::RCP<const MultiVector> rmv = bx->getMultiVector(col);
895  Teuchos::RCP<const Vector> rscale = rmv->getVector(0);
896  XPETRA_TEST_FOR_EXCEPTION(rscale.is_null() == true, Xpetra::Exceptions::RuntimeError, "BlockedCrsMatrix::leftScale: x must be a Vector.");
897  for (size_t row = 0; row < Rows(); row++) {
898  Teuchos::RCP<Matrix> rm = getMatrix(row, col);
899  if (!rm.is_null()) {
900  rm->rightScale(*rscale);
901  }
902  }
903  }
904  }
905 
907  virtual typename ScalarTraits<Scalar>::magnitudeType getFrobeniusNorm() const {
908  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getFrobeniusNorm");
909  typename ScalarTraits<Scalar>::magnitudeType ret = Teuchos::ScalarTraits<Scalar>::magnitude(Teuchos::ScalarTraits<Scalar>::zero());
910  for (size_t col = 0; col < Cols(); ++col) {
911  for (size_t row = 0; row < Rows(); ++row) {
912  if (getMatrix(row, col) != Teuchos::null) {
913  typename ScalarTraits<Scalar>::magnitudeType n = getMatrix(row, col)->getFrobeniusNorm();
914  ret += n * n;
915  }
916  }
917  }
918  return Teuchos::ScalarTraits<typename ScalarTraits<Scalar>::magnitudeType>::squareroot(ret);
919  }
920 
922  virtual bool haveGlobalConstants() const { return true; }
923 
925 
927 
928 
930 
950 
952 
953 
955  virtual void apply(const MultiVector& X, MultiVector& Y, Teuchos::ETransp mode, Scalar alpha, Scalar beta, bool sumInterfaceValues,
956  const RCP<Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node> >& regionInterfaceImporter,
957  const Teuchos::ArrayRCP<LocalOrdinal>& regionInterfaceLIDs) const {}
958 
960 
963  virtual void apply(const MultiVector& X, MultiVector& Y,
964  Teuchos::ETransp mode = Teuchos::NO_TRANS,
965  Scalar alpha = ScalarTraits<Scalar>::one(),
966  Scalar beta = ScalarTraits<Scalar>::zero()) const {
967  XPETRA_MONITOR("XpetraBlockedCrsMatrix::apply");
968  // using Teuchos::RCP;
969 
970  TEUCHOS_TEST_FOR_EXCEPTION(mode != Teuchos::NO_TRANS && mode != Teuchos::TRANS, Xpetra::Exceptions::RuntimeError,
971  "apply() only supports the following modes: NO_TRANS and TRANS.");
972 
973  // check whether input parameters are blocked or not
974  RCP<const MultiVector> refX = rcpFromRef(X);
975  RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(refX);
976  // RCP<MultiVector> tmpY = rcpFromRef(Y);
977  // RCP<BlockedMultiVector> tmpbY = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(tmpY);
978 
979  // TODO get rid of me: adapt MapExtractor
980  bool bBlockedX = (refbX != Teuchos::null) ? true : false;
981 
982  // create (temporary) vectors for output
983  // In the end we call Y.update(alpha, *tmpY, beta). Therefore we need a new vector storing the temporary results
984  RCP<MultiVector> tmpY = MultiVectorFactory::Build(Y.getMap(), Y.getNumVectors(), true);
985 
986  // RCP<Teuchos::FancyOStream> out = rcp(new Teuchos::FancyOStream(rcp(&std::cout,false)));
987 
988  SC one = ScalarTraits<SC>::one();
989 
990  if (mode == Teuchos::NO_TRANS) {
991  for (size_t row = 0; row < Rows(); row++) {
992  RCP<MultiVector> Yblock = rangemaps_->getVector(row, Y.getNumVectors(), bRangeThyraMode_, true);
993  for (size_t col = 0; col < Cols(); col++) {
994  // extract matrix block
995  RCP<Matrix> Ablock = getMatrix(row, col);
996 
997  if (Ablock.is_null())
998  continue;
999 
1000  // check whether Ablock is itself a blocked operator
1001  // If it is a blocked operator we have to provide Xpetra style GIDs, i.e. we have to transform GIDs
1002  bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false : true;
1003 
1004  // input/output vectors for local block operation
1005  RCP<const MultiVector> Xblock = Teuchos::null; // subpart of X vector to be applied to subblock of A
1006 
1007  // extract sub part of X using Xpetra or Thyra GIDs
1008  // if submatrix is again blocked, we extract it using Xpetra style gids. If it is a single
1009  // block matrix we use the Thyra or Xpetra style GIDs that are used to store the matrix
1010  if (bBlockedX)
1011  Xblock = domainmaps_->ExtractVector(refbX, col, bDomainThyraMode_);
1012  else
1013  Xblock = domainmaps_->ExtractVector(refX, col, bBlockedSubMatrix == true ? false : bDomainThyraMode_);
1014 
1015  RCP<MultiVector> tmpYblock = rangemaps_->getVector(row, Y.getNumVectors(), bRangeThyraMode_, false); // subpart of Y vector containing part of solution of Xblock applied to Ablock
1016  Ablock->apply(*Xblock, *tmpYblock);
1017 
1018  Yblock->update(one, *tmpYblock, one);
1019  }
1020  rangemaps_->InsertVector(Yblock, row, tmpY, bRangeThyraMode_);
1021  }
1022 
1023  } else if (mode == Teuchos::TRANS) {
1024  // TODO: test me!
1025  for (size_t col = 0; col < Cols(); col++) {
1026  RCP<MultiVector> Yblock = domainmaps_->getVector(col, Y.getNumVectors(), bDomainThyraMode_, true);
1027 
1028  for (size_t row = 0; row < Rows(); row++) {
1029  RCP<Matrix> Ablock = getMatrix(row, col);
1030 
1031  if (Ablock.is_null())
1032  continue;
1033 
1034  // check whether Ablock is itself a blocked operator
1035  // If it is a blocked operator we have to provide Xpetra style GIDs, i.e. we have to transform GIDs
1036  bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false : true;
1037 
1038  RCP<const MultiVector> Xblock = Teuchos::null;
1039 
1040  // extract sub part of X using Xpetra or Thyra GIDs
1041  if (bBlockedX)
1042  Xblock = rangemaps_->ExtractVector(refbX, row, bRangeThyraMode_);
1043  else
1044  Xblock = rangemaps_->ExtractVector(refX, row, bBlockedSubMatrix == true ? false : bRangeThyraMode_);
1045  RCP<MultiVector> tmpYblock = domainmaps_->getVector(col, Y.getNumVectors(), bDomainThyraMode_, false);
1046  Ablock->apply(*Xblock, *tmpYblock, Teuchos::TRANS);
1047 
1048  Yblock->update(one, *tmpYblock, one);
1049  }
1050  domainmaps_->InsertVector(Yblock, col, tmpY, bDomainThyraMode_);
1051  }
1052  }
1053  Y.update(alpha, *tmpY, beta);
1054  }
1055 
1057  RCP<const Map> getFullDomainMap() const {
1058  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getFullDomainMap()");
1059  return domainmaps_->getFullMap();
1060  }
1061 
1063  RCP<const BlockedMap> getBlockedDomainMap() const {
1064  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getBlockedDomainMap()");
1065  return domainmaps_->getBlockedMap();
1066  }
1067 
1069  const RCP<const Map> getDomainMap() const {
1070  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getDomainMap()");
1071  return domainmaps_->getMap(); /*domainmaps_->getFullMap();*/
1072  }
1073 
1075  RCP<const Map> getDomainMap(size_t i) const {
1076  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getDomainMap(size_t)");
1077  return domainmaps_->getMap(i, bDomainThyraMode_);
1078  }
1079 
1081  RCP<const Map> getDomainMap(size_t i, bool bThyraMode) const {
1082  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getDomainMap(size_t,bool)");
1083  return domainmaps_->getMap(i, bThyraMode);
1084  }
1085 
1087  RCP<const Map> getFullRangeMap() const {
1088  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getRangeMap()");
1089  return rangemaps_->getFullMap();
1090  }
1091 
1093  RCP<const BlockedMap> getBlockedRangeMap() const {
1094  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getBlockedRangeMap()");
1095  return rangemaps_->getBlockedMap();
1096  }
1097 
1099  const RCP<const Map> getRangeMap() const {
1100  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getRangeMap()");
1101  return rangemaps_->getMap(); /*rangemaps_->getFullMap();*/
1102  }
1103 
1105  RCP<const Map> getRangeMap(size_t i) const {
1106  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getRangeMap(size_t)");
1107  return rangemaps_->getMap(i, bRangeThyraMode_);
1108  }
1109 
1111  RCP<const Map> getRangeMap(size_t i, bool bThyraMode) const {
1112  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getRangeMap(size_t,bool)");
1113  return rangemaps_->getMap(i, bThyraMode);
1114  }
1115 
1117  RCP<const MapExtractor> getRangeMapExtractor() const {
1118  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getRangeMapExtractor()");
1119  return rangemaps_;
1120  }
1121 
1123  RCP<const MapExtractor> getDomainMapExtractor() const {
1124  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getDomainMapExtractor()");
1125  return domainmaps_;
1126  }
1127 
1129 
1131  //{@
1132 
1141  virtual void bgs_apply(
1142  const MultiVector& X,
1143  MultiVector& Y,
1144  size_t row,
1145  Teuchos::ETransp mode = Teuchos::NO_TRANS,
1146  Scalar alpha = ScalarTraits<Scalar>::one(),
1147  Scalar beta = ScalarTraits<Scalar>::zero()
1148  ) const {
1149  XPETRA_MONITOR("XpetraBlockedCrsMatrix::bgs_apply");
1150  // using Teuchos::RCP;
1151 
1152  TEUCHOS_TEST_FOR_EXCEPTION(mode != Teuchos::NO_TRANS && mode != Teuchos::TRANS, Xpetra::Exceptions::RuntimeError,
1153  "apply() only supports the following modes: NO_TRANS and TRANS.");
1154 
1155  // check whether input parameters are blocked or not
1156  RCP<const MultiVector> refX = rcpFromRef(X);
1157  RCP<const BlockedMultiVector> refbX = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(refX);
1158  // RCP<MultiVector> tmpY = rcpFromRef(Y);
1159  // RCP<BlockedMultiVector> tmpbY = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(tmpY);
1160 
1161  bool bBlockedX = (refbX != Teuchos::null) ? true : false;
1162 
1163  // create (temporary) vectors for output
1164  // In the end we call Y.update(alpha, *tmpY, beta). Therefore we need a new vector storing the temporary results
1165  RCP<MultiVector> tmpY = MultiVectorFactory::Build(Y.getMap(), Y.getNumVectors(), true);
1166 
1167  SC one = ScalarTraits<SC>::one();
1168 
1169  if (mode == Teuchos::NO_TRANS) {
1170  RCP<MultiVector> Yblock = rangemaps_->getVector(row, Y.getNumVectors(), bRangeThyraMode_, true);
1171  for (size_t col = 0; col < Cols(); col++) {
1172  // extract matrix block
1173  RCP<Matrix> Ablock = getMatrix(row, col);
1174 
1175  if (Ablock.is_null())
1176  continue;
1177 
1178  // check whether Ablock is itself a blocked operator
1179  // If it is a blocked operator we have to provide Xpetra style GIDs, i.e. we have to transform GIDs
1180  bool bBlockedSubMatrix = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Ablock) == Teuchos::null ? false : true;
1181 
1182  // input/output vectors for local block operation
1183  RCP<const MultiVector> Xblock = Teuchos::null; // subpart of X vector to be applied to subblock of A
1184 
1185  // extract sub part of X using Xpetra or Thyra GIDs
1186  // if submatrix is again blocked, we extract it using Xpetra style gids. If it is a single
1187  // block matrix we use the Thyra or Xpetra style GIDs that are used to store the matrix
1188  if (bBlockedX)
1189  Xblock = domainmaps_->ExtractVector(refbX, col, bDomainThyraMode_);
1190  else
1191  Xblock = domainmaps_->ExtractVector(refX, col, bBlockedSubMatrix == true ? false : bDomainThyraMode_);
1192 
1193  RCP<MultiVector> tmpYblock = rangemaps_->getVector(row, Y.getNumVectors(), bRangeThyraMode_, false); // subpart of Y vector containing part of solution of Xblock applied to Ablock
1194  Ablock->apply(*Xblock, *tmpYblock);
1195 
1196  Yblock->update(one, *tmpYblock, one);
1197  }
1198  rangemaps_->InsertVector(Yblock, row, tmpY, bRangeThyraMode_);
1199  } else {
1200  TEUCHOS_TEST_FOR_EXCEPTION(true, Xpetra::Exceptions::NotImplemented, "Xpetar::BlockedCrsMatrix::bgs_apply: not implemented for transpose case.");
1201  }
1202  Y.update(alpha, *tmpY, beta);
1203  }
1204 
1206 
1208  //{@
1209 
1211  const Teuchos::RCP<const Map> getMap() const {
1212  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getMap");
1213  if (Rows() == 1 && Cols() == 1) {
1214  return getMatrix(0, 0)->getMap();
1215  }
1216  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::getMap(): operation not supported.");
1217  }
1218 
1220  void doImport(const Matrix& source, const Import& importer, CombineMode CM) {
1221  XPETRA_MONITOR("XpetraBlockedCrsMatrix::doImport");
1222  if (Rows() == 1 && Cols() == 1) {
1223  getMatrix(0, 0)->doImport(source, importer, CM);
1224  return;
1225  }
1226  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doImport(): operation not supported.");
1227  }
1228 
1230  void doExport(const Matrix& dest, const Import& importer, CombineMode CM) {
1231  XPETRA_MONITOR("XpetraBlockedCrsMatrix::doExport");
1232  if (Rows() == 1 && Cols() == 1) {
1233  getMatrix(0, 0)->doExport(dest, importer, CM);
1234  return;
1235  }
1236  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doExport(): operation not supported.");
1237  }
1238 
1240  void doImport(const Matrix& source, const Export& exporter, CombineMode CM) {
1241  XPETRA_MONITOR("XpetraBlockedCrsMatrix::doImport");
1242  if (Rows() == 1 && Cols() == 1) {
1243  getMatrix(0, 0)->doImport(source, exporter, CM);
1244  return;
1245  }
1246  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doImport(): operation not supported.");
1247  }
1248 
1250  void doExport(const Matrix& dest, const Export& exporter, CombineMode CM) {
1251  XPETRA_MONITOR("XpetraBlockedCrsMatrix::doExport");
1252  if (Rows() == 1 && Cols() == 1) {
1253  getMatrix(0, 0)->doExport(dest, exporter, CM);
1254  return;
1255  }
1256  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doExport(): operation not supported.");
1257  }
1258 
1259  // @}
1260 
1262 
1263 
1265  std::string description() const { return "Xpetra_BlockedCrsMatrix.description()"; }
1266 
1268  void describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default) const {
1269  out << "Xpetra::BlockedCrsMatrix: " << Rows() << " x " << Cols() << std::endl;
1270 
1271  if (isFillComplete()) {
1272  out << "BlockMatrix is fillComplete" << std::endl;
1273 
1274  /*if(fullrowmap_ != Teuchos::null) {
1275  out << "fullRowMap" << std::endl;
1276  fullrowmap_->describe(out,verbLevel);
1277  } else {
1278  out << "fullRowMap not set. Check whether block matrix is properly fillCompleted!" << std::endl;
1279  }*/
1280 
1281  // out << "fullColMap" << std::endl;
1282  // fullcolmap_->describe(out,verbLevel);
1283 
1284  } else {
1285  out << "BlockMatrix is NOT fillComplete" << std::endl;
1286  }
1287 
1288  for (size_t r = 0; r < Rows(); ++r)
1289  for (size_t c = 0; c < Cols(); ++c) {
1290  if (getMatrix(r, c) != Teuchos::null) {
1291  out << "Block(" << r << "," << c << ")" << std::endl;
1292  getMatrix(r, c)->describe(out, verbLevel);
1293  } else
1294  out << "Block(" << r << "," << c << ") = null" << std::endl;
1295  }
1296  }
1297 
1299 
1300  void setObjectLabel(const std::string& objectLabel) {
1301  XPETRA_MONITOR("TpetraBlockedCrsMatrix::setObjectLabel");
1302  for (size_t r = 0; r < Rows(); ++r)
1303  for (size_t c = 0; c < Cols(); ++c) {
1304  if (getMatrix(r, c) != Teuchos::null) {
1305  std::ostringstream oss;
1306  oss << objectLabel << "(" << r << "," << c << ")";
1307  getMatrix(r, c)->setObjectLabel(oss.str());
1308  }
1309  }
1310  }
1312 
1314  bool hasCrsGraph() const {
1315  if (Rows() == 1 && Cols() == 1)
1316  return true;
1317  else
1318  return false;
1319  }
1320 
1322  RCP<const CrsGraph> getCrsGraph() const {
1323  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getCrsGraph");
1324  if (Rows() == 1 && Cols() == 1) {
1325  return getMatrix(0, 0)->getCrsGraph();
1326  }
1327  throw Xpetra::Exceptions::RuntimeError("getCrsGraph() not supported by BlockedCrsMatrix");
1328  }
1329 
1331 
1333 
1334 
1335  virtual bool isDiagonal() const { return is_diagonal_; }
1336 
1338  virtual size_t Rows() const {
1339  XPETRA_MONITOR("XpetraBlockedCrsMatrix::Rows");
1340  return rangemaps_->NumMaps();
1341  }
1342 
1344  virtual size_t Cols() const {
1345  XPETRA_MONITOR("XpetraBlockedCrsMatrix::Cols");
1346  return domainmaps_->NumMaps();
1347  }
1348 
1350  Teuchos::RCP<Matrix> getCrsMatrix() const {
1351  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getCrsMatrix");
1352  TEUCHOS_TEST_FOR_EXCEPTION(Rows() != 1, std::out_of_range, "Can only unwrap a 1x1 blocked matrix. The matrix has " << Rows() << " block rows, though.");
1353  TEUCHOS_TEST_FOR_EXCEPTION(Cols() != 1, std::out_of_range, "Can only unwrap a 1x1 blocked matrix. The matrix has " << Cols() << " block columns, though.");
1354 
1355  RCP<Matrix> mat = getMatrix(0, 0);
1356  RCP<BlockedCrsMatrix> bmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mat);
1357  if (bmat == Teuchos::null) return mat;
1358  return bmat->getCrsMatrix();
1359  }
1360 
1362  Teuchos::RCP<Matrix> getInnermostCrsMatrix() {
1363  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getInnermostCrsMatrix");
1364  size_t row = Rows() + 1, col = Cols() + 1;
1365  for (size_t r = 0; r < Rows(); ++r)
1366  for (size_t c = 0; c < Cols(); ++c)
1367  if (getMatrix(r, c) != Teuchos::null) {
1368  row = r;
1369  col = c;
1370  break;
1371  }
1372  TEUCHOS_TEST_FOR_EXCEPTION(row == Rows() + 1 || col == Cols() + 1, Xpetra::Exceptions::Incompatible, "Xpetra::BlockedCrsMatrix::getInnermostCrsMatrix: Could not find a non-zero sub-block in blocked operator.")
1373  RCP<Matrix> mm = getMatrix(row, col);
1374  RCP<BlockedCrsMatrix> bmat = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(mm);
1375  if (bmat == Teuchos::null) return mm;
1376  return bmat->getInnermostCrsMatrix();
1377  }
1378 
1380  Teuchos::RCP<Matrix> getMatrix(size_t r, size_t c) const {
1381  XPETRA_MONITOR("XpetraBlockedCrsMatrix::getMatrix");
1382  TEUCHOS_TEST_FOR_EXCEPTION(r > Rows(), std::out_of_range, "Error, r = " << Rows() << " is too big");
1383  TEUCHOS_TEST_FOR_EXCEPTION(c > Cols(), std::out_of_range, "Error, c = " << Cols() << " is too big");
1384 
1385  // transfer strided/blocked map information
1386  /* if (blocks_[r*Cols()+c] != Teuchos::null &&
1387  blocks_[r*Cols()+c]->IsView("stridedMaps") == false)
1388  blocks_[r*Cols()+c]->CreateView("stridedMaps", getRangeMap(r,bRangeThyraMode_), getDomainMap(c,bDomainThyraMode_));*/
1389  return blocks_[r * Cols() + c];
1390  }
1391 
1393  // void setMatrix(size_t r, size_t c, Teuchos::RCP<CrsMatrix> mat) {
1394  void setMatrix(size_t r, size_t c, Teuchos::RCP<Matrix> mat) {
1395  XPETRA_MONITOR("XpetraBlockedCrsMatrix::setMatrix");
1396  // TODO: if filled -> return error
1397 
1398  TEUCHOS_TEST_FOR_EXCEPTION(r > Rows(), std::out_of_range, "Error, r = " << Rows() << " is too big");
1399  TEUCHOS_TEST_FOR_EXCEPTION(c > Cols(), std::out_of_range, "Error, c = " << Cols() << " is too big");
1400  if (!mat.is_null() && r != c) is_diagonal_ = false;
1401  // set matrix
1402  blocks_[r * Cols() + c] = mat;
1403  }
1404 
1406  // NOTE: This is a rather expensive operation, since all blocks are copied
1407  // into a new big CrsMatrix
1408  Teuchos::RCP<Matrix> Merge() const {
1409  XPETRA_MONITOR("XpetraBlockedCrsMatrix::Merge");
1410  using Teuchos::RCP;
1411  using Teuchos::rcp_dynamic_cast;
1412  Scalar one = ScalarTraits<SC>::one();
1413 
1415  "BlockedCrsMatrix::Merge: only implemented for Xpetra-style or Thyra-style numbering. No mixup allowed!");
1416 
1417  TEUCHOS_TEST_FOR_EXCEPTION(isFillComplete() == false, Xpetra::Exceptions::RuntimeError,
1418  "BlockedCrsMatrix::Merge: BlockMatrix must be fill-completed.");
1419 
1420  LocalOrdinal lclNumRows = getFullRangeMap()->getLocalNumElements();
1421  Teuchos::ArrayRCP<size_t> numEntPerRow(lclNumRows);
1422  for (LocalOrdinal lclRow = 0; lclRow < lclNumRows; ++lclRow)
1423  numEntPerRow[lclRow] = getNumEntriesInLocalRow(lclRow);
1424 
1425  RCP<Matrix> sparse = MatrixFactory::Build(getFullRangeMap(), numEntPerRow);
1426 
1427  if (bRangeThyraMode_ == false) {
1428  // Xpetra mode
1429  for (size_t i = 0; i < Rows(); i++) {
1430  for (size_t j = 0; j < Cols(); j++) {
1431  if (getMatrix(i, j) != Teuchos::null) {
1432  RCP<const Matrix> mat = getMatrix(i, j);
1433 
1434  // recursively call Merge routine
1435  RCP<const BlockedCrsMatrix> bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1436  if (bMat != Teuchos::null) mat = bMat->Merge();
1437 
1438  bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1439  TEUCHOS_TEST_FOR_EXCEPTION(bMat != Teuchos::null, Xpetra::Exceptions::RuntimeError,
1440  "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!");
1441 
1442  // jump over empty blocks
1443  if (mat->getLocalNumEntries() == 0) continue;
1444 
1445  this->Add(*mat, one, *sparse, one);
1446  }
1447  }
1448  }
1449  } else {
1450  // Thyra mode
1451  for (size_t i = 0; i < Rows(); i++) {
1452  for (size_t j = 0; j < Cols(); j++) {
1453  if (getMatrix(i, j) != Teuchos::null) {
1454  RCP<const Matrix> mat = getMatrix(i, j);
1455  // recursively call Merge routine
1456  RCP<const BlockedCrsMatrix> bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1457  if (bMat != Teuchos::null) mat = bMat->Merge();
1458 
1459  bMat = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(mat);
1460  TEUCHOS_TEST_FOR_EXCEPTION(bMat != Teuchos::null, Xpetra::Exceptions::RuntimeError,
1461  "BlockedCrsMatrix::Merge: Merging of blocked sub-operators failed?!");
1462 
1463  // check whether we have a CrsMatrix block (no blocked operator)
1464  RCP<const CrsMatrixWrap> crsMat = Teuchos::rcp_dynamic_cast<const CrsMatrixWrap>(mat);
1465  TEUCHOS_ASSERT(crsMat != Teuchos::null);
1466 
1467  // these are the thyra style maps of the matrix
1468  RCP<const Map> trowMap = mat->getRowMap();
1469  RCP<const Map> tcolMap = mat->getColMap();
1470  RCP<const Map> tdomMap = mat->getDomainMap();
1471 
1472  // get Xpetra maps
1473  RCP<const Map> xrowMap = getRangeMapExtractor()->getMap(i, false);
1474  RCP<const Map> xdomMap = getDomainMapExtractor()->getMap(j, false);
1475 
1476  // generate column map with Xpetra GIDs
1477  // We have to do this separately for each block since the column
1478  // map of each block might be different in the same block column
1479  Teuchos::RCP<Map> xcolMap = MapUtils::transformThyra2XpetraGIDs(
1480  *tcolMap,
1481  *tdomMap,
1482  *xdomMap);
1483 
1484  // jump over empty blocks
1485  if (mat->getLocalNumEntries() == 0) continue;
1486 
1487  size_t maxNumEntries = mat->getLocalMaxNumRowEntries();
1488 
1489  size_t numEntries;
1490  Array<GO> inds(maxNumEntries);
1491  Array<GO> inds2(maxNumEntries);
1492  Array<SC> vals(maxNumEntries);
1493 
1494  // loop over all rows and add entries
1495  for (size_t k = 0; k < mat->getLocalNumRows(); k++) {
1496  GlobalOrdinal rowTGID = trowMap->getGlobalElement(k);
1497  crsMat->getCrsMatrix()->getGlobalRowCopy(rowTGID, inds(), vals(), numEntries);
1498 
1499  // create new indices array
1500  for (size_t l = 0; l < numEntries; ++l) {
1501  LocalOrdinal lid = tcolMap->getLocalElement(inds[l]);
1502  inds2[l] = xcolMap->getGlobalElement(lid);
1503  }
1504 
1505  GlobalOrdinal rowXGID = xrowMap->getGlobalElement(k);
1506  sparse->insertGlobalValues(
1507  rowXGID, inds2(0, numEntries),
1508  vals(0, numEntries));
1509  }
1510  }
1511  }
1512  }
1513  }
1514 
1515  sparse->fillComplete(getFullDomainMap(), getFullRangeMap());
1516 
1517  TEUCHOS_TEST_FOR_EXCEPTION(sparse->getLocalNumEntries() != getLocalNumEntries(), Xpetra::Exceptions::RuntimeError,
1518  "BlockedCrsMatrix::Merge: Local number of entries of merged matrix does not coincide with local number of entries of blocked operator.");
1519 
1520  TEUCHOS_TEST_FOR_EXCEPTION(sparse->getGlobalNumEntries() != getGlobalNumEntries(), Xpetra::Exceptions::RuntimeError,
1521  "BlockedCrsMatrix::Merge: Global number of entries of merged matrix does not coincide with global number of entries of blocked operator.");
1522 
1523  return sparse;
1524  }
1526 
1530  if (Rows() == 1 && Cols() == 1) {
1531  return getMatrix(0, 0)->getLocalMatrixDevice();
1532  }
1533  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::getLocalMatrix(): operation not supported.");
1534  }
1536  typename local_matrix_type::HostMirror getLocalMatrixHost() const {
1537  if (Rows() == 1 && Cols() == 1) {
1538  return getMatrix(0, 0)->getLocalMatrixHost();
1539  }
1540  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::getLocalMatrix(): operation not supported.");
1541  }
1542 
1543 #ifdef HAVE_XPETRA_THYRA
1544  Teuchos::RCP<Thyra::BlockedLinearOpBase<Scalar> > getThyraOperator() {
1545  Teuchos::RCP<Thyra::LinearOpBase<Scalar> > thOp =
1546  Xpetra::ThyraUtils<Scalar, LO, GO, Node>::toThyra(Teuchos::rcpFromRef(*this));
1547  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thOp));
1548 
1549  Teuchos::RCP<Thyra::BlockedLinearOpBase<Scalar> > thbOp =
1550  Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<Scalar> >(thOp);
1551  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thbOp));
1552  return thbOp;
1553  }
1554 #endif
1555  LocalOrdinal GetStorageBlockSize() const { return 1; }
1557 
1559  void residual(const MultiVector& X,
1560  const MultiVector& B,
1561  MultiVector& R) const {
1562  using STS = Teuchos::ScalarTraits<Scalar>;
1563  R.update(STS::one(), B, STS::zero());
1564  this->apply(X, R, Teuchos::NO_TRANS, -STS::one(), STS::one());
1565  }
1566 
1567  private:
1570 
1572 
1582  void Add(const Matrix& A, const Scalar scalarA, Matrix& B, const Scalar scalarB) const {
1583  XPETRA_MONITOR("XpetraBlockedCrsMatrix::Add");
1584  TEUCHOS_TEST_FOR_EXCEPTION(!A.isFillComplete(), Xpetra::Exceptions::RuntimeError,
1585  "Matrix A is not completed");
1586  using Teuchos::Array;
1587  using Teuchos::ArrayView;
1588 
1589  B.scale(scalarB);
1590 
1591  Scalar one = ScalarTraits<SC>::one();
1592  Scalar zero = ScalarTraits<SC>::zero();
1593 
1594  if (scalarA == zero)
1595  return;
1596 
1597  Teuchos::RCP<const Matrix> rcpA = Teuchos::rcpFromRef(A);
1598  Teuchos::RCP<const CrsMatrixWrap> rcpAwrap = Teuchos::rcp_dynamic_cast<const CrsMatrixWrap>(rcpA);
1599  TEUCHOS_TEST_FOR_EXCEPTION(rcpAwrap == Teuchos::null, Xpetra::Exceptions::BadCast,
1600  "BlockedCrsMatrix::Add: matrix A must be of type CrsMatrixWrap.");
1601  Teuchos::RCP<const CrsMatrix> crsA = rcpAwrap->getCrsMatrix();
1602 
1603  size_t maxNumEntries = crsA->getLocalMaxNumRowEntries();
1604 
1605  size_t numEntries;
1606  Array<GO> inds(maxNumEntries);
1607  Array<SC> vals(maxNumEntries);
1608 
1609  RCP<const Map> rowMap = crsA->getRowMap();
1610  RCP<const Map> colMap = crsA->getColMap();
1611 
1612  ArrayView<const GO> rowGIDs = crsA->getRowMap()->getLocalElementList();
1613  for (size_t i = 0; i < crsA->getLocalNumRows(); i++) {
1614  GO row = rowGIDs[i];
1615  crsA->getGlobalRowCopy(row, inds(), vals(), numEntries);
1616 
1617  if (scalarA != one)
1618  for (size_t j = 0; j < numEntries; ++j)
1619  vals[j] *= scalarA;
1620 
1621  B.insertGlobalValues(row, inds(0, numEntries), vals(0, numEntries)); // insert should be ok, since blocks in BlockedCrsOpeartor do not overlap!
1622  }
1623  }
1624 
1626 
1627  // Default view is created after fillComplete()
1628  // Because ColMap might not be available before fillComplete().
1630  XPETRA_MONITOR("XpetraBlockedCrsMatrix::CreateDefaultView");
1631 
1632  // Create default view
1633  this->defaultViewLabel_ = "point";
1635 
1636  // Set current view
1637  this->currentViewLabel_ = this->GetDefaultViewLabel();
1638  }
1639 
1640  private:
1642  Teuchos::RCP<const MapExtractor> domainmaps_;
1643  Teuchos::RCP<const MapExtractor> rangemaps_;
1644 
1645  std::vector<Teuchos::RCP<Matrix> > blocks_;
1646 #ifdef HAVE_XPETRA_THYRA
1647  Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > thyraOp_;
1648 #endif
1651 };
1652 
1653 } // namespace Xpetra
1654 
1655 #define XPETRA_BLOCKEDCRSMATRIX_SHORT
1656 #endif /* XPETRA_BLOCKEDCRSMATRIX_HPP */
virtual void getLocalRowCopy(LocalOrdinal LocalRow, const ArrayView< LocalOrdinal > &Indices, const ArrayView< Scalar > &Values, size_t &NumEntries) const
Extract a list of entries in a specified local row of the matrix. Put into storage allocated by calli...
size_t getLocalNumRows() const
Returns the number of matrix rows owned on the calling node.
CrsMatrix::local_matrix_type local_matrix_type
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...
RCP< const Map > getDomainMap(size_t i, bool bThyraMode) const
Returns the Map associated with the i&#39;th block domain of this operator.
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
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. ...
void replaceGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Replace matrix entries, using global IDs.
void fillComplete(const RCP< const Map > &domainMap, const RCP< const Map > &rangeMap, const RCP< ParameterList > &params=null)
Signal that data entry is complete.
virtual void setAllToScalar(const Scalar &alpha)
Set all matrix entries equal to scalar.
LocalOrdinal GetStorageBlockSize() const
Returns the block size of the storage mechanism.
static Teuchos::RCP< Xpetra::MapExtractor< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map > &fullmap, const std::vector< Teuchos::RCP< const Map >> &maps, bool bThyraMode=false)
Build MapExtrasctor from a given set of partial maps.
Teuchos::RCP< const MapExtractor > rangemaps_
full range map together with all partial domain maps
void doImport(const Matrix &source, const Import &importer, CombineMode CM)
Import.
void getLocalRowView(LocalOrdinal LocalRow, ArrayView< const LocalOrdinal > &indices, ArrayView< const Scalar > &values) const
Extract a const, non-persisting view of local indices in a specified row of the matrix.
static Teuchos::RCP< Xpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node >> &map, bool zeroOut=true)
Constructor specifying the number of non-zeros for all rows.
static RCP< Matrix > Build(const RCP< const Map > &rowMap)
virtual void bgs_apply(const MultiVector &X, MultiVector &Y, size_t row, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=ScalarTraits< Scalar >::one(), Scalar beta=ScalarTraits< Scalar >::zero()) const
Special multiplication routine (for BGS/Jacobi smoother)
Exception throws to report errors in the internal logical of the program.
RCP< const Map > getFullDomainMap() const
Returns the Map associated with the full domain of this operator.
virtual ~BlockedCrsMatrix()
Destructor.
Teuchos::RCP< Matrix > getCrsMatrix() const
return unwrap 1x1 blocked operators
void doExport(const Matrix &dest, const Import &importer, CombineMode CM)
Export.
RCP< const Map > getRangeMap(size_t i, bool bThyraMode) const
Returns the Map associated with the i&#39;th block range of this operator.
local_matrix_type::HostMirror getLocalMatrixHost() const
Access the underlying local Kokkos::CrsMatrix object.
size_t getGlobalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on all nodes.
void Add(const Matrix &A, const Scalar scalarA, Matrix &B, const Scalar scalarB) const
Add a Xpetra::CrsMatrix to another: B = B*scalarB + A*scalarA.
void resumeFill(const RCP< ParameterList > &params=null)
global_size_t getGlobalNumCols() const
Returns the number of global columns in the matrix.
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.
void rightScale(const Vector &x)
Right scale matrix using the given vector entries.
const Teuchos::RCP< const Map > getMap() const
Implements DistObject interface.
size_t getLocalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
global_size_t getGlobalNumEntries() const
Returns the global number of entries in this matrix.
size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const
Returns the current number of entries on this node in the specified local row.
RCP< const CrsGraph > getCrsGraph() const
Returns the CrsGraph associated with this matrix.
local_matrix_type getLocalMatrixDevice() const
Access the underlying local Kokkos::CrsMatrix object.
Exception indicating invalid cast attempted.
virtual bool haveGlobalConstants() const
Returns true if globalConstants have been computed; false otherwise.
void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Insert matrix entries, using global IDs.
void getLocalDiagCopy(Vector &diag) const
Get a copy of the diagonal entries owned by this node, with local row indices.
viewLabel_t defaultViewLabel_
virtual void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)=0
Insert matrix entries, using global IDs.
RCP< const Map > getRangeMap(size_t i) const
Returns the Map associated with the i&#39;th block range of this operator.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
bool is_diagonal_
If we&#39;re diagonal, a bunch of the extraction stuff should work.
void doExport(const Matrix &dest, const Export &exporter, CombineMode CM)
Export (using an Importer).
void leftScale(const Vector &x)
Left scale matrix using the given vector entries.
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
Map constructor with Xpetra-defined contiguous uniform distribution.
void setObjectLabel(const std::string &objectLabel)
Teuchos::RCP< Matrix > getInnermostCrsMatrix()
helper routine recursively returns the first inner-most non-null matrix block from a (nested) blocked...
void insertLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Insert matrix entries, using local IDs.
Teuchos::RCP< Matrix > getMatrix(size_t r, size_t c) const
return block (r,c)
virtual bool isFillComplete() const =0
Returns true if fillComplete() has been called and the matrix is in compute mode. ...
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< Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > transformThyra2XpetraGIDs(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &input, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlInput, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &nonOvlReferenceInput)
replace set of global ids by new global ids
void scale(const Scalar &alpha)
Scale the current values of a matrix, this = alpha*this.
void CreateView(viewLabel_t viewLabel, const RCP< const Map > &rowMap, const RCP< const Map > &colMap)
RCP< const Map > getFullRangeMap() const
Returns the Map associated with the full range of this operator.
void residual(const MultiVector &X, const MultiVector &B, MultiVector &R) const
Compute a residual R = B - (*this) * X.
viewLabel_t currentViewLabel_
RCP< const Map > getDomainMap(size_t i) const
Returns the Map associated with the i&#39;th block domain of this operator.
RCP< const BlockedMap > getBlockedRangeMap() const
Returns the BlockedMap associated with the range of this operator.
void doImport(const Matrix &source, const Export &exporter, CombineMode CM)
Import (using an Exporter).
void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView< const GlobalOrdinal > &indices, ArrayView< const Scalar > &values) const
Extract a const, non-persisting view of global indices in a specified row of the matrix.
Exception throws when you call an unimplemented method of Xpetra.
bool hasCrsGraph() const
Supports the getCrsGraph() call.
std::string viewLabel_t
size_t global_size_t
Global size_t object.
std::vector< Teuchos::RCP< Matrix > > blocks_
row major matrix block storage
Teuchos::RCP< Matrix > Merge() const
merge BlockedCrsMatrix blocks in a CrsMatrix
BlockedCrsMatrix(const Teuchos::RCP< const BlockedMap > &rangeMaps, const Teuchos::RCP< const BlockedMap > &domainMaps, size_t numEntriesPerRow)
Constructor.
RCP< const MapExtractor > getDomainMapExtractor() const
Returns map extractor for domain map.
global_size_t getGlobalNumRows() const
Returns the number of global rows.
const RCP< const Map > getDomainMap() const
Returns the Map associated with the domain of this operator.
#define XPETRA_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
size_t getNumEntriesInGlobalRow(GlobalOrdinal globalRow) const
Returns the current number of entries in the specified (locally owned) global row.
size_t getLocalNumEntries() const
Returns the local number of entries in this matrix.
void setMatrix(size_t r, size_t c, Teuchos::RCP< Matrix > mat)
set matrix block
std::string description() const
Return a simple one-line description of this object.
bool bDomainThyraMode_
boolean flag, which is true, if BlockedCrsMatrix has been created using Thyra-style numbering for sub...
bool isGloballyIndexed() const
If matrix indices are in the global range, this function returns true. Otherwise, this function retur...
Exception throws to report incompatible objects (like maps).
Concrete implementation of Xpetra::Matrix.
BlockedCrsMatrix(Teuchos::RCP< const MapExtractor > &rangeMapExtractor, Teuchos::RCP< const MapExtractor > &domainMapExtractor, size_t numEntriesPerRow)
Constructor.
virtual size_t Rows() const
number of row blocks
CombineMode
Xpetra::Combine Mode enumerable type.
#define XPETRA_MONITOR(funcName)
virtual const RCP< const Map > & getRowMap() const
Returns the Map that describes the row distribution in this matrix.
virtual void scale(const Scalar &alpha)=0
Scale the current values of a matrix, this = alpha*this.
void fillComplete(const RCP< ParameterList > &params=null)
Signal that data entry is complete.
const viewLabel_t & GetDefaultViewLabel() const
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
KokkosSparse::CrsMatrix< impl_scalar_type, LocalOrdinal, execution_space, void, typename local_graph_type::size_type > local_matrix_type
The specialization of Kokkos::CrsMatrix that represents the part of the sparse matrix on each MPI pro...
virtual ScalarTraits< Scalar >::magnitudeType getFrobeniusNorm() const
Get Frobenius norm of the matrix.
void removeEmptyProcessesInPlace(const Teuchos::RCP< const Map > &newMap)
bool isLocallyIndexed() const
If matrix indices of all matrix blocks are in the local range, this function returns true...
void replaceLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Replace matrix entries, using local IDs.
Xpetra-specific matrix class.
Teuchos::RCP< const MapExtractor > domainmaps_
full domain map together with all partial domain maps
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.
bool bRangeThyraMode_
boolean flag, which is true, if BlockedCrsMatrix has been created using Thyra-style numbering for sub...
RCP< const BlockedMap > getBlockedDomainMap() const
Returns the BlockedMap associated with the domain of this operator.
RCP< const MapExtractor > getRangeMapExtractor() const
Returns map extractor class for range map.
RCP< const CrsGraph< int, GlobalOrdinal, Node > > toXpetra(const Epetra_CrsGraph &g)