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 <Kokkos_DefaultNode.hpp>
50 
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"
60 #include "Xpetra_CrsGraph.hpp"
61 #include "Xpetra_CrsMatrix.hpp"
63 
64 #include "Xpetra_MapExtractor.hpp"
65 
66 #include "Xpetra_Matrix.hpp"
67 
68 #ifdef HAVE_XPETRA_THYRA
69 #include <Thyra_ProductVectorSpaceBase.hpp>
70 #include <Thyra_VectorSpaceBase.hpp>
71 #include <Thyra_LinearOpBase.hpp>
72 #include <Thyra_BlockedLinearOpBase.hpp>
73 #include <Thyra_PhysicallyBlockedLinearOpBase.hpp>
74 #include "Xpetra_ThyraUtils.hpp"
75 #endif
76 
77 
82 namespace Xpetra {
83 
84  typedef std::string viewLabel_t;
85 
86  template <class Scalar = Matrix<>::scalar_type,
87  class LocalOrdinal =
89  class GlobalOrdinal =
91  class Node =
93  class BlockedCrsMatrix :
94  public Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
95  public:
96  typedef Scalar scalar_type;
97  typedef LocalOrdinal local_ordinal_type;
98  typedef GlobalOrdinal global_ordinal_type;
99  typedef Node node_type;
100 
101  private:
102 #undef XPETRA_BLOCKEDCRSMATRIX_SHORT
103 #include "Xpetra_UseShortNames.hpp"
104 
105  public:
106 
108 
109 
111 
119  size_t npr, Xpetra::ProfileType pftype = Xpetra::DynamicProfile)
120  : domainmaps_(domainMaps), rangemaps_(rangeMaps)
121  {
122  blocks_.reserve(Rows()*Cols());
123 
124  // add CrsMatrix objects in row,column order
125  for (size_t r = 0; r < Rows(); ++r)
126  for (size_t c = 0; c < Cols(); ++c)
127  blocks_.push_back(CrsMatrixFactory::Build(getRangeMap(r), npr, pftype));
128 
129  // Default view
131  }
132 
133 #ifdef HAVE_XPETRA_THYRA
134 
142  BlockedCrsMatrix(const Teuchos::RCP<Thyra::BlockedLinearOpBase<Scalar> >& thyraOp, const Teuchos::RCP<const Teuchos::Comm<int> >& comm)
143  : thyraOp_(thyraOp)
144  {
145  // extract information from Thyra blocked operator and rebuilt information
146  const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productRangeSpace = thyraOp->productRange();
147  const Teuchos::RCP<const Thyra::ProductVectorSpaceBase<Scalar> > productDomainSpace = thyraOp->productDomain();
148 
149  int numRangeBlocks = productRangeSpace->numBlocks();
150  int numDomainBlocks = productDomainSpace->numBlocks();
151 
152  // build range map extractor from Thyra::BlockedLinearOpBase object
153  std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > > subRangeMaps(numRangeBlocks);
154  for (size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
155  for (size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
156  if (thyraOp->blockExists(r,c)) {
157  // we only need at least one block in each block row to extract the range map
158  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r,c); // nonConst access is not allowed.
161  subRangeMaps[r] = xop->getRangeMap();
162  break;
163  }
164  }
165  }
166  Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > fullRangeMap = mergeMaps(subRangeMaps);
168 
169  // build domain map extractor from Thyra::BlockedLinearOpBase object
170  std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > > subDomainMaps(numDomainBlocks);
171  for (size_t c=0; c<Teuchos::as<size_t>(numDomainBlocks); ++c) {
172  for (size_t r=0; r<Teuchos::as<size_t>(numRangeBlocks); ++r) {
173  if (thyraOp->blockExists(r,c)) {
174  // we only need at least one block in each block row to extract the range map
175  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r,c); // nonConst access is not allowed.
178  subDomainMaps[c] = xop->getDomainMap();
179  break;
180  }
181  }
182  }
183  Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > fullDomainMap = mergeMaps(subDomainMaps);
185 
186 
187  //std::cout << *(rangemaps_->getFullMap()) << std::endl;
188  //Teuchos::RCP<const Xpetra::EpetraMap> epmap2 = Teuchos::rcp_dynamic_cast<const Xpetra::EpetraMap>(rangemaps_->getFullMap());
189  //std::cout << epmap2->getEpetra_Map() << std::endl;
190 
191  //Teuchos::RCP<Thyra::LinearOpBase<Scalar> > fullOp = Teuchos::rcp_dynamic_cast<Thyra::LinearOpBase<Scalar> >(thyraOp);
192 
193  //Teuchos::RCP<const Xpetra::CrsMatrix<Scalar,LO,GO,Node> > xFullOp =
194  // Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toXpetra(fullOp);
195  //std::cout << *(xFullOp->getRangeMap()) << std::endl;
197 
198  blocks_.reserve(Rows()*Cols());
199  // add CrsMatrix objects in row,column order
200  for (size_t r = 0; r < Rows(); ++r) {
201  for (size_t c = 0; c < Cols(); ++c) {
202  if(thyraOp->blockExists(r,c)) {
203  Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > const_op = thyraOp->getBlock(r,c); // nonConst access is not allowed.
204  Teuchos::RCP<Thyra::LinearOpBase<Scalar> > op = Teuchos::rcp_const_cast<Thyra::LinearOpBase<Scalar> >(const_op); // cast away const
207  blocks_.push_back(xop);
208  } else {
209  // add empty block
211  }
212  }
213  }
214  // Default view
216  }
217 
218  private:
220 
226  Teuchos::RCP<const Map> mergeMaps(std::vector<Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > > & subMaps) {
227  // merge submaps to global map
228  std::vector<GlobalOrdinal> gids;
229  for(size_t tt = 0; tt<subMaps.size(); ++tt) {
231  for(LocalOrdinal l = 0; l < Teuchos::as<LocalOrdinal>(subMap->getNodeNumElements()); ++l) {
232  GlobalOrdinal gid = subMap->getGlobalElement(l);
233  gids.push_back(gid);
234  }
235  }
236 
238  std::sort(gids.begin(), gids.end());
239  gids.erase(std::unique(gids.begin(), gids.end()), gids.end());
240  Teuchos::ArrayView<GO> gidsView(&gids[0], gids.size());
241  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());
242  return fullMap;
243  }
244 
245  public:
246 #endif
247 
249  virtual ~BlockedCrsMatrix() {}
250 
252 
253 
255 
256 
258 
280  void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView<const GlobalOrdinal>& cols, const ArrayView<const Scalar>& vals) {
281  throw Xpetra::Exceptions::RuntimeError("insertGlobalValues not supported by BlockedCrsMatrix");
282  }
283 
285 
292  void insertLocalValues(LocalOrdinal localRow, const ArrayView<const LocalOrdinal>& cols, const ArrayView<const Scalar>& vals) {
293  throw Xpetra::Exceptions::RuntimeError("insertLocalValues not supported by BlockedCrsMatrix");
294  }
295 
297  throw Xpetra::Exceptions::RuntimeError("removeEmptyProcesses not supported by BlockedCrsMatrix");
298  }
299 
301 
309  void replaceGlobalValues(GlobalOrdinal globalRow,
310  const ArrayView<const GlobalOrdinal> &cols,
311  const ArrayView<const Scalar> &vals) {
312  throw Xpetra::Exceptions::RuntimeError("replaceGlobalValues not supported by BlockedCrsMatrix");
313  }
314 
316 
320  void replaceLocalValues(LocalOrdinal localRow,
321  const ArrayView<const LocalOrdinal> &cols,
322  const ArrayView<const Scalar> &vals) {
323  throw Xpetra::Exceptions::RuntimeError("replaceLocalValues not supported by BlockedCrsMatrix");
324  }
325 
327  virtual void setAllToScalar(const Scalar& alpha) {
328  throw Xpetra::Exceptions::RuntimeError("setAllToScalar not supported by BlockedCrsMatrix");
329  }
330 
332  void scale(const Scalar& alpha) {
333  throw Xpetra::Exceptions::RuntimeError("scale not supported by BlockedCrsMatrix");
334  }
335 
337 
339 
340 
349  void resumeFill(const RCP< ParameterList >& params = null) {
350  throw Xpetra::Exceptions::RuntimeError("resumeFill not supported for block matrices");
351  }
352 
366  void fillComplete(const RCP<const Map>& domainMap, const RCP<const Map>& rangeMap, const RCP<ParameterList>& params = null) {
367  throw Xpetra::Exceptions::RuntimeError("fillComplete with arguments not supported for block matrices");
368  }
369 
384  void fillComplete(const RCP<ParameterList>& params = null) {
385  for (size_t r = 0; r < Rows(); ++r)
386  for (size_t c = 0; c < Cols(); ++c) {
387  Teuchos::RCP<CrsMatrix> Ablock = getMatrix(r,c);
388 
389  if (Ablock != Teuchos::null && !Ablock->isFillComplete())
390  Ablock->fillComplete(getDomainMap(c), getRangeMap(r), params);
391  }
392 
393  // get full row map
394  RCP<const Map> rangeMap = rangemaps_->getFullMap();
395  fullrowmap_ = MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getNodeElementList(), rangeMap()->getIndexBase(), rangeMap()->getComm());
396 
397  // build full col map
398  fullcolmap_ = Teuchos::null; // delete old full column map
399 
400  std::vector<GO> colmapentries;
401  for (size_t c = 0; c < Cols(); ++c) {
402  // copy all local column lids of all block rows to colset
403  std::set<GO> colset;
404  for (size_t r = 0; r < Rows(); ++r) {
405  Teuchos::RCP<CrsMatrix> Ablock = getMatrix(r,c);
406 
407  if (Ablock != Teuchos::null) {
408  Teuchos::ArrayView<const GO> colElements = Ablock->getColMap()->getNodeElementList();
409  Teuchos::RCP<const Map> colmap = Ablock->getColMap();
410  copy(colElements.getRawPtr(), colElements.getRawPtr() + colElements.size(), inserter(colset, colset.begin()));
411  }
412  }
413 
414  // remove duplicates (entries which are in column maps of more than one block row)
415  colmapentries.reserve(colmapentries.size() + colset.size());
416  copy(colset.begin(), colset.end(), back_inserter(colmapentries));
417  sort(colmapentries.begin(), colmapentries.end());
418  typename std::vector<GO>::iterator gendLocation;
419  gendLocation = std::unique(colmapentries.begin(), colmapentries.end());
420  colmapentries.erase(gendLocation,colmapentries.end());
421  }
422 
423  // sum up number of local elements
424  size_t numGlobalElements = 0;
425  Teuchos::reduceAll(*(rangeMap->getComm()), Teuchos::REDUCE_SUM, colmapentries.size(), Teuchos::outArg(numGlobalElements));
426 
427  // store global full column map
428  const Teuchos::ArrayView<const GO> aView = Teuchos::ArrayView<const GO>(colmapentries);
429  fullcolmap_ = MapFactory::Build(rangeMap->lib(), numGlobalElements, aView, 0, rangeMap->getComm());
430 
431  }
432 
434 
436 
439  global_size_t globalNumRows = 0;
440 
441  for (size_t row = 0; row < Rows(); row++)
442  for (size_t col = 0; col < Cols(); col++)
443  if (!getMatrix(row,col).is_null()) {
444  globalNumRows += getMatrix(row,col)->getGlobalNumRows();
445  break; // we need only one non-null matrix in a row
446  }
447 
448  return globalNumRows;
449  }
450 
452 
455  global_size_t globalNumCols = 0;
456 
457  for (size_t col = 0; col < Cols(); col++)
458  for (size_t row = 0; row < Rows(); row++)
459  if (!getMatrix(row,col).is_null()) {
460  globalNumCols += getMatrix(row,col)->getGlobalNumCols();
461  break; // we need only one non-null matrix in a col
462  }
463 
464  return globalNumCols;
465  }
466 
468  size_t getNodeNumRows() const {
469  global_size_t nodeNumRows = 0;
470 
471  for (size_t row = 0; row < Rows(); ++row)
472  for (size_t col = 0; col < Cols(); col++)
473  if (!getMatrix(row,col).is_null()) {
474  nodeNumRows += getMatrix(row,col)->getNodeNumRows();
475  break; // we need only one non-null matrix in a row
476  }
477 
478  return nodeNumRows;
479  }
480 
483  global_size_t globalNumEntries = 0;
484 
485  for (size_t row = 0; row < Rows(); ++row)
486  for (size_t col = 0; col < Cols(); ++col)
487  if (!getMatrix(row,col).is_null())
488  globalNumEntries += getMatrix(row,col)->getGlobalNumEntries();
489 
490  return globalNumEntries;
491  }
492 
494  size_t getNodeNumEntries() const {
495  global_size_t nodeNumEntries = 0;
496 
497  for (size_t row = 0; row < Rows(); ++row)
498  for (size_t col = 0; col < Cols(); ++col)
499  if (!getMatrix(row,col).is_null())
500  nodeNumEntries += getMatrix(row,col)->getNodeNumEntries();
501 
502  return nodeNumEntries;
503  }
504 
506 
507  size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const {
508  throw Xpetra::Exceptions::RuntimeError("getNumEntriesInLocalRow not supported by BlockedCrsMatrix");
509  }
510 
512 
515  throw Xpetra::Exceptions::RuntimeError("getGlobalNumDiags() not supported by BlockedCrsMatrix");
516  }
517 
519 
521  size_t getNodeNumDiags() const {
522  throw Xpetra::Exceptions::RuntimeError("getNodeNumDiags() not supported by BlockedCrsMatrix");
523  }
524 
526 
528  size_t getGlobalMaxNumRowEntries() const {
529  throw Xpetra::Exceptions::RuntimeError("getGlobalMaxNumRowEntries() not supported by BlockedCrsMatrix");
530  }
531 
533 
535  size_t getNodeMaxNumRowEntries() const {
536  throw Xpetra::Exceptions::RuntimeError("getNodeMaxNumRowEntries() not supported by BlockedCrsMatrix");
537  }
538 
540 
543  bool isLocallyIndexed() const {
544  for (size_t i = 0; i < blocks_.size(); ++i)
545  if (blocks_[i] != Teuchos::null && !blocks_[i]->isLocallyIndexed())
546  return false;
547  return true;
548  }
549 
551 
554  bool isGloballyIndexed() const {
555  for (size_t i = 0; i < blocks_.size(); i++)
556  if (blocks_[i] != Teuchos::null && !blocks_[i]->isGloballyIndexed())
557  return false;
558  return true;
559  }
560 
562  bool isFillComplete() const {
563  for (size_t i = 0; i < blocks_.size(); i++)
564  if (blocks_[i] != Teuchos::null && !blocks_[i]->isFillComplete())
565  return false;
566  return true;
567  }
568 
570 
584  virtual void getLocalRowCopy(LocalOrdinal LocalRow,
585  const ArrayView<LocalOrdinal>& Indices,
586  const ArrayView<Scalar>& Values,
587  size_t &NumEntries) const {
588  throw Xpetra::Exceptions::RuntimeError("getLocalRowCopy not supported by BlockedCrsMatrix" );
589  }
590 
592 
601  void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView<const GlobalOrdinal>& indices, ArrayView<const Scalar>& values) const {
602  throw Xpetra::Exceptions::RuntimeError("getGlobalRowView not supported by BlockedCrsMatrix");
603  }
604 
606 
615  void getLocalRowView(LocalOrdinal LocalRow, ArrayView<const LocalOrdinal>& indices, ArrayView<const Scalar>& values) const {
616  throw Xpetra::Exceptions::RuntimeError("getLocalRowView not supported by BlockedCrsMatrix");
617  }
618 
620 
623  void getLocalDiagCopy(Vector& diag) const {
624  throw Xpetra::Exceptions::RuntimeError("getLocalDiagCopy not supported by BlockedCrsMatrix" );
625  }
626 
629  throw Xpetra::Exceptions::RuntimeError("getFrobeniusNorm() not supported by BlockedCrsMatrix, yet");
630  }
631 
633 
635 
636 
638 
658 
660 
661 
663 
666  virtual void apply(const MultiVector& X, MultiVector& Y,
668  Scalar alpha = ScalarTraits<Scalar>::one(),
669  Scalar beta = ScalarTraits<Scalar>::zero()) const
670  {
671  using Teuchos::RCP;
672 
674  "apply() only supports the following modes: NO_TRANS and TRANS." );
675 
676  RCP<const MultiVector> refX = rcpFromRef(X);
678 
679  SC one = ScalarTraits<SC>::one();
680 
681  if (mode == Teuchos::NO_TRANS) {
682  for (size_t row = 0; row < Rows(); row++) {
683  RCP<MultiVector> Yblock = rangemaps_->getVector(row, Y.getNumVectors());
684  RCP<MultiVector> tmpYblock = rangemaps_->getVector(row, Y.getNumVectors());
685 
686  for (size_t col = 0; col < Cols(); col++) {
687  RCP<const MultiVector> Xblock = domainmaps_->ExtractVector(refX, col);
688  RCP<CrsMatrix> Ablock = getMatrix(row, col);
689 
690  if (Ablock.is_null())
691  continue;
692 
693  Ablock->apply(*Xblock, *tmpYblock);
694 
695  Yblock->update(one, *tmpYblock, one);
696  }
697  rangemaps_->InsertVector(Yblock, row, tmpY);
698  }
699 
700  } else if (mode == Teuchos::TRANS) {
701  // TODO: test me!
702  for (size_t col = 0; col < Cols(); col++) {
703  RCP<MultiVector> Yblock = domainmaps_->getVector(col, Y.getNumVectors());
704  RCP<MultiVector> tmpYblock = domainmaps_->getVector(col, Y.getNumVectors());
705 
706  for (size_t row = 0; row<Rows(); row++) {
707  RCP<const MultiVector> Xblock = rangemaps_->ExtractVector(refX, row);
708  RCP<CrsMatrix> Ablock = getMatrix(row, col);
709 
710  if (Ablock.is_null())
711  continue;
712 
713  Ablock->apply(*Xblock, *tmpYblock, Teuchos::TRANS);
714 
715  Yblock->update(one, *tmpYblock, one);
716  }
717  domainmaps_->InsertVector(Yblock, col, tmpY);
718  }
719  }
720 
721  Y.update(alpha, *tmpY, beta);
722  }
723 
726  RCP<const Map > getDomainMap() const { return domainmaps_->getFullMap(); }
727 
730  RCP<const Map > getDomainMap(size_t i) const { return domainmaps_->getMap(i); }
731 
734  RCP<const Map > getRangeMap() const { return rangemaps_->getFullMap(); }
735 
738  RCP<const Map > getRangeMap(size_t i) const { return rangemaps_->getMap(i); }
739 
742 
745 
747 
749  //{@
750 
753  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::getMap(): operation not supported.");
754  }
755 
757  void doImport(const Matrix &source, const Import& importer, CombineMode CM) {
758  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doImport(): operation not supported.");
759  }
760 
762  void doExport(const Matrix& dest, const Import& importer, CombineMode CM) {
763  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doExport(): operation not supported.");
764  }
765 
767  void doImport(const Matrix& source, const Export& exporter, CombineMode CM) {
768  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doImport(): operation not supported.");
769  }
770 
772  void doExport(const Matrix& dest, const Export& exporter, CombineMode CM) {
773  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doExport(): operation not supported.");
774  }
775 
776  // @}
777 
779 
780 
782  std::string description() const { return "Xpetra_BlockedCrsMatrix.description()"; }
783 
786  out << "Xpetra::BlockedCrsMatrix: " << Rows() << " x " << Cols() << std::endl;
787 
788  if (isFillComplete()) {
789  out << "BlockMatrix is fillComplete" << std::endl;
790 
791  out << "fullRowMap" << std::endl;
792  fullrowmap_->describe(out,verbLevel);
793 
794  out << "fullColMap" << std::endl;
795  fullcolmap_->describe(out,verbLevel);
796 
797  } else {
798  out << "BlockMatrix is NOT fillComplete" << std::endl;
799  }
800 
801  for (size_t r = 0; r < Rows(); ++r)
802  for (size_t c = 0; c < Cols(); ++c) {
803  out << "Block(" << r << "," << c << ")" << std::endl;
804  getMatrix(r,c)->describe(out,verbLevel);
805  }
806  }
807 
810  throw Xpetra::Exceptions::RuntimeError("getCrsGraph() not supported by BlockedCrsMatrix");
811  }
812 
814 
816 
817 
819  virtual size_t Rows() const { return rangemaps_->NumMaps(); }
820 
822  virtual size_t Cols() const { return domainmaps_->NumMaps(); }
823 
825  Teuchos::RCP<CrsMatrix> getMatrix(size_t r, size_t c) const { return blocks_[r*Cols()+c]; }
826 
828  void setMatrix(size_t r, size_t c, Teuchos::RCP<CrsMatrix> mat) {
829  // TODO: if filled -> return error
830 
831  TEUCHOS_TEST_FOR_EXCEPTION(r > Rows(), std::out_of_range, "Error, r = " << Rows() << " is too big");
832  TEUCHOS_TEST_FOR_EXCEPTION(c > Cols(), std::out_of_range, "Error, c = " << Cols() << " is too big");
833 
834  // set matrix
835  blocks_[r*Cols() + c] = mat;
836  }
837 
839  // NOTE: This is a rather expensive operation, since all blocks are copied
840  // into a new big CrsMatrix
842  using Teuchos::RCP;
843  using Teuchos::rcp_dynamic_cast;
844  Scalar one = ScalarTraits<SC>::one();
845 
847 
848  for (size_t i = 0; i < blocks_.size(); i++)
849  if (blocks_[i] != Teuchos::null)
850  this->Add(*blocks_[i], one, *sparse, one);
851 
852  sparse->fillComplete(getDomainMap(), getRangeMap());
853 
854  return sparse;
855  }
857 
858 #ifdef HAVE_XPETRA_KOKKOS_REFACTOR
859  typedef typename CrsMatrix::local_matrix_type local_matrix_type;
860 
862  local_matrix_type getLocalMatrix () const {
863  throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::getLocalMatrix(): operation not supported.");
864  }
865 #endif
866 
867 #ifdef HAVE_XPETRA_THYRA
870  Xpetra::ThyraUtils<Scalar,LO,GO,Node>::toThyra(this);
872 
874  Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<Scalar> >(thOp);
876  return thbOp;
877  }
878 #endif
879 
880  private:
881 
884 
886 
896  void Add(const CrsMatrix& A, const Scalar scalarA, CrsMatrix& B, const Scalar scalarB) const {
898  "Matrix A is not completed");
899  using Teuchos::Array;
900  using Teuchos::ArrayView;
901 
902  B.scale(scalarB);
903 
904  Scalar one = ScalarTraits<SC>::one();
905  Scalar zero = ScalarTraits<SC>::zero();
906 
907  if (scalarA == zero)
908  return;
909 
910  size_t maxNumEntries = A.getNodeMaxNumRowEntries();
911 
912  size_t numEntries;
913  Array<GO> inds(maxNumEntries);
914  Array<SC> vals(maxNumEntries);
915 
916  RCP<const Map> rowMap = A.getRowMap();
917  RCP<const Map> colMap = A.getColMap();
918 
919  ArrayView<const GO> rowGIDs = A.getRowMap()->getNodeElementList();
920  for (size_t i = 0; i < A.getNodeNumRows(); i++) {
921  GO row = rowGIDs[i];
922  A.getGlobalRowCopy(row, inds(), vals(), numEntries);
923 
924  if (scalarA != one)
925  for (size_t j = 0; j < numEntries; ++j)
926  vals[j] *= scalarA;
927 
928  B.insertGlobalValues(row, inds(0, numEntries), vals(0, numEntries)); // insert should be ok, since blocks in BlockedCrsOpeartor do not overlap!
929  }
930  }
931 
933 
934  // Default view is created after fillComplete()
935  // Because ColMap might not be available before fillComplete().
937  // Create default view
938  this->defaultViewLabel_ = "point";
940 
941  // Set current view
942  this->currentViewLabel_ = this->GetDefaultViewLabel();
943  }
944 
945  private:
946  Teuchos::RCP<const MapExtractor> domainmaps_; // full domain map together with all partial domain maps
947  Teuchos::RCP<const MapExtractor> rangemaps_; // full range map together with all partial domain maps
948  Teuchos::RCP<Map> fullrowmap_; // full matrix row map
949  Teuchos::RCP<Map> fullcolmap_; // full matrix column map
950 
951  std::vector<Teuchos::RCP<CrsMatrix> > blocks_; // row major matrix block storage
952 #ifdef HAVE_XPETRA_THYRA
954 #endif
955 };
956 
957 } //namespace Xpetra
958 
959 #define XPETRA_BLOCKEDCRSMATRIX_SHORT
960 #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...
RCP< const MapExtractor > getRangeMapExtractor()
Returns map extractor class for range map.
virtual void apply(const MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=ScalarTraits< Scalar >::one(), Scalar beta=ScalarTraits< Scalar >::zero()) const =0
Computes the sparse matrix-multivector multiplication.
virtual size_t getNodeMaxNumRowEntries() const =0
Returns the maximum number of entries across all rows/columns on this node.
virtual Teuchos::RCP< const Teuchos::Comm< int > > getComm() const =0
Get this Map&#39;s Comm object.
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, const Teuchos::RCP< Node > &node=defaultArgNode())
Map constructor with Xpetra-defined contiguous uniform distribution.
std::vector< Teuchos::RCP< CrsMatrix > > blocks_
virtual const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getColMap() const =0
Returns the Map that describes the column distribution in this matrix.
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, specifying domain and range maps.
virtual void setAllToScalar(const Scalar &alpha)
Set all matrix entries equal to scalar.
virtual void scale(const Scalar &alpha)=0
Scale the current values of a matrix, this = alpha*this.
virtual void fillComplete(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rangeMap, const RCP< ParameterList > &params=null)=0
Signal that data entry is complete, specifying domain and range maps.
GlobalOrdinal GO
virtual void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView< const GlobalOrdinal > &cols, const ArrayView< const Scalar > &vals)=0
Insert matrix entries, using global IDs.
bool is_null(const std::shared_ptr< T > &p)
RCP< const Map > getRangeMap() const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static RCP< CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rowMap, size_t maxNumEntriesPerRow, Xpetra::ProfileType pftype=Xpetra::DynamicProfile, const Teuchos::RCP< Teuchos::ParameterList > &plist=Teuchos::null)
Constructor specifying fixed number of entries for each row.
Teuchos::RCP< const MapExtractor > rangemaps_
virtual const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
Returns the Map that describes the row distribution in this matrix.
Xpetra namespace
void doImport(const Matrix &source, const Import &importer, CombineMode CM)
Import.
Teuchos::RCP< CrsMatrix > getMatrix(size_t r, size_t c) const
return block (r,c)
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.
size_type size() const
LocalOrdinal local_ordinal_type
Exception throws to report errors in the internal logical of the program.
size_t getNodeNumEntries() const
Returns the local number of entries in this matrix.
virtual ~BlockedCrsMatrix()
Destructor.
RCP< const CrsGraph< int, GlobalOrdinal > > toXpetra(const Epetra_CrsGraph &g)
RCP< const Map > getRangeMap(size_t i) const
size_t getNodeNumDiags() const
Returns the number of local diagonal entries, based on global row/column index comparisons.
void doExport(const Matrix &dest, const Import &importer, CombineMode CM)
Export.
void Add(const CrsMatrix &A, const Scalar scalarA, CrsMatrix &B, const Scalar scalarB) const
Add a Xpetra::CrsMatrix to another: B = B*scalarB + A*scalarA.
void setMatrix(size_t r, size_t c, Teuchos::RCP< CrsMatrix > mat)
set matrix block
size_t getGlobalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on all nodes.
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.
virtual void getGlobalRowCopy(GlobalOrdinal GlobalRow, const ArrayView< GlobalOrdinal > &indices, const ArrayView< Scalar > &values, size_t &numEntries) const =0
Extract a list of entries in a specified global row of this matrix. Put into pre-allocated storage...
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.
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 idices.
viewLabel_t defaultViewLabel_
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void doExport(const Matrix &dest, const Export &exporter, CombineMode CM)
Export (using an Importer).
void insertLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)
Insert matrix entries, using local IDs.
RCP< const MapExtractor > getDomainMapExtractor()
Returns map extractor for domain map.
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
const Teuchos::RCP< const Map > getMap() const
Implements DistObject interface.
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)
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
The Map describing the parallel distribution of this object.
viewLabel_t currentViewLabel_
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
Teuchos::RCP< CrsMatrix > Merge() const
merge BlockedCrsMatrix blocks in a CrsMatrix
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.
T * getRawPtr() const
std::string viewLabel_t
size_t global_size_t
Global size_t object.
size_t getNodeMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
static const EVerbosityLevel verbLevel_default
global_size_t getGlobalNumDiags() const
Returns the number of global diagonal entries, based on global row/column index comparisons.
global_size_t getGlobalNumRows() const
Returns the number of global rows.
virtual bool isFillComplete() const =0
Returns true if the matrix is in compute mode, i.e. if fillComplete() has been called.
std::string description() const
Return a simple one-line description of this object.
BlockedCrsMatrix(Teuchos::RCP< const MapExtractor > &rangeMaps, Teuchos::RCP< const MapExtractor > &domainMaps, size_t npr, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
Constructor.
bool isGloballyIndexed() const
If matrix indices are in the global range, this function returns true. Otherwise, this function retur...
RCP< const Map > getDomainMap() const
Returns the Map associated with the full domain of this operator. This will be null until fillComplet...
virtual size_t Rows() const
number of row blocks
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.
CombineMode
Xpetra::Combine Mode enumerable type.
void fillComplete(const RCP< ParameterList > &params=null)
Signal that data entry is complete.
const viewLabel_t & GetDefaultViewLabel() const
RCP< const Map > getDomainMap(size_t i) const
Returns the Map associated with the i&#39;th block domain of this operator. This will be null until fillC...
virtual size_t getNumVectors() const =0
Number of columns in the multivector.
virtual size_t getNodeNumRows() const =0
Returns the number of matrix rows owned on the calling node.
size_t getNodeNumRows() const
Returns the number of matrix rows owned on the calling node.
virtual UnderlyingLib lib() const =0
Get the library used by this object (Tpetra or Epetra?)
virtual ScalarTraits< Scalar >::magnitudeType getFrobeniusNorm() const
Get Frobenius norm of the matrix.
void removeEmptyProcessesInPlace(const Teuchos::RCP< const Map > &newMap)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
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_
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.
GlobalOrdinal global_ordinal_type
bool is_null() const