10 #ifndef IFPACK2_DENSECONTAINER_DEF_HPP
11 #define IFPACK2_DENSECONTAINER_DEF_HPP
13 #include "Tpetra_CrsMatrix.hpp"
15 #include "Tpetra_BlockMultiVector.hpp"
21 #include "Teuchos_DefaultSerialComm.hpp"
26 template <
class MatrixType,
class LocalScalarType>
32 : ContainerImpl<MatrixType, LocalScalarType>(matrix, partitions, pointIndexed)
33 , scalarOffsets_(this->numBlocks_) {
35 !matrix->hasColMap(), std::invalid_argument,
36 "Ifpack2::DenseContainer: "
37 "The constructor's input matrix must have a column Map.");
42 scalarOffsets_[i] = totalScalars;
46 scalars_.
resize(totalScalars);
50 diagBlocks_.emplace_back(
Teuchos::View, scalars_.
data() + scalarOffsets_[i], denseRows, denseRows, denseRows);
56 template <
class MatrixType,
class LocalScalarType>
60 template <
class MatrixType,
class LocalScalarType>
64 for (
int i = 0; i < this->numBlocks_; i++)
66 std::fill(ipiv_.begin(), ipiv_.end(), 0);
68 this->IsInitialized_ =
true;
71 this->IsComputed_ =
false;
74 template <
class MatrixType,
class LocalScalarType>
83 this->IsComputed_ =
false;
84 if (!this->isInitialized()) {
90 this->IsComputed_ =
true;
93 template <
class MatrixType,
class LocalScalarType>
98 SC zero = STS::zero();
106 if (this->scalarsPerRow_ > 1) {
107 Array<LO> colToBlockOffset(this->inputBlockMatrix_->getLocalNumCols(), INVALID);
108 for (
int i = 0; i < this->numBlocks_; i++) {
110 LO blockStart = this->blockOffsets_[i];
111 LO blockEnd = blockStart + this->blockSizes_[i];
112 ArrayView<const LO> blockRows = this->getBlockRows(i);
116 for (
size_t j = 0; j < size_t(blockRows.size()); j++) {
117 LO localCol = this->translateRowToCol(blockRows[j]);
118 colToBlockOffset[localCol] = blockStart + j;
120 using h_inds_type =
typename block_crs_matrix_type::local_inds_host_view_type;
121 using h_vals_type =
typename block_crs_matrix_type::values_host_view_type;
122 for (LO blockRow = 0; blockRow < LO(blockRows.size()); blockRow++) {
126 LO inputRow = this->blockRows_[blockStart + blockRow];
127 this->inputBlockMatrix_->getLocalRowView(inputRow, indices, values);
128 LO numEntries = (LO)indices.size();
129 for (LO k = 0; k < numEntries; k++) {
130 LO colOffset = colToBlockOffset[indices[k]];
131 if (blockStart <= colOffset && colOffset < blockEnd) {
135 LO blockCol = colOffset - blockStart;
136 for (LO bc = 0; bc < this->bcrsBlockSize_; bc++) {
137 for (LO br = 0; br < this->bcrsBlockSize_; br++) {
138 LO r = this->bcrsBlockSize_ * blockRow + br;
139 LO c = this->bcrsBlockSize_ * blockCol + bc;
140 auto val = values[k * (this->bcrsBlockSize_ * this->bcrsBlockSize_) + (br + this->bcrsBlockSize_ * bc)];
142 diagBlocks_[i](r, c) = val;
152 Array<LO> colToBlockOffset(this->inputMatrix_->getLocalNumCols() * this->bcrsBlockSize_, INVALID);
153 for (
int i = 0; i < this->numBlocks_; i++) {
155 LO blockStart = this->blockOffsets_[i];
156 LO blockEnd = blockStart + this->blockSizes_[i];
157 ArrayView<const LO> blockRows = this->getBlockRows(i);
161 for (
size_t j = 0; j < size_t(blockRows.size()); j++) {
163 LO localCol = this->translateRowToCol(blockRows[j]);
164 colToBlockOffset[localCol] = blockStart + j;
166 for (
size_t blockRow = 0; blockRow < size_t(blockRows.size()); blockRow++) {
168 LO inputPointRow = this->blockRows_[blockStart + blockRow];
169 auto rowView = this->getInputRowView(inputPointRow);
170 for (
size_t k = 0; k < rowView.size(); k++) {
171 LO colOffset = colToBlockOffset[rowView.ind(k)];
172 if (blockStart <= colOffset && colOffset < blockEnd) {
173 LO blockCol = colOffset - blockStart;
174 auto val = rowView.val(k);
176 diagBlocks_[i](blockRow, blockCol) = rowView.val(k);
184 template <
class MatrixType,
class LocalScalarType>
185 void DenseContainer<MatrixType, LocalScalarType>::
188 for (
int i = 0; i < this->numBlocks_; i++) {
190 int* blockIpiv = &ipiv_[this->blockOffsets_[i] * this->scalarsPerRow_];
191 lapack.
GETRF(diagBlocks_[i].numRows(),
192 diagBlocks_[i].numCols(),
193 diagBlocks_[i].values(),
194 diagBlocks_[i].stride(),
198 INFO < 0, std::logic_error,
199 "Ifpack2::DenseContainer::factor: "
200 "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
201 "incorrectly. INFO = "
203 "Please report this bug to the Ifpack2 developers.");
208 INFO > 0, std::runtime_error,
209 "Ifpack2::DenseContainer::factor: "
210 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
211 "computed U factor is exactly singular. U("
212 << INFO <<
"," << INFO <<
") "
213 "(one-based index i) is exactly zero. This probably means that the input "
214 "matrix has a singular diagonal block.");
218 template <
class MatrixType,
class LocalScalarType>
219 void DenseContainer<MatrixType, LocalScalarType>::
220 solveBlock(ConstHostSubviewLocal X,
226 #ifdef HAVE_IFPACK2_DEBUG
228 X.extent(0) != Y.extent(0),
230 "Ifpack2::DenseContainer::solveBlock: X and Y have "
231 "incompatible dimensions ("
232 << X.extent(0) <<
" resp. "
233 << Y.extent(0) <<
"). Please report this bug to "
234 "the Ifpack2 developers.");
237 X.extent(1) != Y.extent(1),
239 "Ifpack2::DenseContainer::solveBlock: X and Y have "
240 "incompatible numbers of vectors ("
241 << X.extent(1) <<
" resp. "
242 << Y.extent(1) <<
"). Please report this bug to "
243 "the Ifpack2 developers.");
247 size_t numRows = X.extent(0);
248 size_t numVecs = X.extent(1);
249 if (alpha == STS::zero()) {
250 if (beta == STS::zero()) {
254 for (
size_t j = 0; j < numVecs; j++) {
255 for (
size_t i = 0; i < numRows; i++)
256 Y(i, j) = STS::zero();
259 for (
size_t j = 0; j < numVecs; j++) {
260 for (
size_t i = 0; i < numRows; i++)
261 Y(i, j) = beta * Y(i, j);
268 std::vector<LSC> yTemp(numVecs * numRows);
269 for (
size_t j = 0; j < numVecs; j++) {
270 for (
size_t i = 0; i < numRows; i++)
271 yTemp[j * numRows + i] = X(i, j);
275 int* blockIpiv = &ipiv_[this->blockOffsets_[blockIndex] * this->scalarsPerRow_];
279 diagBlocks_[blockIndex].numRows(),
281 diagBlocks_[blockIndex].values(),
282 diagBlocks_[blockIndex].stride(),
288 if (beta != STS::zero()) {
289 for (
size_t j = 0; j < numVecs; j++) {
290 for (
size_t i = 0; i < numRows; i++) {
291 Y(i, j) *= ISC(beta);
292 Y(i, j) += ISC(alpha * yTemp[j * numRows + i]);
296 for (
size_t j = 0; j < numVecs; j++) {
297 for (
size_t i = 0; i < numRows; i++)
298 Y(i, j) = ISC(yTemp[j * numRows + i]);
303 INFO != 0, std::runtime_error,
304 "Ifpack2::DenseContainer::solveBlock: "
305 "LAPACK's _GETRS (solve using LU factorization with partial pivoting) "
306 "failed with INFO = "
307 << INFO <<
" != 0.");
311 template <
class MatrixType,
class LocalScalarType>
321 template <
class MatrixType,
class LocalScalarType>
325 std::ostringstream oss;
326 oss <<
"Ifpack::DenseContainer: ";
327 if (this->isInitialized()) {
328 if (this->isComputed()) {
329 oss <<
"{status = initialized, computed";
331 oss <<
"{status = initialized, not computed";
334 oss <<
"{status = not initialized, not computed";
341 template <
class MatrixType,
class LocalScalarType>
347 os <<
"================================================================================" << endl;
348 os <<
"Ifpack2::DenseContainer" << endl;
349 for (
int i = 0; i < this->numBlocks_; i++) {
350 os <<
"Block " << i <<
" number of rows = " << this->blockSizes_[i] << endl;
352 os <<
"isInitialized() = " << this->IsInitialized_ << endl;
353 os <<
"isComputed() = " << this->IsComputed_ << endl;
354 os <<
"================================================================================" << endl;
358 template <
class MatrixType,
class LocalScalarType>
365 template <
class MatrixType,
class LocalScalarType>
376 #define IFPACK2_DENSECONTAINER_INSTANT(S, LO, GO, N) \
377 template class Ifpack2::DenseContainer<Tpetra::RowMatrix<S, LO, GO, N>, S>;
379 #endif // IFPACK2_DENSECONTAINER_DEF_HPP
Teuchos::Array< LO > blockRows_
Local indices of the rows of the input matrix that belong to this block.
Definition: Ifpack2_Container_decl.hpp:259
Teuchos::Array< LO > blockSizes_
Number of rows in each block.
Definition: Ifpack2_Container_decl.hpp:261
int numBlocks_
The number of blocks (partitions) in the container.
Definition: Ifpack2_Container_decl.hpp:257
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:307
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void compute()
Extract the local diagonal block and prepare the solver.
Definition: Ifpack2_DenseContainer_def.hpp:76
LO scalarsPerRow_
Definition: Ifpack2_Container_decl.hpp:282
static std::string getName()
Get the name of this container type for Details::constructContainer()
Definition: Ifpack2_DenseContainer_def.hpp:366
void GETRF(const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, OrdinalType *IPIV, OrdinalType *info) const
Store and solve a local dense linear problem.
Definition: Ifpack2_DenseContainer_decl.hpp:70
DenseContainer(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.
virtual std::ostream & print(std::ostream &os) const
Print information about this object to the given output stream.
Definition: Ifpack2_DenseContainer_def.hpp:314
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_DenseContainer_def.hpp:343
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
void resize(size_type new_size, const value_type &x=value_type())
virtual ~DenseContainer()
Destructor (declared virtual for memory safety of derived classes).
Definition: Ifpack2_DenseContainer_def.hpp:58
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
virtual std::string description() const
A one-line description of this object.
Definition: Ifpack2_DenseContainer_def.hpp:324
virtual void initialize()
Do all set-up operations that only require matrix structure.
Definition: Ifpack2_DenseContainer_def.hpp:62