43 #ifndef IFPACK2_SPARSECONTAINER_DEF_HPP
44 #define IFPACK2_SPARSECONTAINER_DEF_HPP
51 #include "Teuchos_DefaultSerialComm.hpp"
58 template<
class MatrixType,
class InverseType>
64 ContainerImpl<MatrixType, InverseScalar> (matrix, partitions, pointIndexed),
66 localComm_ (Teuchos::
rcp (new Teuchos::MpiComm<int> (MPI_COMM_SELF)))
68 localComm_ (Teuchos::
rcp (new Teuchos::SerialComm<int> ()))
73 template<
class MatrixType,
class InverseType>
78 template<
class MatrixType,
class InverseType>
85 template<
class MatrixType,
class InverseType>
96 diagBlocks_.assign(this->numBlocks_, Teuchos::null);
97 Inverses_.assign(this->numBlocks_, Teuchos::null);
99 this->IsInitialized_ =
true;
100 this->IsComputed_ =
false;
104 template<
class MatrixType,
class InverseType>
107 this->IsComputed_ =
false;
108 if (!this->isInitialized ()) {
118 for(
int i = 0; i < this->numBlocks_; i++)
120 Inverses_[i]->setParameters(List_);
121 Inverses_[i]->initialize ();
123 for(
int i = 0; i < this->numBlocks_; i++)
124 Inverses_[i]->compute ();
125 this->IsComputed_ =
true;
129 template<
class MatrixType,
class InverseType>
132 for(
auto inv : Inverses_)
140 template<
class MatrixType,
class InverseType>
147 InverseScalar beta)
const
150 Inverses_[blockIndex]->getDomainMap()->getNodeNumElements() != X.getLocalLength(),
151 std::logic_error,
"Ifpack2::SparseContainer::apply: Inverse_ "
152 "operator and X have incompatible dimensions (" <<
153 Inverses_[blockIndex]->getDomainMap()->getNodeNumElements() <<
" resp. "
154 << X.getLocalLength() <<
"). Please report this bug to "
155 "the Ifpack2 developers.");
157 Inverses_[blockIndex]->getRangeMap()->getNodeNumElements() != Y.getLocalLength(),
158 std::logic_error,
"Ifpack2::SparseContainer::apply: Inverse_ "
159 "operator and Y have incompatible dimensions (" <<
160 Inverses_[blockIndex]->getRangeMap()->getNodeNumElements() <<
" resp. "
161 << Y.getLocalLength() <<
"). Please report this bug to "
162 "the Ifpack2 developers.");
163 Inverses_[blockIndex]->apply(X, Y, mode, alpha, beta);
166 template<
class MatrixType,
class InverseType>
189 size_t numVecs = X.extent(1);
192 ! this->IsComputed_, std::runtime_error,
"Ifpack2::SparseContainer::apply: "
193 "You must have called the compute() method before you may call apply(). "
194 "You may call the apply() method as many times as you want after calling "
195 "compute() once, but you must have called compute() at least once.");
197 X.extent(1) != Y.extent(1), std::runtime_error,
198 "Ifpack2::SparseContainer::apply: X and Y have different numbers of "
199 "vectors. X has " << X.extent(1)
200 <<
", but Y has " << Y.extent(1) <<
".");
206 const LO numRows = this->blockSizes_[blockIndex];
235 for(LO i = 0; i < this->numBlocks_; i++)
236 invX.emplace_back(Inverses_[i]->getDomainMap(), numVecs);
237 for(LO i = 0; i < this->numBlocks_; i++)
238 invY.emplace_back(Inverses_[i]->getDomainMap(), numVecs);
240 inverse_mv_type& X_local = invX[blockIndex];
242 X_local.getLocalLength() != size_t(numRows * this->scalarsPerRow_), std::logic_error,
243 "Ifpack2::SparseContainer::apply: "
244 "X_local has length " << X_local.getLocalLength() <<
", which does "
245 "not match numRows = " << numRows * this->scalarsPerRow_ <<
". Please report this bug to "
246 "the Ifpack2 developers.");
247 const ArrayView<const LO> blockRows = this->getBlockRows(blockIndex);
248 if(this->scalarsPerRow_ == 1)
249 mvgs.gatherMVtoView(X_local, X, blockRows);
251 mvgs.gatherMVtoViewBlock(X_local, X, blockRows, this->scalarsPerRow_);
258 inverse_mv_type& Y_local = invY[blockIndex];
260 Y_local.getLocalLength () != size_t(numRows * this->scalarsPerRow_), std::logic_error,
261 "Ifpack2::SparseContainer::apply: "
262 "Y_local has length " << Y_local.getLocalLength () <<
", which does "
263 "not match numRows = " << numRows * this->scalarsPerRow_ <<
". Please report this bug to "
264 "the Ifpack2 developers.");
266 if(this->scalarsPerRow_ == 1)
267 mvgs.gatherMVtoView(Y_local, Y, blockRows);
269 mvgs.gatherMVtoViewBlock(Y_local, Y, blockRows, this->scalarsPerRow_);
273 this->solveBlockMV(X_local, Y_local, blockIndex, mode,
274 InverseScalar(alpha), InverseScalar(beta));
279 if(this->scalarsPerRow_ == 1)
280 mvgs.scatterMVtoView(Y, Y_local, blockRows);
282 mvgs.scatterMVtoViewBlock(Y, Y_local, blockRows, this->scalarsPerRow_);
286 template<
class MatrixType,
class InverseType>
312 typedef Tpetra::Vector<InverseScalar, InverseLocalOrdinal, InverseGlobalOrdinal, InverseNode> inverse_vector_type;
315 const size_t numVecs = X.extent(1);
318 ! this->IsComputed_, std::runtime_error,
"Ifpack2::SparseContainer::"
319 "weightedApply: You must have called the compute() method before you may "
320 "call apply(). You may call the apply() method as many times as you want "
321 "after calling compute() once, but you must have called compute() at least "
324 X.extent(1) != Y.extent(1), std::runtime_error,
325 "Ifpack2::SparseContainer::weightedApply: X and Y have different numbers "
326 "of vectors. X has " << X.extent(1) <<
", but Y has "
327 << Y.extent(1) <<
".");
331 this->scalarsPerRow_ > 1, std::logic_error,
"Ifpack2::SparseContainer::weightedApply: "
332 "Use of block rows isn't allowed in overlapping Jacobi (the only method that uses weightedApply");
362 const LO numRows = this->blockSizes_[blockIndex];
366 for(LO i = 0; i < this->numBlocks_; i++)
367 invX.emplace_back(Inverses_[i]->getDomainMap(), numVecs);
368 for(LO i = 0; i < this->numBlocks_; i++)
369 invY.emplace_back(Inverses_[i]->getDomainMap(), numVecs);
371 inverse_mv_type& X_local = invX[blockIndex];
372 const ArrayView<const LO> blockRows = this->getBlockRows(blockIndex);
373 mvgs.gatherMVtoView(X_local, X, blockRows);
380 inverse_mv_type Y_local = invY[blockIndex];
381 TEUCHOS_TEST_FOR_EXCEPTION(
382 Y_local.getLocalLength() != size_t(numRows), std::logic_error,
383 "Ifpack2::SparseContainer::weightedApply: "
384 "Y_local has length " << X_local.getLocalLength() <<
", which does "
385 "not match numRows = " << numRows <<
". Please report this bug to "
386 "the Ifpack2 developers.");
387 mvgs.gatherMVtoView(Y_local, Y, blockRows);
399 inverse_vector_type D_local(Inverses_[blockIndex]->getDomainMap());
400 TEUCHOS_TEST_FOR_EXCEPTION(
401 D_local.getLocalLength() != size_t(this->blockSizes_[blockIndex]), std::logic_error,
402 "Ifpack2::SparseContainer::weightedApply: "
403 "D_local has length " << X_local.getLocalLength () <<
", which does "
404 "not match numRows = " << this->blockSizes_[blockIndex] <<
". Please report this bug to "
405 "the Ifpack2 developers.");
406 mvgs.gatherMVtoView(D_local, D, blockRows);
407 inverse_mv_type X_scaled(Inverses_[blockIndex]->getDomainMap(), numVecs);
408 X_scaled.elementWiseMultiply(STS::one(), D_local, X_local, STS::zero());
415 inverse_mv_type* Y_temp;
416 if (InverseScalar(beta) == STS::zero ()) {
419 Y_temp =
new inverse_mv_type(Inverses_[blockIndex]->getRangeMap(), numVecs);
422 Inverses_[blockIndex]->apply(X_scaled, *Y_temp, mode);
428 Y_local.elementWiseMultiply(alpha, D_local, *Y_temp, beta);
429 if(Y_temp != &Y_local)
433 mvgs.scatterMVtoView(Y, Y_local, blockRows);
437 template<
class MatrixType,
class InverseType>
447 template<
class MatrixType,
class InverseType>
450 std::ostringstream oss;
451 oss <<
"\"Ifpack2::SparseContainer\": {";
452 if (this->isInitialized()) {
453 if (this->isComputed()) {
454 oss <<
"status = initialized, computed";
457 oss <<
"status = initialized, not computed";
461 oss <<
"status = not initialized, not computed";
463 for(
int i = 0; i < this->numBlocks_; i++)
465 oss <<
", Block Inverse " << i <<
": {";
466 oss << Inverses_[i]->description();
474 template<
class MatrixType,
class InverseType>
479 os <<
"================================================================================" << endl;
480 os <<
"Ifpack2::SparseContainer" << endl;
481 for(
int i = 0; i < this->numBlocks_; i++)
483 os <<
"Block " << i <<
" rows: = " << this->blockSizes_[i] << endl;
485 os <<
"isInitialized() = " << this->IsInitialized_ << endl;
486 os <<
"isComputed() = " << this->IsComputed_ << endl;
487 os <<
"================================================================================" << endl;
492 template<
class MatrixType,
class InverseType>
508 if(this->scalarsPerRow_ > 1)
510 Array<LO> colToBlockOffset(this->inputBlockMatrix_->getNodeNumCols(), INVALID);
511 for(
int i = 0; i < this->numBlocks_; i++)
514 LO blockStart = this->blockOffsets_[i];
515 LO blockSize = this->blockSizes_[i];
516 LO blockPointSize = this->blockSizes_[i] * this->scalarsPerRow_;
517 LO blockEnd = blockStart + blockSize;
518 ArrayView<const LO> blockRows = this->getBlockRows(i);
522 for(LO j = 0; j < blockSize; j++)
524 LO localCol = this->translateRowToCol(blockRows[j]);
525 colToBlockOffset[localCol] = blockStart + j;
529 Array<size_t> rowEntryCounts(blockPointSize, 0);
532 for(LO blockRow = 0; blockRow < blockSize; blockRow++)
538 LO inputRow = this->blockRows_[blockStart + blockRow];
539 this->inputBlockMatrix_->getLocalRowView(inputRow, indices, values, numEntries);
540 for(LO br = 0; br < this->bcrsBlockSize_; br++)
542 for(LO k = 0; k < numEntries; k++)
544 LO colOffset = colToBlockOffset[indices[k]];
545 if(blockStart <= colOffset && colOffset < blockEnd)
547 rowEntryCounts[blockRow * this->bcrsBlockSize_ + br] += this->bcrsBlockSize_;
553 RCP<InverseMap> tempMap(
new InverseMap(blockPointSize, 0, this->localComm_));
554 diagBlocks_[i] =
rcp(
new InverseCrs(tempMap, rowEntryCounts, Tpetra::StaticProfile));
555 Inverses_[i] =
rcp(
new InverseType(diagBlocks_[i]));
557 for(LO blockRow = 0; blockRow < blockSize; blockRow++)
563 LO inputRow = this->blockRows_[blockStart + blockRow];
564 this->inputBlockMatrix_->getLocalRowView(inputRow, indices, values, numEntries);
565 for(LO br = 0; br < this->bcrsBlockSize_; br++)
567 indicesToInsert.
clear();
568 valuesToInsert.
clear();
569 for(LO k = 0; k < numEntries; k++)
571 LO colOffset = colToBlockOffset[indices[k]];
572 if(blockStart <= colOffset && colOffset < blockEnd)
574 LO blockCol = colOffset - blockStart;
576 for(LO bc = 0; bc < this->bcrsBlockSize_; bc++)
578 indicesToInsert.
push_back(blockCol * this->bcrsBlockSize_ + bc);
579 valuesToInsert.
push_back(values[k * this->bcrsBlockSize_ * this->bcrsBlockSize_ + bc * this->bcrsBlockSize_ + br]);
583 InverseGlobalOrdinal rowToInsert = blockRow * this->bcrsBlockSize_ + br;
584 if(indicesToInsert.
size())
585 diagBlocks_[i]->insertGlobalValues(rowToInsert, indicesToInsert(), valuesToInsert());
588 diagBlocks_[i]->fillComplete();
595 Array<LO> colToBlockOffset(this->inputMatrix_->getNodeNumCols() * this->bcrsBlockSize_, INVALID);
596 for(
int i = 0; i < this->numBlocks_; i++)
599 LO blockStart = this->blockOffsets_[i];
600 LO blockSize = this->blockSizes_[i];
601 LO blockEnd = blockStart + blockSize;
602 ArrayView<const LO> blockRows = this->getBlockRows(i);
606 for(LO j = 0; j < blockSize; j++)
609 LO localCol = this->translateRowToCol(blockRows[j]);
610 colToBlockOffset[localCol] = blockStart + j;
613 for(LO j = 0; j < blockSize; j++)
615 rowEntryCounts[j] = this->getInputRowView(this->blockRows_[blockStart + j]).size();
617 RCP<InverseMap> tempMap(
new InverseMap(blockSize, 0, this->localComm_));
618 diagBlocks_[i] =
rcp(
new InverseCrs(tempMap, rowEntryCounts, Tpetra::StaticProfile));
619 Inverses_[i] =
rcp(
new InverseType(diagBlocks_[i]));
620 for(LO blockRow = 0; blockRow < blockSize; blockRow++)
622 valuesToInsert.
clear();
623 indicesToInsert.
clear();
625 LO inputSplitRow = this->blockRows_[blockStart + blockRow];
626 auto rowView = this->getInputRowView(inputSplitRow);
627 for(
size_t k = 0; k < rowView.size(); k++)
629 LO colOffset = colToBlockOffset[rowView.ind(k)];
630 if(blockStart <= colOffset && colOffset < blockEnd)
632 LO blockCol = colOffset - blockStart;
634 valuesToInsert.
push_back(rowView.val(k));
637 if(indicesToInsert.
size())
638 diagBlocks_[i]->insertGlobalValues(blockRow, indicesToInsert(), valuesToInsert());
640 diagBlocks_[i]->fillComplete ();
645 template<
typename MatrixType,
typename InverseType>
649 #ifdef HAVE_IFPACK2_AMESOS2
651 if(std::is_same<InverseType, ILUTInverse>::value)
655 else if(std::is_same<InverseType, AmesosInverse>::value)
657 return "SparseAmesos";
661 throw std::logic_error(
"InverseType for SparseContainer must be Ifpack2::ILUT or Details::Amesos2Wrapper");
666 constexpr
bool inverseTypeIsILUT = std::is_same<InverseType, ILUTInverse>::value;
668 "InverseType for SparseContainer must be Ifpack2::ILUT<ROW>");
676 #include "Ifpack2_ILUT.hpp"
677 #ifdef HAVE_IFPACK2_AMESOS2
678 #include "Ifpack2_Details_Amesos2Wrapper.hpp"
685 #ifdef HAVE_IFPACK2_AMESOS2
686 # define IFPACK2_SPARSECONTAINER_INSTANT(S,LO,GO,N) \
687 template class Ifpack2::SparseContainer< Tpetra::RowMatrix<S, LO, GO, N>, \
688 Ifpack2::ILUT<Tpetra::RowMatrix<S,LO,GO,N> > >; \
689 template class Ifpack2::SparseContainer< Tpetra::RowMatrix<S, LO, GO, N>, \
690 Ifpack2::Details::Amesos2Wrapper<Tpetra::RowMatrix<S,LO,GO,N> > >;
692 # define IFPACK2_SPARSECONTAINER_INSTANT(S,LO,GO,N) \
693 template class Ifpack2::SparseContainer< Tpetra::RowMatrix<S,LO,GO,N>, \
694 Ifpack2::ILUT<Tpetra::RowMatrix<S, LO, GO, N> > >;
696 #endif // IFPACK2_SPARSECONTAINER_DEF_HPP
static std::string getName()
Get the name of this container type for Details::constructContainer()
Definition: Ifpack2_SparseContainer_def.hpp:646
SparseContainer(const Teuchos::RCP< const row_matrix_type > &matrix, const Teuchos::Array< Teuchos::Array< LO > > &partitions, const Teuchos::RCP< const import_type > &importer, bool pointIndexed)
Constructor.
Definition: Ifpack2_SparseContainer_def.hpp:60
Store and solve a local sparse linear problem.
Definition: Ifpack2_SparseContainer_decl.hpp:134
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to the given FancyOStream.
Definition: Ifpack2_SparseContainer_def.hpp:475
The implementation of the numerical features of Container (Jacobi, Gauss-Seidel, SGS). This class allows a custom scalar type (LocalScalarType) to be used for storing blocks and solving the block systems. Hiding this template parameter from the Container interface simplifies the BlockRelaxation and ContainerFactory classes.
Definition: Ifpack2_Container_decl.hpp:342
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void initialize()
Do all set-up operations that only require matrix structure.
Definition: Ifpack2_SparseContainer_def.hpp:86
ILUT (incomplete LU factorization with threshold) of a Tpetra sparse matrix.
Definition: Ifpack2_ILUT_decl.hpp:91
virtual std::ostream & print(std::ostream &os) const
Print information about this object to the given output stream.
Definition: Ifpack2_SparseContainer_def.hpp:438
virtual std::string description() const
A one-line description of this object.
Definition: Ifpack2_SparseContainer_def.hpp:448
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Wrapper class for direct solvers in Amesos2.
Definition: Ifpack2_Details_Amesos2Wrapper_decl.hpp:102
virtual void weightedApply(HostView X, HostView Y, HostView W, int blockIndex, Teuchos::ETransp mode=Teuchos::NO_TRANS, SC alpha=Teuchos::ScalarTraits< SC >::one(), SC beta=Teuchos::ScalarTraits< SC >::zero()) const
Compute Y := alpha * diag(D) * M^{-1} (diag(D) * X) + beta*Y.
Definition: Ifpack2_SparseContainer_def.hpp:288
virtual void apply(HostView X, HostView Y, int blockIndex, Teuchos::ETransp mode=Teuchos::NO_TRANS, SC alpha=Teuchos::ScalarTraits< SC >::one(), SC beta=Teuchos::ScalarTraits< SC >::zero()) const
Compute Y := alpha * M^{-1} X + beta*Y.
Definition: Ifpack2_SparseContainer_def.hpp:168
typename mv_type::dual_view_type::t_host HostView
Definition: Ifpack2_Container_decl.hpp:139
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
void push_back(const value_type &x)
virtual ~SparseContainer()
Destructor (declared virtual for memory safety of derived classes).
Definition: Ifpack2_SparseContainer_def.hpp:75
TypeTo as(const TypeFrom &t)
virtual void setParameters(const Teuchos::ParameterList &List)
Set all necessary parameters.
Definition: Ifpack2_SparseContainer_def.hpp:79
virtual void compute()
Initialize and compute all blocks.
Definition: Ifpack2_SparseContainer_def.hpp:105
Ifpack2::SparseContainer class declaration.
void clearBlocks()
Definition: Ifpack2_SparseContainer_def.hpp:130
Implementation detail of Ifpack2::Container subclasses.
Definition: Ifpack2_Details_MultiVectorLocalGatherScatter.hpp:85