00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef XPETRA_BLOCKEDCRSMATRIX_HPP
00047 #define XPETRA_BLOCKEDCRSMATRIX_HPP
00048
00049 #include <Kokkos_DefaultNode.hpp>
00050
00051 #include <Teuchos_SerialDenseMatrix.hpp>
00052 #include <Teuchos_Hashtable.hpp>
00053
00054 #include "Xpetra_ConfigDefs.hpp"
00055 #include "Xpetra_Exceptions.hpp"
00056
00057 #include "Xpetra_MapFactory.hpp"
00058 #include "Xpetra_MultiVector.hpp"
00059 #include "Xpetra_MultiVectorFactory.hpp"
00060 #include "Xpetra_CrsGraph.hpp"
00061 #include "Xpetra_CrsMatrix.hpp"
00062 #include "Xpetra_CrsMatrixFactory.hpp"
00063
00064 #include "Xpetra_MapExtractor.hpp"
00065
00066 #include "Xpetra_Matrix.hpp"
00067
00072 namespace Xpetra {
00073
00074 typedef std::string viewLabel_t;
00075
00076 template <class Scalar = Matrix<>::scalar_type,
00077 class LocalOrdinal =
00078 typename Matrix<Scalar>::local_ordinal_type,
00079 class GlobalOrdinal =
00080 typename Matrix<Scalar, LocalOrdinal>::global_ordinal_type,
00081 class Node =
00082 typename Matrix<Scalar, LocalOrdinal, GlobalOrdinal>::node_type>
00083 class BlockedCrsMatrix :
00084 public Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> {
00085 public:
00086 typedef Scalar scalar_type;
00087 typedef LocalOrdinal local_ordinal_type;
00088 typedef GlobalOrdinal global_ordinal_type;
00089 typedef Node node_type;
00090
00091 private:
00092 #undef XPETRA_BLOCKEDCRSMATRIX_SHORT
00093 #include "Xpetra_UseShortNames.hpp"
00094
00095 public:
00096
00098
00099
00101
00107 BlockedCrsMatrix(Teuchos::RCP<const MapExtractor>& rangeMaps,
00108 Teuchos::RCP<const MapExtractor>& domainMaps,
00109 size_t npr, Xpetra::ProfileType pftype = Xpetra::DynamicProfile)
00110 : domainmaps_(domainMaps), rangemaps_(rangeMaps)
00111 {
00112 blocks_.reserve(Rows()*Cols());
00113
00114
00115 for (size_t r = 0; r < Rows(); ++r)
00116 for (size_t c = 0; c < Cols(); ++c)
00117 blocks_.push_back(CrsMatrixFactory::Build(getRangeMap(r), npr, pftype));
00118
00119
00120 CreateDefaultView();
00121 }
00122
00124 virtual ~BlockedCrsMatrix() {}
00125
00127
00128
00130
00131
00133
00155 void insertGlobalValues(GlobalOrdinal globalRow, const ArrayView<const GlobalOrdinal>& cols, const ArrayView<const Scalar>& vals) {
00156 throw Xpetra::Exceptions::RuntimeError("insertGlobalValues not supported by BlockedCrsMatrix");
00157 }
00158
00160
00167 void insertLocalValues(LocalOrdinal localRow, const ArrayView<const LocalOrdinal>& cols, const ArrayView<const Scalar>& vals) {
00168 throw Xpetra::Exceptions::RuntimeError("insertLocalValues not supported by BlockedCrsMatrix");
00169 }
00170
00171 void removeEmptyProcessesInPlace(const Teuchos::RCP<const Map>& newMap) {
00172 throw Xpetra::Exceptions::RuntimeError("removeEmptyProcesses not supported by BlockedCrsMatrix");
00173 }
00174
00176
00184 void replaceGlobalValues(GlobalOrdinal globalRow,
00185 const ArrayView<const GlobalOrdinal> &cols,
00186 const ArrayView<const Scalar> &vals) {
00187 throw Xpetra::Exceptions::RuntimeError("replaceGlobalValues not supported by BlockedCrsMatrix");
00188 }
00189
00191
00195 void replaceLocalValues(LocalOrdinal localRow,
00196 const ArrayView<const LocalOrdinal> &cols,
00197 const ArrayView<const Scalar> &vals) {
00198 throw Xpetra::Exceptions::RuntimeError("replaceLocalValues not supported by BlockedCrsMatrix");
00199 }
00200
00202 virtual void setAllToScalar(const Scalar& alpha) {
00203 throw Xpetra::Exceptions::RuntimeError("setAllToScalar not supported by BlockedCrsMatrix");
00204 }
00205
00207 void scale(const Scalar& alpha) {
00208 throw Xpetra::Exceptions::RuntimeError("scale not supported by BlockedCrsMatrix");
00209 }
00210
00212
00214
00215
00224 void resumeFill(const RCP< ParameterList >& params = null) {
00225 throw Xpetra::Exceptions::RuntimeError("resumeFill not supported for block matrices");
00226 }
00227
00241 void fillComplete(const RCP<const Map>& domainMap, const RCP<const Map>& rangeMap, const RCP<ParameterList>& params = null) {
00242 throw Xpetra::Exceptions::RuntimeError("fillComplete with arguments not supported for block matrices");
00243 }
00244
00259 void fillComplete(const RCP<ParameterList>& params = null) {
00260 for (size_t r = 0; r < Rows(); ++r)
00261 for (size_t c = 0; c < Cols(); ++c) {
00262 Teuchos::RCP<CrsMatrix> Ablock = getMatrix(r,c);
00263
00264 if (Ablock != Teuchos::null && !Ablock->isFillComplete())
00265 Ablock->fillComplete(getDomainMap(c), getRangeMap(r), params);
00266 }
00267
00268
00269 RCP<const Map> rangeMap = rangemaps_->getFullMap();
00270 fullrowmap_ = MapFactory::Build(rangeMap()->lib(), rangeMap()->getGlobalNumElements(), rangeMap()->getNodeElementList(), rangeMap()->getIndexBase(), rangeMap()->getComm());
00271
00272
00273 fullcolmap_ = Teuchos::null;
00274
00275 std::vector<GO> colmapentries;
00276 for (size_t c = 0; c < Cols(); ++c) {
00277
00278 std::set<GO> colset;
00279 for (size_t r = 0; r < Rows(); ++r) {
00280 Teuchos::RCP<CrsMatrix> Ablock = getMatrix(r,c);
00281
00282 if (Ablock != Teuchos::null) {
00283 Teuchos::ArrayView<const GO> colElements = Ablock->getColMap()->getNodeElementList();
00284 Teuchos::RCP<const Map> colmap = Ablock->getColMap();
00285 copy(colElements.getRawPtr(), colElements.getRawPtr() + colElements.size(), inserter(colset, colset.begin()));
00286 }
00287 }
00288
00289
00290 colmapentries.reserve(colmapentries.size() + colset.size());
00291 copy(colset.begin(), colset.end(), back_inserter(colmapentries));
00292 sort(colmapentries.begin(), colmapentries.end());
00293 typename std::vector<GO>::iterator gendLocation;
00294 gendLocation = std::unique(colmapentries.begin(), colmapentries.end());
00295 colmapentries.erase(gendLocation,colmapentries.end());
00296 }
00297
00298
00299 size_t numGlobalElements = 0;
00300 Teuchos::reduceAll(*(rangeMap->getComm()), Teuchos::REDUCE_SUM, colmapentries.size(), Teuchos::outArg(numGlobalElements));
00301
00302
00303 const Teuchos::ArrayView<const GO> aView = Teuchos::ArrayView<const GO>(colmapentries);
00304 fullcolmap_ = MapFactory::Build(rangeMap->lib(), numGlobalElements, aView, 0, rangeMap->getComm());
00305
00306 }
00307
00309
00311
00313 global_size_t getGlobalNumRows() const {
00314 global_size_t globalNumRows = 0;
00315
00316 for (size_t row = 0; row < Rows(); row++)
00317 for (size_t col = 0; col < Cols(); col++)
00318 if (!getMatrix(row,col).is_null()) {
00319 globalNumRows += getMatrix(row,col)->getGlobalNumRows();
00320 break;
00321 }
00322
00323 return globalNumRows;
00324 }
00325
00327
00329 global_size_t getGlobalNumCols() const {
00330 global_size_t globalNumCols = 0;
00331
00332 for (size_t col = 0; col < Cols(); col++)
00333 for (size_t row = 0; row < Rows(); row++)
00334 if (!getMatrix(row,col).is_null()) {
00335 globalNumCols += getMatrix(row,col)->getGlobalNumCols();
00336 break;
00337 }
00338
00339 return globalNumCols;
00340 }
00341
00343 size_t getNodeNumRows() const {
00344 global_size_t nodeNumRows = 0;
00345
00346 for (size_t row = 0; row < Rows(); ++row)
00347 for (size_t col = 0; col < Cols(); col++)
00348 if (!getMatrix(row,col).is_null()) {
00349 nodeNumRows += getMatrix(row,col)->getNodeNumRows();
00350 break;
00351 }
00352
00353 return nodeNumRows;
00354 }
00355
00357 global_size_t getGlobalNumEntries() const {
00358 global_size_t globalNumEntries = 0;
00359
00360 for (size_t row = 0; row < Rows(); ++row)
00361 for (size_t col = 0; col < Cols(); ++col)
00362 if (!getMatrix(row,col).is_null())
00363 globalNumEntries += getMatrix(row,col)->getGlobalNumEntries();
00364
00365 return globalNumEntries;
00366 }
00367
00369 size_t getNodeNumEntries() const {
00370 global_size_t nodeNumEntries = 0;
00371
00372 for (size_t row = 0; row < Rows(); ++row)
00373 for (size_t col = 0; col < Cols(); ++col)
00374 if (!getMatrix(row,col).is_null())
00375 nodeNumEntries += getMatrix(row,col)->getNodeNumEntries();
00376
00377 return nodeNumEntries;
00378 }
00379
00381
00382 size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const {
00383 throw Xpetra::Exceptions::RuntimeError("getNumEntriesInLocalRow not supported by BlockedCrsMatrix");
00384 }
00385
00387
00389 global_size_t getGlobalNumDiags() const {
00390 throw Xpetra::Exceptions::RuntimeError("getGlobalNumDiags() not supported by BlockedCrsMatrix");
00391 }
00392
00394
00396 size_t getNodeNumDiags() const {
00397 throw Xpetra::Exceptions::RuntimeError("getNodeNumDiags() not supported by BlockedCrsMatrix");
00398 }
00399
00401
00403 size_t getGlobalMaxNumRowEntries() const {
00404 throw Xpetra::Exceptions::RuntimeError("getGlobalMaxNumRowEntries() not supported by BlockedCrsMatrix");
00405 }
00406
00408
00410 size_t getNodeMaxNumRowEntries() const {
00411 throw Xpetra::Exceptions::RuntimeError("getNodeMaxNumRowEntries() not supported by BlockedCrsMatrix");
00412 }
00413
00415
00418 bool isLocallyIndexed() const {
00419 for (size_t i = 0; i < blocks_.size(); ++i)
00420 if (blocks_[i] != Teuchos::null && !blocks_[i]->isLocallyIndexed())
00421 return false;
00422 return true;
00423 }
00424
00426
00429 bool isGloballyIndexed() const {
00430 for (size_t i = 0; i < blocks_.size(); i++)
00431 if (blocks_[i] != Teuchos::null && !blocks_[i]->isGloballyIndexed())
00432 return false;
00433 return true;
00434 }
00435
00437 bool isFillComplete() const {
00438 for (size_t i = 0; i < blocks_.size(); i++)
00439 if (blocks_[i] != Teuchos::null && !blocks_[i]->isFillComplete())
00440 return false;
00441 return true;
00442 }
00443
00445
00459 virtual void getLocalRowCopy(LocalOrdinal LocalRow,
00460 const ArrayView<LocalOrdinal>& Indices,
00461 const ArrayView<Scalar>& Values,
00462 size_t &NumEntries) const {
00463 throw Xpetra::Exceptions::RuntimeError("getLocalRowCopy not supported by BlockedCrsMatrix" );
00464 }
00465
00467
00476 void getGlobalRowView(GlobalOrdinal GlobalRow, ArrayView<const GlobalOrdinal>& indices, ArrayView<const Scalar>& values) const {
00477 throw Xpetra::Exceptions::RuntimeError("getGlobalRowView not supported by BlockedCrsMatrix");
00478 }
00479
00481
00490 void getLocalRowView(LocalOrdinal LocalRow, ArrayView<const LocalOrdinal>& indices, ArrayView<const Scalar>& values) const {
00491 throw Xpetra::Exceptions::RuntimeError("getLocalRowView not supported by BlockedCrsMatrix");
00492 }
00493
00495
00498 void getLocalDiagCopy(Vector& diag) const {
00499 throw Xpetra::Exceptions::RuntimeError("getLocalDiagCopy not supported by BlockedCrsMatrix" );
00500 }
00501
00503 virtual typename ScalarTraits<Scalar>::magnitudeType getFrobeniusNorm() const {
00504 throw Xpetra::Exceptions::RuntimeError("getFrobeniusNorm() not supported by BlockedCrsMatrix, yet");
00505 }
00506
00508
00510
00511
00513
00533
00535
00536
00538
00541 virtual void apply(const MultiVector& X, MultiVector& Y,
00542 Teuchos::ETransp mode = Teuchos::NO_TRANS,
00543 Scalar alpha = ScalarTraits<Scalar>::one(),
00544 Scalar beta = ScalarTraits<Scalar>::zero()) const
00545 {
00546 using Teuchos::RCP;
00547
00548 TEUCHOS_TEST_FOR_EXCEPTION(mode != Teuchos::NO_TRANS && mode != Teuchos::TRANS, Xpetra::Exceptions::RuntimeError,
00549 "apply() only supports the following modes: NO_TRANS and TRANS." );
00550
00551 RCP<const MultiVector> refX = rcpFromRef(X);
00552 RCP<MultiVector> tmpY = MultiVectorFactory::Build(Y.getMap(), Y.getNumVectors());
00553
00554 SC one = ScalarTraits<SC>::one();
00555
00556 if (mode == Teuchos::NO_TRANS) {
00557 for (size_t row = 0; row < Rows(); row++) {
00558 RCP<MultiVector> Yblock = rangemaps_->getVector(row, Y.getNumVectors());
00559 RCP<MultiVector> tmpYblock = rangemaps_->getVector(row, Y.getNumVectors());
00560
00561 for (size_t col = 0; col < Cols(); col++) {
00562 RCP<const MultiVector> Xblock = domainmaps_->ExtractVector(refX, col);
00563 RCP<CrsMatrix> Ablock = getMatrix(row, col);
00564
00565 if (Ablock.is_null())
00566 continue;
00567
00568 Ablock->apply(*Xblock, *tmpYblock);
00569
00570 Yblock->update(one, *tmpYblock, one);
00571 }
00572 rangemaps_->InsertVector(Yblock, row, tmpY);
00573 }
00574
00575 } else if (mode == Teuchos::TRANS) {
00576
00577 for (size_t col = 0; col < Cols(); col++) {
00578 RCP<MultiVector> Yblock = domainmaps_->getVector(col, Y.getNumVectors());
00579 RCP<MultiVector> tmpYblock = domainmaps_->getVector(col, Y.getNumVectors());
00580
00581 for (size_t row = 0; row<Rows(); row++) {
00582 RCP<const MultiVector> Xblock = rangemaps_->ExtractVector(refX, row);
00583 RCP<CrsMatrix> Ablock = getMatrix(row, col);
00584
00585 if (Ablock.is_null())
00586 continue;
00587
00588 Ablock->apply(*Xblock, *tmpYblock, Teuchos::TRANS);
00589
00590 Yblock->update(one, *tmpYblock, one);
00591 }
00592 domainmaps_->InsertVector(Yblock, col, tmpY);
00593 }
00594 }
00595
00596 Y.update(alpha, *tmpY, beta);
00597 }
00598
00601 const RCP<const Map > getDomainMap() const { return domainmaps_->getFullMap(); }
00602
00605 const RCP<const Map > getDomainMap(size_t i) const { return domainmaps_->getMap(i); }
00606
00609 const RCP<const Map > getRangeMap() const { return rangemaps_->getFullMap(); }
00610
00613 const RCP<const Map > getRangeMap(size_t i) const { return rangemaps_->getMap(i); }
00614
00616 const RCP<const MapExtractor> getRangeMapExtractor() { return rangemaps_; }
00617
00619 const RCP<const MapExtractor> getDomainMapExtractor() { return domainmaps_; }
00620
00622
00624
00625
00627 const Teuchos::RCP< const Map > getMap() const {
00628 throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::getMap(): operation not supported.");
00629 }
00630
00632 void doImport(const Matrix &source, const Import& importer, CombineMode CM) {
00633 throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doImport(): operation not supported.");
00634 }
00635
00637 void doExport(const Matrix& dest, const Import& importer, CombineMode CM) {
00638 throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doExport(): operation not supported.");
00639 }
00640
00642 void doImport(const Matrix& source, const Export& exporter, CombineMode CM) {
00643 throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doImport(): operation not supported.");
00644 }
00645
00647 void doExport(const Matrix& dest, const Export& exporter, CombineMode CM) {
00648 throw Xpetra::Exceptions::RuntimeError("BlockedCrsMatrix::doExport(): operation not supported.");
00649 }
00650
00651
00652
00654
00655
00657 std::string description() const { return "Xpetra_BlockedCrsMatrix.description()"; }
00658
00660 void describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default) const {
00661 out << "Xpetra::BlockedCrsMatrix: " << Rows() << " x " << Cols() << std::endl;
00662
00663 if (isFillComplete()) {
00664 out << "BlockMatrix is fillComplete" << std::endl;
00665
00666 out << "fullRowMap" << std::endl;
00667 fullrowmap_->describe(out,verbLevel);
00668
00669 out << "fullColMap" << std::endl;
00670 fullcolmap_->describe(out,verbLevel);
00671
00672 } else {
00673 out << "BlockMatrix is NOT fillComplete" << std::endl;
00674 }
00675
00676 for (size_t r = 0; r < Rows(); ++r)
00677 for (size_t c = 0; c < Cols(); ++c) {
00678 out << "Block(" << r << "," << c << ")" << std::endl;
00679 getMatrix(r,c)->describe(out,verbLevel);
00680 }
00681 }
00682
00684 RCP<const CrsGraph> getCrsGraph() const {
00685 throw Xpetra::Exceptions::RuntimeError("getCrsGraph() not supported by BlockedCrsMatrix");
00686 }
00687
00689
00691
00692
00694 virtual size_t Rows() const { return rangemaps_->NumMaps(); }
00695
00697 virtual size_t Cols() const { return domainmaps_->NumMaps(); }
00698
00700 Teuchos::RCP<CrsMatrix> getMatrix(size_t r, size_t c) const { return blocks_[r*Cols()+c]; }
00701
00703 void setMatrix(size_t r, size_t c, Teuchos::RCP<CrsMatrix> mat) {
00704
00705
00706 TEUCHOS_TEST_FOR_EXCEPTION(r > Rows(), std::out_of_range, "Error, r = " << Rows() << " is too big");
00707 TEUCHOS_TEST_FOR_EXCEPTION(c > Cols(), std::out_of_range, "Error, c = " << Cols() << " is too big");
00708
00709
00710 blocks_[r*Cols() + c] = mat;
00711 }
00712
00714
00715
00716 Teuchos::RCP<CrsMatrix> Merge() const {
00717 using Teuchos::RCP;
00718 using Teuchos::rcp_dynamic_cast;
00719 Scalar one = ScalarTraits<SC>::one();
00720
00721 RCP<CrsMatrix> sparse = CrsMatrixFactory::Build(fullrowmap_, 33);
00722
00723 for (size_t i = 0; i < blocks_.size(); i++)
00724 if (blocks_[i] != Teuchos::null)
00725 this->Add(*blocks_[i], one, *sparse, one);
00726
00727 sparse->fillComplete(getDomainMap(), getRangeMap());
00728
00729 return sparse;
00730 }
00732
00733
00734 private:
00735
00738
00740
00750 void Add(const CrsMatrix& A, const Scalar scalarA, CrsMatrix& B, const Scalar scalarB) const {
00751 TEUCHOS_TEST_FOR_EXCEPTION(!A.isFillComplete(), Xpetra::Exceptions::RuntimeError,
00752 "Matrix A is not completed");
00753 using Teuchos::Array;
00754 using Teuchos::ArrayView;
00755
00756 B.scale(scalarB);
00757
00758 Scalar one = ScalarTraits<SC>::one();
00759 Scalar zero = ScalarTraits<SC>::zero();
00760
00761 if (scalarA == zero)
00762 return;
00763
00764 size_t maxNumEntries = A.getNodeMaxNumRowEntries();
00765
00766 size_t numEntries;
00767 Array<GO> inds(maxNumEntries);
00768 Array<SC> vals(maxNumEntries);
00769
00770 RCP<const Map> rowMap = A.getRowMap();
00771 RCP<const Map> colMap = A.getColMap();
00772
00773 ArrayView<const GO> rowGIDs = A.getRowMap()->getNodeElementList();
00774 for (size_t i = 0; i < A.getNodeNumRows(); i++) {
00775 GO row = rowGIDs[i];
00776 A.getGlobalRowCopy(row, inds(), vals(), numEntries);
00777
00778 if (scalarA != one)
00779 for (size_t j = 0; j < numEntries; ++j)
00780 vals[j] *= scalarA;
00781
00782 B.insertGlobalValues(row, inds(0, numEntries), vals(0, numEntries));
00783 }
00784 }
00785
00787
00788
00789
00790 void CreateDefaultView() {
00791
00792 this->defaultViewLabel_ = "point";
00793 this->CreateView(this->GetDefaultViewLabel(), getRangeMap(), getDomainMap());
00794
00795
00796 this->currentViewLabel_ = this->GetDefaultViewLabel();
00797 }
00798
00799 private:
00800 Teuchos::RCP<const MapExtractor> domainmaps_;
00801 Teuchos::RCP<const MapExtractor> rangemaps_;
00802 Teuchos::RCP<Map> fullrowmap_;
00803 Teuchos::RCP<Map> fullcolmap_;
00804
00805 std::vector<Teuchos::RCP<CrsMatrix> > blocks_;
00806 };
00807
00808 }
00809
00810 #define XPETRA_BLOCKEDCRSMATRIX_SHORT
00811 #endif