43 #ifndef IFPACK2_DENSECONTAINER_DEF_HPP 44 #define IFPACK2_DENSECONTAINER_DEF_HPP 46 #include "Tpetra_CrsMatrix.hpp" 47 #include "Teuchos_LAPACK.hpp" 51 # include "Teuchos_DefaultMpiComm.hpp" 53 # include "Teuchos_DefaultSerialComm.hpp" 59 template<
class MatrixType,
class LocalScalarType>
62 const Teuchos::ArrayView<const local_ordinal_type>& localRows) :
63 Container<MatrixType> (matrix, localRows),
64 numRows_ (localRows.size ()),
65 diagBlock_ (numRows_, numRows_),
69 using Teuchos::ArrayView;
72 using Teuchos::toString;
73 typedef Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type> map_type;
74 typedef typename ArrayView<const local_ordinal_type>::size_type size_type;
75 TEUCHOS_TEST_FOR_EXCEPTION(
76 ! matrix->hasColMap (), std::invalid_argument,
"Ifpack2::DenseContainer: " 77 "The constructor's input matrix must have a column Map.");
80 const map_type& rowMap = * (matrix->getRowMap ());
81 const size_type numRows = localRows.size ();
82 bool rowIndicesValid =
true;
83 Array<local_ordinal_type> invalidLocalRowIndices;
84 for (size_type i = 0; i < numRows; ++i) {
85 if (! rowMap.isNodeLocalElement (localRows[i])) {
86 rowIndicesValid =
false;
87 invalidLocalRowIndices.push_back (localRows[i]);
91 TEUCHOS_TEST_FOR_EXCEPTION(
92 ! rowIndicesValid, std::invalid_argument,
"Ifpack2::DenseContainer: " 93 "On process " << rowMap.getComm ()->getRank () <<
" of " 94 << rowMap.getComm ()->getSize () <<
", in the given set of local row " 95 "indices localRows = " <<
toString (localRows) <<
", the following " 96 "entries are not valid local row indices on the calling process: " 97 <<
toString (invalidLocalRowIndices) <<
".");
100 RCP<const Teuchos::Comm<int> > localComm =
101 rcp (
new Teuchos::MpiComm<int> (MPI_COMM_SELF));
103 RCP<const Teuchos::Comm<int> > localComm =
104 rcp (
new Teuchos::SerialComm<int> ());
110 localMap_ = rcp (
new map_type (numRows_, indexBase, localComm));
113 template<
class MatrixType,
class LocalScalarType>
116 const Teuchos::ArrayView<const local_ordinal_type>& localRows) :
117 Container<MatrixType> (matrix, localRows)
119 TEUCHOS_TEST_FOR_EXCEPTION
120 (
true, std::logic_error,
"Ifpack2::DenseContainer: Not implemented for " 121 "LocalScalarType = " << Teuchos::TypeNameTraits<LocalScalarType>::name ()
125 template<
class MatrixType,
class LocalScalarType>
129 template<
class MatrixType,
class LocalScalarType>
134 template<
class MatrixType,
class LocalScalarType>
141 template<
class MatrixType,
class LocalScalarType>
149 template<
class MatrixType,
class LocalScalarType>
159 IsInitialized_ =
false;
163 diagBlock_.putScalar (Teuchos::ScalarTraits<local_scalar_type>::zero ());
164 std::fill (ipiv_.begin (), ipiv_.end (), 0);
166 IsInitialized_ =
true;
169 template<
class MatrixType,
class LocalScalarType>
175 template<
class MatrixType,
class LocalScalarType>
180 TEUCHOS_TEST_FOR_EXCEPTION(
181 static_cast<size_t> (ipiv_.size ()) != numRows_, std::logic_error,
182 "Ifpack2::DenseContainer::compute: ipiv_ array has the wrong size. " 183 "Please report this bug to the Ifpack2 developers.");
186 if (! this->isInitialized ()) {
191 extract (this->getMatrix ());
197 template<
class MatrixType,
class LocalScalarType>
203 template<
class MatrixType,
class LocalScalarType>
208 Teuchos::LAPACK<int, local_scalar_type> lapack;
210 lapack.GETRF (diagBlock_.numRows (), diagBlock_.numCols (),
211 diagBlock_.values (), diagBlock_.stride (),
212 ipiv_.getRawPtr (), &INFO);
214 TEUCHOS_TEST_FOR_EXCEPTION(
215 INFO < 0, std::logic_error,
"Ifpack2::DenseContainer::factor: " 216 "LAPACK's _GETRF (LU factorization with partial pivoting) was called " 217 "incorrectly. INFO = " << INFO <<
" < 0. " 218 "Please report this bug to the Ifpack2 developers.");
222 TEUCHOS_TEST_FOR_EXCEPTION(
223 INFO > 0, std::runtime_error,
"Ifpack2::DenseContainer::factor: " 224 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the " 225 "computed U factor is exactly singular. U(" << INFO <<
"," << INFO <<
") " 226 "(one-based index i) is exactly zero. This probably means that the input " 227 "matrix has a singular diagonal block.");
230 template<
class MatrixType,
class LocalScalarType>
236 template<
class MatrixType,
class LocalScalarType>
241 Teuchos::ETransp mode,
242 LocalScalarType alpha,
243 LocalScalarType beta)
const 245 using Teuchos::ArrayRCP;
248 using Teuchos::rcpFromRef;
250 TEUCHOS_TEST_FOR_EXCEPTION(
251 X.getLocalLength () != Y.getLocalLength (),
252 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: X and Y have " 253 "incompatible dimensions (" << X.getLocalLength () <<
" resp. " 254 << Y.getLocalLength () <<
"). Please report this bug to " 255 "the Ifpack2 developers.");
256 TEUCHOS_TEST_FOR_EXCEPTION(
257 localMap_->getNodeNumElements () != X.getLocalLength (),
258 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: The inverse " 259 "operator and X have incompatible dimensions (" <<
260 localMap_->getNodeNumElements () <<
" resp. " 261 << X.getLocalLength () <<
"). Please report this bug to " 262 "the Ifpack2 developers.");
263 TEUCHOS_TEST_FOR_EXCEPTION(
264 localMap_->getNodeNumElements () != Y.getLocalLength (),
265 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: The inverse " 266 "operator and Y have incompatible dimensions (" <<
267 localMap_->getNodeNumElements () <<
" resp. " 268 << Y.getLocalLength () <<
"). Please report this bug to " 269 "the Ifpack2 developers.");
270 TEUCHOS_TEST_FOR_EXCEPTION(
271 X.getLocalLength () !=
static_cast<size_t> (diagBlock_.numRows ()),
272 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: The input " 273 "multivector X has incompatible dimensions from those of the " 274 "inverse operator (" << X.getLocalLength () <<
" vs. " 275 << (mode == Teuchos::NO_TRANS ? diagBlock_.numCols () : diagBlock_.numRows ())
276 <<
"). Please report this bug to the Ifpack2 developers.");
277 TEUCHOS_TEST_FOR_EXCEPTION(
278 X.getLocalLength () !=
static_cast<size_t> (diagBlock_.numRows ()),
279 std::logic_error,
"Ifpack2::DenseContainer::applyImpl: The output " 280 "multivector Y has incompatible dimensions from those of the " 281 "inverse operator (" << Y.getLocalLength () <<
" vs. " 282 << (mode == Teuchos::NO_TRANS ? diagBlock_.numRows () : diagBlock_.numCols ())
283 <<
"). Please report this bug to the Ifpack2 developers.");
285 typedef Teuchos::ScalarTraits<local_scalar_type> STS;
286 const int numVecs =
static_cast<int> (X.getNumVectors ());
287 if (alpha == STS::zero ()) {
288 if (beta == STS::zero ()) {
292 Y.putScalar (STS::zero ());
299 Teuchos::LAPACK<int, local_scalar_type> lapack;
303 RCP<local_mv_type> Y_tmp;
304 if (beta == STS::zero () ){
305 Tpetra::deep_copy (Y, X);
306 Y_tmp = rcpFromRef (Y);
309 Y_tmp = rcp (
new local_mv_type (X, Teuchos::Copy));
311 const int Y_stride =
static_cast<int> (Y_tmp->getStride ());
312 ArrayRCP<local_scalar_type> Y_view = Y_tmp->get1dViewNonConst ();
317 (mode == Teuchos::CONJ_TRANS ?
'C' : (mode == Teuchos::TRANS ?
'T' :
'N'));
318 lapack.GETRS (trans, diagBlock_.numRows (), numVecs,
319 diagBlock_.values (), diagBlock_.stride (),
320 ipiv_.getRawPtr (), Y_ptr, Y_stride, &INFO);
321 TEUCHOS_TEST_FOR_EXCEPTION(
322 INFO != 0, std::runtime_error,
"Ifpack2::DenseContainer::applyImpl: " 323 "LAPACK's _GETRS (solve using LU factorization with partial pivoting) " 324 "failed with INFO = " << INFO <<
" != 0.");
326 if (beta != STS::zero ()) {
327 Y.update (alpha, *Y_tmp, beta);
329 else if (! Y.isConstantStride ()) {
330 Tpetra::deep_copy (Y, *Y_tmp);
335 template<
class MatrixType,
class LocalScalarType>
342 LocalScalarType )
const 345 template<
class MatrixType,
class LocalScalarType>
348 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
349 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
350 Teuchos::ETransp mode,
352 scalar_type beta)
const 354 using Teuchos::ArrayView;
366 typedef Tpetra::MultiVector<scalar_type,
369 const char prefix[] =
"Ifpack2::DenseContainer::weightedApply: ";
370 TEUCHOS_TEST_FOR_EXCEPTION(
371 ! IsComputed_, std::runtime_error, prefix <<
"You must have called the " 372 "compute() method before you may call this method. You may call " 373 "apply() as many times as you want after calling compute() once, " 374 "but you must have called compute() at least once first.");
375 const size_t numVecs = X.getNumVectors ();
376 TEUCHOS_TEST_FOR_EXCEPTION(
377 numVecs != Y.getNumVectors (), std::runtime_error,
378 prefix <<
"X and Y have different numbers of vectors (columns). X has " 379 << X.getNumVectors () <<
", but Y has " << X.getNumVectors () <<
".");
411 X_ = rcp (
new local_mv_type (localMap_, numVecs));
413 RCP<local_mv_type> X_local = X_;
414 TEUCHOS_TEST_FOR_EXCEPTION(
415 X_local->getLocalLength () != numRows_, std::logic_error,
416 "Ifpack2::DenseContainer::apply: " 417 "X_local has length " << X_local->getLocalLength () <<
", which does " 418 "not match numRows_ = " << numRows_ <<
". Please report this bug to " 419 "the Ifpack2 developers.");
420 ArrayView<const local_ordinal_type> localRows = this->getLocalRows ();
423 mvgs.gather (*X_local, X, localRows);
431 Y_ = rcp (
new local_mv_type (localMap_, numVecs));
433 RCP<local_mv_type> Y_local = Y_;
434 TEUCHOS_TEST_FOR_EXCEPTION(
435 Y_local->getLocalLength () != numRows_, std::logic_error,
436 "Ifpack2::DenseContainer::apply: " 437 "Y_local has length " << X_local->getLocalLength () <<
", which does " 438 "not match numRows_ = " << numRows_ <<
". Please report this bug to " 439 "the Ifpack2 developers.");
440 mvgs.gather (*Y_local, Y, localRows);
444 this->applyImpl (*X_local, *Y_local, mode, as<local_scalar_type> (alpha),
445 as<local_scalar_type> (beta));
449 mvgs.scatter (Y, *Y_local, localRows);
452 template<
class MatrixType,
class LocalScalarType>
455 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& ,
456 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& ,
462 template<
class MatrixType,
class LocalScalarType>
464 weightedApply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
465 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
466 const Tpetra::Vector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& D,
467 Teuchos::ETransp mode,
469 scalar_type beta)
const 471 using Teuchos::ArrayRCP;
472 using Teuchos::ArrayView;
473 using Teuchos::Range1D;
476 using Teuchos::rcp_const_cast;
479 typedef Teuchos::ScalarTraits<scalar_type> STS;
489 typedef Tpetra::MultiVector<scalar_type,
495 global_ordinal_type,
node_type> local_vec_type;
497 const char prefix[] =
"Ifpack2::DenseContainer::weightedApply: ";
498 TEUCHOS_TEST_FOR_EXCEPTION(
499 ! IsComputed_, std::runtime_error, prefix <<
"You must have called the " 500 "compute() method before you may call this method. You may call " 501 "weightedApply() as many times as you want after calling compute() once, " 502 "but you must have called compute() at least once first.");
503 const size_t numVecs = X.getNumVectors ();
504 TEUCHOS_TEST_FOR_EXCEPTION(
505 numVecs != Y.getNumVectors (), std::runtime_error,
506 prefix <<
"X and Y have different numbers of vectors (columns). X has " 507 << X.getNumVectors () <<
", but Y has " << X.getNumVectors () <<
".");
538 X_ = rcp (
new local_mv_type (localMap_, numVecs));
540 RCP<local_mv_type> X_local = X_;
541 TEUCHOS_TEST_FOR_EXCEPTION(
542 X_local->getLocalLength () != numRows_, std::logic_error,
543 "Ifpack2::DenseContainer::weightedApply: " 544 "X_local has length " << X_local->getLocalLength () <<
", which does " 545 "not match numRows_ = " << numRows_ <<
". Please report this bug to " 546 "the Ifpack2 developers.");
547 ArrayView<const local_ordinal_type> localRows = this->getLocalRows ();
550 mvgs.gather (*X_local, X, localRows);
558 Y_ = rcp (
new local_mv_type (localMap_, numVecs));
560 RCP<local_mv_type> Y_local = Y_;
561 TEUCHOS_TEST_FOR_EXCEPTION(
562 Y_local->getLocalLength () != numRows_, std::logic_error,
563 "Ifpack2::DenseContainer::weightedApply: " 564 "Y_local has length " << X_local->getLocalLength () <<
", which does " 565 "not match numRows_ = " << numRows_ <<
". Please report this bug to " 566 "the Ifpack2 developers.");
567 mvgs.gather (*Y_local, Y, localRows);
579 local_vec_type D_local (localMap_);
580 TEUCHOS_TEST_FOR_EXCEPTION(
581 D_local.getLocalLength () != numRows_, std::logic_error,
582 "Ifpack2::DenseContainer::weightedApply: " 583 "D_local has length " << D_local.getLocalLength () <<
", which does " 584 "not match numRows_ = " << numRows_ <<
". Please report this bug to " 585 "the Ifpack2 developers.");
586 mvgs.gather (D_local, D, localRows);
587 local_mv_type X_scaled (localMap_, numVecs);
588 X_scaled.elementWiseMultiply (STS::one (), D_local, *X_local, STS::zero ());
595 RCP<local_mv_type> Y_temp;
596 if (beta == STS::zero ()) {
599 Y_temp = rcp (
new local_mv_type (localMap_, numVecs));
603 this->applyImpl (X_scaled, *Y_temp, mode, STS::one (), STS::zero ());
609 Y_local->elementWiseMultiply (alpha, D_local, *Y_temp, beta);
613 mvgs.scatter (Y, *Y_local, localRows);
616 template<
class MatrixType,
class LocalScalarType>
619 weightedApply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& ,
620 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& ,
621 const Tpetra::Vector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& ,
628 template<
class MatrixType,
class LocalScalarType>
633 Teuchos::FancyOStream fos (Teuchos::rcpFromRef (os));
634 fos.setOutputToRootOnly (0);
635 this->describe (fos);
639 template<
class MatrixType,
class LocalScalarType>
647 template<
class MatrixType,
class LocalScalarType>
652 std::ostringstream oss;
653 oss << Teuchos::Describable::description();
654 if (isInitialized()) {
656 oss <<
"{status = initialized, computed";
659 oss <<
"{status = initialized, not computed";
663 oss <<
"{status = not initialized, not computed";
670 template<
class MatrixType,
class LocalScalarType>
678 template<
class MatrixType,
class LocalScalarType>
682 const Teuchos::EVerbosityLevel verbLevel)
const 685 if(verbLevel==Teuchos::VERB_NONE)
return;
686 os <<
"================================================================================" << endl;
687 os <<
"Ifpack2::DenseContainer" << endl;
688 os <<
"Number of rows = " << numRows_ << endl;
689 os <<
"isInitialized() = " << IsInitialized_ << endl;
690 os <<
"isComputed() = " << IsComputed_ << endl;
691 os <<
"================================================================================" << endl;
695 template<
class MatrixType,
class LocalScalarType>
699 const Teuchos::EVerbosityLevel verbLevel)
const 702 template<
class MatrixType,
class LocalScalarType>
705 extract (
const Teuchos::RCP<const row_matrix_type>& globalMatrix)
707 using Teuchos::Array;
708 using Teuchos::ArrayView;
709 using Teuchos::toString;
712 typedef Tpetra::Map<LO, GO, node_type> map_type;
713 const size_t inputMatrixNumRows = globalMatrix->getNodeNumRows ();
717 const int myRank = globalMatrix->getRowMap ()->getComm ()->getRank ();
718 const int numProcs = globalMatrix->getRowMap ()->getComm ()->getSize ();
722 ArrayView<const LO> localRows = this->getLocalRows ();
723 for (
size_t j = 0; j < numRows_; ++j) {
724 TEUCHOS_TEST_FOR_EXCEPTION(
726 static_cast<size_t> (localRows[j]) >= inputMatrixNumRows,
727 std::runtime_error,
"Ifpack2::DenseContainer::extract: On process " <<
728 myRank <<
" of " << numProcs <<
", localRows[j=" << j <<
"] = " <<
729 localRows[j] <<
", which is out of the valid range of local row indices " 730 "indices [0, " << (inputMatrixNumRows - 1) <<
"] for the input matrix.");
743 const map_type& globalRowMap = * (globalMatrix->getRowMap ());
744 const map_type& globalColMap = * (globalMatrix->getColMap ());
745 const map_type& globalDomMap = * (globalMatrix->getDomainMap ());
747 bool rowIndsValid =
true;
748 bool colIndsValid =
true;
749 Array<LO> localCols (numRows_);
752 Array<LO> invalidLocalRowInds;
753 Array<GO> invalidGlobalColInds;
754 for (
size_t i = 0; i < numRows_; ++i) {
756 const LO ii_local = localRows[i];
761 const GO jj_global = globalRowMap.getGlobalElement (ii_local);
762 if (jj_global == Teuchos::OrdinalTraits<GO>::invalid ()) {
768 rowIndsValid =
false;
769 invalidLocalRowInds.push_back (ii_local);
774 if (globalDomMap.isNodeGlobalElement (jj_global)) {
783 const LO jj_local = globalColMap.getLocalElement (jj_global);
784 if (jj_local == Teuchos::OrdinalTraits<local_ordinal_type>::invalid ()) {
785 colIndsValid =
false;
786 invalidGlobalColInds.push_back (jj_global);
789 localCols[i] = jj_local;
792 TEUCHOS_TEST_FOR_EXCEPTION(
793 ! rowIndsValid, std::logic_error,
"Ifpack2::DenseContainer::extract: " 794 "On process " << myRank <<
", at least one row index in the set of local " 795 "row indices given to the constructor is not a valid local row index in " 796 "the input matrix's row Map on this process. This should be impossible " 797 "because the constructor checks for this case. Here is the complete set " 798 "of invalid local row indices: " <<
toString (invalidLocalRowInds) <<
". " 799 "Please report this bug to the Ifpack2 developers.");
800 TEUCHOS_TEST_FOR_EXCEPTION(
801 ! colIndsValid, std::runtime_error,
"Ifpack2::DenseContainer::extract: " 802 "On process " << myRank <<
", " 803 "At least one row index in the set of row indices given to the constructor " 804 "does not have a corresponding column index in the input matrix's column " 805 "Map. This probably means that the column(s) in question is/are empty on " 806 "this process, which would make the submatrix to extract structurally " 807 "singular. Here is the compete set of invalid global column indices: " 808 <<
toString (invalidGlobalColInds) <<
".");
810 diagBlock_.putScalar (Teuchos::ScalarTraits<local_scalar_type>::zero ());
812 const size_t maxNumEntriesInRow = globalMatrix->getNodeMaxNumRowEntries ();
813 Array<scalar_type> val (maxNumEntriesInRow);
814 Array<local_ordinal_type> ind (maxNumEntriesInRow);
817 Teuchos::OrdinalTraits<local_ordinal_type>::invalid ();
818 for (
size_t i = 0; i < numRows_; ++i) {
821 globalMatrix->getLocalRowCopy (localRow, ind (), val (), numEntries);
823 for (
size_t k = 0; k < numEntries; ++k) {
835 if (localCol >= 0 && static_cast<size_t> (localCol) < inputMatrixNumRows) {
839 for (
size_t kk = 0; kk < numRows_; ++kk) {
840 if (localRows[kk] == localCol) {
845 diagBlock_ (i, jj) += val[k];
852 template<
class MatrixType,
class LocalScalarType>
855 extract (
const Teuchos::RCP<const row_matrix_type>& )
864 #define IFPACK2_DENSECONTAINER_INSTANT(S,LO,GO,N) \ 865 template class Ifpack2::DenseContainer< Tpetra::RowMatrix<S, LO, GO, N>, S >; 867 #endif // IFPACK2_SPARSECONTAINER_HPP DenseContainer(const Teuchos::RCP< const row_matrix_type > &matrix, const Teuchos::ArrayView< const local_ordinal_type > &localRows)
Constructor.
Definition: Ifpack2_DenseContainer_def.hpp:61
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input (global) matrix.
Definition: Ifpack2_DenseContainer_decl.hpp:332
Store and solve a local dense linear problem.
Definition: Ifpack2_DenseContainer_decl.hpp:108
LocalScalarType local_scalar_type
The second template parameter of this class.
Definition: Ifpack2_DenseContainer_decl.hpp:325
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input (global) matrix.
Definition: Ifpack2_DenseContainer_decl.hpp:134
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input (global) matrix.
Definition: Ifpack2_DenseContainer_decl.hpp:330
LocalScalarType local_scalar_type
The second template parameter of this class.
Definition: Ifpack2_DenseContainer_decl.hpp:127
MatrixType::node_type node_type
The Node type of the input (global) matrix.
Definition: Ifpack2_DenseContainer_decl.hpp:136
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input (global) matrix.
Definition: Ifpack2_DenseContainer_decl.hpp:132
Interface for creating and solving a local linear problem.
Definition: Ifpack2_Container.hpp:103
BELOS_DEPRECATED const char * toString(const StatusType status)
Preconditioners and smoothers for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:72
Implementation detail of Ifpack2::Container subclasses.
Definition: Ifpack2_Details_MultiVectorLocalGatherScatter.hpp:85