43 #ifndef IFPACK2_DENSECONTAINER_DEF_HPP
44 #define IFPACK2_DENSECONTAINER_DEF_HPP
46 #include "Tpetra_CrsMatrix.hpp"
48 #include "Tpetra_Experimental_BlockMultiVector.hpp"
54 # include "Teuchos_DefaultSerialComm.hpp"
59 template<
class MatrixType,
class LocalScalarType>
60 DenseContainer<MatrixType, LocalScalarType, true>::
65 scalar_type DampingFactor) :
66 Container<MatrixType> (matrix, partitions, importer, OverlapLevel,
69 scalarOffsets_ (this->numBlocks_)
77 typedef typename ArrayView<const local_ordinal_type>::size_type size_type;
79 !matrix->hasColMap(), std::invalid_argument,
"Ifpack2::DenseContainer: "
80 "The constructor's input matrix must have a column Map.");
83 global_ordinal_type totalScalars = 0;
84 for(local_ordinal_type i = 0; i < this->numBlocks_; i++)
86 scalarOffsets_[i] = totalScalars;
87 totalScalars += this->blockRows_[i] * this->blockRows_[i]
88 * this->bcrsBlockSize_ * this->bcrsBlockSize_;
90 scalars_ =
new local_scalar_type[totalScalars];
91 for(
int i = 0; i < this->numBlocks_; i++)
93 int nnodes = this->blockRows_[i];
94 int denseRows = nnodes * this->bcrsBlockSize_;
96 diagBlocks_.emplace_back(
Teuchos::View, scalars_ + scalarOffsets_[i], denseRows, denseRows, denseRows);
97 diagBlocks_[i].putScalar(0);
100 ipiv_.resize(this->partitions_.size() * this->bcrsBlockSize_);
102 for(
int i = 0; i < this->numBlocks_; i++)
106 const map_type& rowMap = * (matrix->getRowMap ());
107 const size_type numRows = localRows.
size ();
108 bool rowIndicesValid =
true;
109 Array<local_ordinal_type> invalidLocalRowIndices;
110 for(size_type j = 0; j < numRows; j++) {
111 if(!rowMap.isNodeLocalElement(localRows[j])) {
112 rowIndicesValid =
false;
113 invalidLocalRowIndices.push_back(localRows[j]);
118 !rowIndicesValid, std::invalid_argument,
"Ifpack2::DenseContainer: "
119 "On process " << rowMap.getComm()->getRank() <<
" of "
120 << rowMap.getComm()->getSize() <<
", in the given set of local row "
121 "indices localRows = " <<
toString(localRows) <<
", the following "
122 "entries are not valid local row indices on the calling process: "
123 <<
toString(invalidLocalRowIndices) <<
".");
125 IsInitialized_ =
false;
129 template<
class MatrixType,
class LocalScalarType>
130 DenseContainer<MatrixType, LocalScalarType, true>::
133 Container<MatrixType>(matrix, localRows),
141 typedef typename ArrayView<const local_ordinal_type>::size_type size_type;
143 !matrix->hasColMap(), std::invalid_argument,
"Ifpack2::DenseContainer: "
144 "The constructor's input matrix must have a column Map.");
145 diagBlocks_.emplace_back(this->blockRows_[0] * this->bcrsBlockSize_,
146 this->blockRows_[0] * this->bcrsBlockSize_);
147 diagBlocks_[0].putScalar(0);
149 ipiv_.resize(this->partitions_.size() * this->bcrsBlockSize_);
151 for(
int i = 0; i < this->numBlocks_; i++)
154 const map_type& rowMap = *(matrix->getRowMap());
155 const size_type numRows = localRows.
size ();
156 bool rowIndicesValid =
true;
157 Array<local_ordinal_type> invalidLocalRowIndices;
158 for(size_type j = 0; j < numRows; j++)
160 if(!rowMap.isNodeLocalElement(localRows[j]))
162 rowIndicesValid =
false;
163 invalidLocalRowIndices.push_back(localRows[j]);
168 !rowIndicesValid, std::invalid_argument,
"Ifpack2::DenseContainer: "
169 "On process " << rowMap.getComm()->getRank() <<
" of "
170 << rowMap.getComm()->getSize() <<
", in the given set of local row "
171 "indices localRows = " <<
toString (localRows) <<
", the following "
172 "entries are not valid local row indices on the calling process: "
173 <<
toString(invalidLocalRowIndices) <<
".");
177 IsInitialized_ =
false;
181 template<
class MatrixType,
class LocalScalarType>
182 DenseContainer<MatrixType, LocalScalarType, true>::~DenseContainer()
188 template<
class MatrixType,
class LocalScalarType>
189 void DenseContainer<MatrixType, LocalScalarType, true>::
195 template<
class MatrixType,
class LocalScalarType>
197 DenseContainer<MatrixType, LocalScalarType, true>::
205 IsInitialized_ =
false;
209 for(
int i = 0; i < this->numBlocks_; i++)
211 std::fill (ipiv_.begin (), ipiv_.end (), 0);
212 IsInitialized_ =
true;
215 template<
class MatrixType,
class LocalScalarType>
217 DenseContainer<MatrixType, LocalScalarType, true>::
227 if (! this->isInitialized ()) {
238 template<
class MatrixType,
class LocalScalarType>
240 DenseContainer<MatrixType, LocalScalarType, true>::
244 for(
int i = 0; i < this->numBlocks_; i++)
247 int* blockIpiv = ipiv_.getRawPtr() + this->partitionIndices_[i] * this->bcrsBlockSize_;
248 lapack.
GETRF(diagBlocks_[i].numRows(),
249 diagBlocks_[i].numCols(),
250 diagBlocks_[i].values(),
251 diagBlocks_[i].stride(),
255 INFO < 0, std::logic_error,
"Ifpack2::DenseContainer::factor: "
256 "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
257 "incorrectly. INFO = " << INFO <<
" < 0. "
258 "Please report this bug to the Ifpack2 developers.");
263 INFO > 0, std::runtime_error,
"Ifpack2::DenseContainer::factor: "
264 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
265 "computed U factor is exactly singular. U(" << INFO <<
"," << INFO <<
") "
266 "(one-based index i) is exactly zero. This probably means that the input "
267 "matrix has a singular diagonal block.");
271 template<
class MatrixType,
class LocalScalarType>
273 DenseContainer<MatrixType, LocalScalarType, true>::
274 applyImplBlockCrs (HostViewLocal& X,
279 local_scalar_type alpha,
280 local_scalar_type beta)
const
287 using Teuchos::rcpFromRef;
290 const size_t numRows = X.extent(0);
291 const size_t numVecs = X.extent(1);
294 static_cast<size_t> (X.extent (0)) != static_cast<size_t> (diagBlocks_[blockIndex].numRows ()),
295 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: X and Y have "
296 "different number of rows than block matrix (" << X.extent(0) <<
" resp. "
297 << diagBlocks_[blockIndex].numRows() <<
"). Please report this bug to "
298 "the Ifpack2 developers.");
300 if (alpha == STS::zero ()) {
301 if (beta == STS::zero ()) {
305 for(
size_t i = 0; i < numRows; i++)
306 for(
size_t j = 0; j < numVecs; j++)
307 Y(i, j) = STS::zero();
310 for(
size_t i = 0; i < numRows; i++)
311 for(
size_t j = 0; j < numVecs; j++)
312 Y(i, j) = beta * (local_impl_scalar_type) Y(i, j);
320 Ptr<HostViewLocal> Y_tmp;
321 bool deleteYT =
false;
322 if (beta == STS::zero () ){
323 Kokkos::deep_copy(Y, X);
327 Y_tmp = ptr (
new HostViewLocal (
"", X.extent(0), X.extent(1)));
328 Kokkos::deep_copy(*Y_tmp, X);
331 local_scalar_type*
const Y_ptr = (local_scalar_type*) Y_tmp->data();
335 int* blockIpiv = (
int*) ipiv_.getRawPtr()
336 + this->partitionIndices_[blockIndex] * this->bcrsBlockSize_;
338 diagBlocks_[blockIndex].numRows (),
340 diagBlocks_[blockIndex].values (),
341 diagBlocks_[blockIndex].stride (),
346 INFO != 0, std::runtime_error,
"Ifpack2::DenseContainer::applyImpl: "
347 "LAPACK's _GETRS (solve using LU factorization with partial pivoting) "
348 "failed with INFO = " << INFO <<
" != 0.");
350 if (beta != STS::zero ()) {
351 for(
size_t i = 0; i < Y.extent(0); i++)
353 for(
size_t j = 0; j < Y.extent(1); j++)
355 Y(i, j) = beta * (local_impl_scalar_type) Y(i, j);
356 Y(i, j) += alpha * (*Y_tmp)(i, j);
365 template<
class MatrixType,
class LocalScalarType>
367 DenseContainer<MatrixType, LocalScalarType, true>::
368 applyImpl (HostViewLocal& X,
373 local_scalar_type alpha,
374 local_scalar_type beta)
const
381 using Teuchos::rcpFromRef;
384 X.extent (0) != Y.extent (0),
385 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: X and Y have "
386 "incompatible dimensions (" << X.extent (0) <<
" resp. "
387 << Y.extent (0) <<
"). Please report this bug to "
388 "the Ifpack2 developers.");
391 X.extent (1) != Y.extent(1),
392 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: X and Y have "
393 "incompatible numbers of vectors (" << X.extent (1) <<
" resp. "
394 << Y.extent (1) <<
"). Please report this bug to "
395 "the Ifpack2 developers.");
397 if(this->hasBlockCrs_) {
398 applyImplBlockCrs(X,Y,blockIndex,stride,mode,alpha,beta);
403 size_t numVecs = X.extent(1);
404 if(alpha == STS::zero()) {
405 if(beta == STS::zero()) {
409 for(
size_t i = 0; i < Y.extent(0); i++)
411 for(
size_t j = 0; j < Y.extent(1); j++)
412 Y(i, j) = STS::zero();
416 for(
size_t i = 0; i < Y.extent(0); i++)
418 for(
size_t j = 0; j < Y.extent(1); j++)
419 Y(i, j) = beta * (local_impl_scalar_type) Y(i, j);
427 Ptr<HostViewLocal> Y_tmp;
428 bool deleteYT =
false;
429 if (beta == STS::zero () ){
430 Kokkos::deep_copy (Y, X);
434 Y_tmp = ptr (
new HostViewLocal (
"", Y.extent(0), Y.extent(1)));
435 Kokkos::deep_copy(*Y_tmp, X);
438 local_scalar_type* Y_ptr = (local_scalar_type*) Y_tmp->data();
440 int* blockIpiv = (
int*) ipiv_.getRawPtr() + this->partitionIndices_[blockIndex] * this->bcrsBlockSize_;
444 diagBlocks_[blockIndex].numRows (),
446 diagBlocks_[blockIndex].values (),
447 diagBlocks_[blockIndex].stride (),
452 INFO != 0, std::runtime_error,
"Ifpack2::DenseContainer::applyImpl: "
453 "LAPACK's _GETRS (solve using LU factorization with partial pivoting) "
454 "failed with INFO = " << INFO <<
" != 0.");
456 if (beta != STS::zero ()) {
457 for(
size_t i = 0; i < Y.extent(0); i++)
459 for(
size_t j = 0; j < Y.extent(1); j++)
460 Y(i, j) = Y(i, j) * (local_impl_scalar_type) beta + (local_impl_scalar_type) alpha * (*Y_tmp)(i, j);
468 template<
class MatrixType,
class LocalScalarType>
470 DenseContainer<MatrixType, LocalScalarType, true>::
471 applyBlockCrs (HostView& XIn,
477 scalar_type beta)
const
485 const size_t numRows = this->blockRows_[blockIndex];
493 const char prefix[] =
"Ifpack2::DenseContainer::weightedApply: ";
495 ! IsComputed_, std::runtime_error, prefix <<
"You must have called the "
496 "compute() method before you may call this method. You may call "
497 "apply() as many times as you want after calling compute() once, "
498 "but you must have called compute() at least once first.");
499 const size_t numVecs = XIn.extent (1);
501 numVecs != YIn.extent (1), std::runtime_error,
502 prefix <<
"X and Y have different numbers of vectors (columns). X has "
503 << XIn.extent (1) <<
", but Y has " << YIn.extent (1) <<
".");
534 if(X_local.size() == 0)
538 for(
int i = 0; i < this->numBlocks_; i++)
540 X_local.emplace_back(
"", this->blockRows_[i] * this->bcrsBlockSize_, numVecs);
542 for(
int i = 0; i < this->numBlocks_; i++)
544 Y_local.emplace_back(
"", this->blockRows_[i] * this->bcrsBlockSize_, numVecs);
547 HostViewLocal& XOut = X_local[blockIndex];
548 HostViewLocal& YOut = Y_local[blockIndex];
550 ArrayView<const local_ordinal_type> localRows = this->getLocalRows(blockIndex);
552 for (
size_t j = 0; j < numVecs; ++j) {
553 for (
size_t i = 0; i < numRows; ++i) {
554 const size_t i_perm = localRows[i];
555 for (
int k = 0; k < this->bcrsBlockSize_; ++k)
556 XOut(i*this->bcrsBlockSize_+k, j) = XIn(i_perm*this->bcrsBlockSize_+k, j);
566 for (
size_t j = 0; j < numVecs; ++j) {
567 for (
size_t i = 0; i < numRows; ++i) {
568 const size_t i_perm = localRows[i];
569 for (
int k = 0; k < this->bcrsBlockSize_; ++k)
570 YOut(i*this->bcrsBlockSize_+k, j) = YIn(i_perm*this->bcrsBlockSize_+k, j);
576 this->applyImpl (XOut, YOut, blockIndex, stride, mode, as<local_scalar_type>(alpha),
577 as<local_scalar_type>(beta));
581 for(
size_t j = 0; j < numVecs; ++j) {
582 for(
size_t i = 0; i < numRows; ++i) {
583 const size_t i_perm = localRows[i];
584 for(
int k = 0; k < this->bcrsBlockSize_; ++k)
585 YIn(i_perm*this->bcrsBlockSize_+k, j) = YOut(i*this->bcrsBlockSize_+k, j);
590 template<
class MatrixType,
class LocalScalarType>
592 DenseContainer<MatrixType, LocalScalarType, true>::
599 scalar_type beta)
const
607 if(this->hasBlockCrs_) {
608 applyBlockCrs(X,Y,blockIndex,stride,mode,alpha,beta);
611 const size_t numVecs = X.extent(1);
619 const char prefix[] =
"Ifpack2::DenseContainer::weightedApply: ";
621 ! IsComputed_, std::runtime_error, prefix <<
"You must have called the "
622 "compute() method before you may call this method. You may call "
623 "apply() as many times as you want after calling compute() once, "
624 "but you must have called compute() at least once first.");
626 X.extent (1) != Y.extent (1), std::runtime_error,
627 prefix <<
"X and Y have different numbers of vectors (columns). X has "
628 << X.extent (1) <<
", but Y has " << Y.extent (1) <<
".");
659 if(X_local.size() == 0)
663 for(
int i = 0; i < this->numBlocks_; i++)
665 X_local.emplace_back(
"", this->blockRows_[i], numVecs);
667 for(
int i = 0; i < this->numBlocks_; i++)
669 Y_local.emplace_back(
"", this->blockRows_[i], numVecs);
673 const ArrayView<const local_ordinal_type> localRows = this->getLocalRows(blockIndex);
675 Details::MultiVectorLocalGatherScatter<mv_type, local_mv_type> mvgs;
676 mvgs.gatherViewToView (X_local[blockIndex], X, localRows);
683 mvgs.gatherViewToView (Y_local[blockIndex], Y, localRows);
687 this->applyImpl (X_local[blockIndex], Y_local[blockIndex], blockIndex, stride, mode,
688 as<local_scalar_type>(alpha), as<local_scalar_type>(beta));
692 mvgs.scatterViewToView (Y, Y_local[blockIndex], localRows);
695 template<
class MatrixType,
class LocalScalarType>
696 void DenseContainer<MatrixType, LocalScalarType, true>::
697 weightedApply (HostView& X,
704 scalar_type beta)
const
713 using Teuchos::rcp_const_cast;
724 const char prefix[] =
"Ifpack2::DenseContainer::weightedApply: ";
726 ! IsComputed_, std::runtime_error, prefix <<
"You must have called the "
727 "compute() method before you may call this method. You may call "
728 "weightedApply() as many times as you want after calling compute() once, "
729 "but you must have called compute() at least once first.");
731 const size_t numVecs = X.extent(1);
734 X.extent(1) != Y.extent(1), std::runtime_error,
735 prefix <<
"X and Y have different numbers of vectors (columns). X has "
736 << X.extent(1) <<
", but Y has " << Y.extent(1) <<
".");
742 const size_t numRows = this->blockRows_[blockIndex];
768 if(X_local.size() == 0)
772 for(
int i = 0; i < this->numBlocks_; i++)
774 X_local.emplace_back(
"", this->blockRows_[i], numVecs);
776 for(
int i = 0; i < this->numBlocks_; i++)
778 Y_local.emplace_back(
"", this->blockRows_[i], numVecs);
782 ArrayView<const local_ordinal_type> localRows = this->getLocalRows(blockIndex);
784 Details::MultiVectorLocalGatherScatter<mv_type, local_mv_type> mvgs;
785 mvgs.gatherViewToView (X_local[blockIndex], X, localRows);
791 mvgs.gatherViewToView (Y_local[blockIndex], Y, localRows);
803 HostViewLocal D_local(
"", numRows, 1);
804 mvgs.gatherViewToView (D_local, D, localRows);
805 HostViewLocal X_scaled(
"", numRows, numVecs);
806 for(
size_t j = 0; j < numVecs; j++)
807 for(
size_t i = 0; i < numRows; i++)
808 X_scaled(i, j) = X_local[blockIndex](i, j) * D_local(i, 0);
815 Ptr<HostViewLocal> Y_temp;
816 bool deleteYT =
false;
817 if(beta == STS::zero())
819 Y_temp = ptr(&Y_local[blockIndex]);
821 Y_temp = ptr(
new HostViewLocal(
"", numRows, numVecs));
826 this->applyImpl (X_scaled, *Y_temp, blockIndex, stride, mode, STS::one(), STS::zero());
832 for(
size_t j = 0; j < numVecs; j++)
833 for(
size_t i = 0; i < numRows; i++)
834 Y_local[blockIndex](i, j) = Y_local[blockIndex](i, j) * (local_impl_scalar_type) beta + (local_impl_scalar_type) alpha * (*Y_temp)(i, j) * D_local(i, 0);
841 mvgs.scatterViewToView (Y, Y_local[blockIndex], localRows);
844 template<class MatrixType, class LocalScalarType>
846 DenseContainer<MatrixType, LocalScalarType, true>::
847 print (std::ostream& os)
const
850 fos.setOutputToRootOnly (0);
851 this->describe (fos);
855 template<
class MatrixType,
class LocalScalarType>
857 DenseContainer<MatrixType, LocalScalarType, true>::
860 std::ostringstream oss;
861 oss <<
"Ifpack::DenseContainer: ";
862 if (isInitialized()) {
864 oss <<
"{status = initialized, computed";
867 oss <<
"{status = initialized, not computed";
871 oss <<
"{status = not initialized, not computed";
878 template<
class MatrixType,
class LocalScalarType>
880 DenseContainer<MatrixType, LocalScalarType, true>::
886 os <<
"================================================================================" << endl;
887 os <<
"Ifpack2::DenseContainer" << endl;
888 for(
int i = 0; i < this->numBlocks_; i++)
890 os <<
"Block " << i <<
" number of rows = " << this->blockRows_[i] << endl;
892 os <<
"isInitialized() = " << IsInitialized_ << endl;
893 os <<
"isComputed() = " << IsComputed_ << endl;
894 os <<
"================================================================================" << endl;
899 template<
class MatrixType,
class LocalScalarType>
901 DenseContainer<MatrixType, LocalScalarType, true>::
907 auto& A = this->inputMatrix_;
908 const size_t inputMatrixNumRows = A->getNodeNumRows();
912 const int myRank = A->getRowMap ()->getComm ()->getRank ();
913 const int numProcs = A->getRowMap ()->getComm ()->getSize ();
917 for(
int i = 0; i < this->numBlocks_; ++i) {
918 ArrayView<const local_ordinal_type> localRows = this->getLocalRows(i);
919 for(local_ordinal_type j = 0; j < this->blockRows_[i]; ++j) {
922 static_cast<size_t>(localRows[j]) >= inputMatrixNumRows,
923 std::runtime_error,
"Ifpack2::DenseContainer::extract: On process " <<
924 myRank <<
" of " << numProcs <<
", localRows[j=" << j <<
"] = " <<
925 localRows[j] <<
", which is out of the valid range of local row indices "
926 "indices [0, " << (inputMatrixNumRows - 1) <<
"] for the input matrix.");
940 auto globalRowMap = A->getRowMap ();
941 auto globalColMap = A->getColMap ();
942 auto globalDomMap = A->getDomainMap ();
944 for(
int blockIndex = 0; blockIndex < this->numBlocks_; blockIndex++)
946 const local_ordinal_type numRows_ = this->blockRows_[blockIndex];
948 bool rowIndsValid =
true;
949 bool colIndsValid =
true;
950 Array<local_ordinal_type> localCols(numRows_);
953 Array<local_ordinal_type> invalidLocalRowInds;
954 Array<global_ordinal_type> invalidGlobalColInds;
955 for (local_ordinal_type i = 0; i < numRows_; i++)
958 const local_ordinal_type ii_local = localRows[i];
963 const global_ordinal_type jj_global = globalRowMap->getGlobalElement(ii_local);
971 rowIndsValid =
false;
972 invalidLocalRowInds.push_back(ii_local);
977 if(globalDomMap->isNodeGlobalElement(jj_global))
987 const local_ordinal_type jj_local = globalColMap->getLocalElement(jj_global);
990 colIndsValid =
false;
991 invalidGlobalColInds.push_back(jj_global);
994 localCols[i] = jj_local;
998 !rowIndsValid, std::logic_error,
"Ifpack2::DenseContainer::extract: "
999 "On process " << myRank <<
", at least one row index in the set of local "
1000 "row indices given to the constructor is not a valid local row index in "
1001 "the input matrix's row Map on this process. This should be impossible "
1002 "because the constructor checks for this case. Here is the complete set "
1003 "of invalid local row indices: " <<
toString(invalidLocalRowInds) <<
". "
1004 "Please report this bug to the Ifpack2 developers.");
1006 !colIndsValid, std::runtime_error,
"Ifpack2::DenseContainer::extract: "
1007 "On process " << myRank <<
", "
1008 "At least one row index in the set of row indices given to the constructor "
1009 "does not have a corresponding column index in the input matrix's column "
1010 "Map. This probably means that the column(s) in question is/are empty on "
1011 "this process, which would make the submatrix to extract structurally "
1012 "singular. Here is the compete set of invalid global column indices: "
1013 <<
toString(invalidGlobalColInds) <<
".");
1017 const size_t maxNumEntriesInRow = A->getNodeMaxNumRowEntries();
1018 Array<local_ordinal_type> ind(maxNumEntriesInRow);
1022 Array<scalar_type> val(maxNumEntriesInRow * this->bcrsBlockSize_ * this->bcrsBlockSize_);
1023 for(local_ordinal_type i = 0; i < numRows_; i++)
1025 const local_ordinal_type localRow = localRows[i];
1027 A->getLocalRowCopy(localRow, ind(), val(), numEntries);
1029 for(
size_t k = 0; k < numEntries; k++)
1031 const local_ordinal_type localCol = ind[k];
1041 if(localCol >= 0 && static_cast<size_t> (localCol) < inputMatrixNumRows)
1045 local_ordinal_type jj = INVALID;
1046 for(local_ordinal_type kk = 0; kk < numRows_; kk++)
1048 if(localRows[kk] == localCol)
1054 for(local_ordinal_type c = 0; c < this->bcrsBlockSize_; c++)
1056 for(local_ordinal_type r = 0; r < this->bcrsBlockSize_; r++)
1057 diagBlocks_[blockIndex](this->bcrsBlockSize_ * i + r,
1058 this->bcrsBlockSize_ * jj + c)
1059 = val[k * (this->bcrsBlockSize_ * this->bcrsBlockSize_)
1060 + (r + this->bcrsBlockSize_ * c)];
1070 template<
class MatrixType,
class LocalScalarType>
1072 DenseContainer<MatrixType, LocalScalarType, true>::
1078 auto& A = *this->inputMatrix_;
1079 const size_t inputMatrixNumRows = A.getNodeNumRows();
1083 const int myRank = A.getRowMap ()->getComm ()->getRank ();
1084 const int numProcs = A.getRowMap ()->getComm ()->getSize ();
1086 for(
int blockIndex = 0; blockIndex < this->numBlocks_; blockIndex++)
1088 local_ordinal_type numRows_ = this->blockRows_[blockIndex];
1090 if(this->hasBlockCrs_)
1098 ArrayView<const local_ordinal_type> localRows = this->getLocalRows(blockIndex);
1099 for(local_ordinal_type j = 0; j < numRows_; j++)
1103 static_cast<size_t> (localRows[j]) >= inputMatrixNumRows,
1104 std::runtime_error,
"Ifpack2::DenseContainer::extract: On process " <<
1105 myRank <<
" of " << numProcs <<
", localRows[j=" << j <<
"] = " <<
1106 localRows[j] <<
", which is out of the valid range of local row indices "
1107 "indices [0, " << (inputMatrixNumRows - 1) <<
"] for the input matrix.");
1120 const map_type& globalRowMap = * (A.getRowMap ());
1121 const map_type& globalColMap = * (A.getColMap ());
1122 const map_type& globalDomMap = * (A.getDomainMap ());
1124 bool rowIndsValid =
true;
1125 bool colIndsValid =
true;
1126 Array<local_ordinal_type> localCols(numRows_);
1129 Array<local_ordinal_type> invalidLocalRowInds;
1130 Array<global_ordinal_type> invalidGlobalColInds;
1131 for(local_ordinal_type i = 0; i < numRows_; i++)
1134 const local_ordinal_type ii_local = localRows[i];
1139 const global_ordinal_type jj_global = globalRowMap.getGlobalElement(ii_local);
1147 rowIndsValid =
false;
1148 invalidLocalRowInds.push_back(ii_local);
1153 if(globalDomMap.isNodeGlobalElement(jj_global))
1163 const local_ordinal_type jj_local = globalColMap.getLocalElement(jj_global);
1166 colIndsValid =
false;
1167 invalidGlobalColInds.push_back(jj_global);
1170 localCols[i] = jj_local;
1174 !rowIndsValid, std::logic_error,
"Ifpack2::DenseContainer::extract: "
1175 "On process " << myRank <<
", at least one row index in the set of local "
1176 "row indices given to the constructor is not a valid local row index in "
1177 "the input matrix's row Map on this process. This should be impossible "
1178 "because the constructor checks for this case. Here is the complete set "
1179 "of invalid local row indices: " <<
toString(invalidLocalRowInds) <<
". "
1180 "Please report this bug to the Ifpack2 developers.");
1182 !colIndsValid, std::runtime_error,
"Ifpack2::DenseContainer::extract: "
1183 "On process " << myRank <<
", "
1184 "At least one row index in the set of row indices given to the constructor "
1185 "does not have a corresponding column index in the input matrix's column "
1186 "Map. This probably means that the column(s) in question is/are empty on "
1187 "this process, which would make the submatrix to extract structurally "
1188 "singular. Here is the compete set of invalid global column indices: "
1189 <<
toString(invalidGlobalColInds) <<
".");
1193 const size_t maxNumEntriesInRow = A.getNodeMaxNumRowEntries();
1194 Array<local_ordinal_type> ind(maxNumEntriesInRow);
1198 Array<scalar_type> val(maxNumEntriesInRow);
1199 for (local_ordinal_type i = 0; i < numRows_; i++)
1201 const local_ordinal_type localRow = localRows[i];
1203 A.getLocalRowCopy(localRow, ind(), val(), numEntries);
1204 for (
size_t k = 0; k < numEntries; ++k)
1206 const local_ordinal_type localCol = ind[k];
1216 if(localCol >= 0 && static_cast<size_t> (localCol) < inputMatrixNumRows)
1220 local_ordinal_type jj = INVALID;
1221 for(local_ordinal_type kk = 0; kk < numRows_; kk++)
1223 if(localRows[kk] == localCol)
1227 diagBlocks_[blockIndex](i, jj) += val[k];
1234 template<
class MatrixType,
class LocalScalarType>
1235 void DenseContainer<MatrixType, LocalScalarType, true>::clearBlocks()
1237 std::vector<Teuchos::SerialDenseMatrix<int, local_scalar_type>> empty1;
1238 std::swap(diagBlocks_, empty1);
1240 Teuchos::swap(ipiv_, empty2);
1241 std::vector<HostViewLocal> empty3;
1242 std::swap(X_local, empty3);
1243 std::vector<HostViewLocal> empty4;
1244 std::swap(Y_local, empty4);
1245 Container<MatrixType>::clearBlocks();
1248 template<
class MatrixType,
class LocalScalarType>
1249 std::string DenseContainer<MatrixType, LocalScalarType, true>::getName()
1254 template<
class MatrixType,
class LocalScalarType>
1255 DenseContainer<MatrixType, LocalScalarType, false>::
1260 scalar_type DampingFactor) :
1261 Container<MatrixType> (matrix, partitions, importer, OverlapLevel,
1265 (
true, std::logic_error,
"Ifpack2::DenseContainer: Not implemented for "
1270 template<
class MatrixType,
class LocalScalarType>
1271 DenseContainer<MatrixType, LocalScalarType, false>::
1274 Container<MatrixType>(matrix, localRows)
1277 (
true, std::logic_error,
"Ifpack2::DenseContainer: Not implemented for "
1282 template<
class MatrixType,
class LocalScalarType>
1283 DenseContainer<MatrixType, LocalScalarType, false>::~DenseContainer() {}
1285 template<
class MatrixType,
class LocalScalarType>
1286 void DenseContainer<MatrixType, LocalScalarType, false>::
1289 template<
class MatrixType,
class LocalScalarType>
1290 void DenseContainer<MatrixType, LocalScalarType, false>::initialize() {}
1292 template<
class MatrixType,
class LocalScalarType>
1293 void DenseContainer<MatrixType, LocalScalarType, false>::compute() {}
1295 template<
class MatrixType,
class LocalScalarType>
1296 void DenseContainer<MatrixType, LocalScalarType, false>::factor() {}
1298 template<
class MatrixType,
class LocalScalarType>
1299 void DenseContainer<MatrixType, LocalScalarType, false>::
1300 applyImplBlockCrs (HostViewLocal& X,
1305 local_scalar_type alpha,
1306 local_scalar_type beta)
const {}
1308 template<
class MatrixType,
class LocalScalarType>
1309 void DenseContainer<MatrixType, LocalScalarType, false>::
1310 applyImpl (HostViewLocal& X,
1315 local_scalar_type alpha,
1316 local_scalar_type beta)
const {}
1318 template<
class MatrixType,
class LocalScalarType>
1319 void DenseContainer<MatrixType, LocalScalarType, false>::
1320 applyBlockCrs (HostView& XIn,
1326 scalar_type beta)
const {}
1328 template<
class MatrixType,
class LocalScalarType>
1329 void DenseContainer<MatrixType, LocalScalarType, false>::
1336 scalar_type beta)
const {}
1338 template<
class MatrixType,
class LocalScalarType>
1339 void DenseContainer<MatrixType, LocalScalarType, false>::
1340 weightedApply (HostView& X,
1347 scalar_type beta)
const {}
1349 template<
class MatrixType,
class LocalScalarType>
1350 std::ostream& DenseContainer<MatrixType, LocalScalarType, false>::
1351 print (std::ostream& os)
const
1356 template<
class MatrixType,
class LocalScalarType>
1357 std::string DenseContainer<MatrixType, LocalScalarType, false>::
1358 description ()
const
1363 template<
class MatrixType,
class LocalScalarType>
1364 void DenseContainer<MatrixType, LocalScalarType, false>::
1368 template<
class MatrixType,
class LocalScalarType>
1369 void DenseContainer<MatrixType, LocalScalarType, false>::
1370 extractBlockCrs () {}
1372 template<
class MatrixType,
class LocalScalarType>
1373 void DenseContainer<MatrixType, LocalScalarType, false>::
1376 template<
class MatrixType,
class LocalScalarType>
1377 void DenseContainer<MatrixType, LocalScalarType, false>::clearBlocks() {}
1379 template<
class MatrixType,
class LocalScalarType>
1380 std::string DenseContainer<MatrixType, LocalScalarType, false>::getName()
1391 #define IFPACK2_DENSECONTAINER_INSTANT(S,LO,GO,N) \
1392 template class Ifpack2::DenseContainer< Tpetra::RowMatrix<S, LO, GO, N>, S >;
1394 #endif // IFPACK2_DENSECONTAINER_DEF_HPP
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void GETRF(const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, OrdinalType *IPIV, OrdinalType *info) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
TEUCHOSCORE_LIB_DLL_EXPORT std::string toString(const EVerbosityLevel verbLevel)
void GETRS(const char &TRANS, const OrdinalType &n, const OrdinalType &nrhs, const ScalarType *A, const OrdinalType &lda, const OrdinalType *IPIV, ScalarType *B, const OrdinalType &ldb, OrdinalType *info) const
TypeTo as(const TypeFrom &t)
std::string toString(const T &t)