10 #ifndef IFPACK2_DATABASESCHWARZ_DEF_HPP
11 #define IFPACK2_DATABASESCHWARZ_DEF_HPP
13 #include "Ifpack2_Parameters.hpp"
15 #include "Tpetra_CrsMatrix.hpp"
16 #include "Teuchos_FancyOStream.hpp"
17 #include "Teuchos_oblackholestream.hpp"
25 template <
class MatrixType>
29 , IsInitialized_(false)
34 , InitializeTime_(0.0)
40 , PatchTolerance_(1e-3)
41 , SkipDatabase_(false)
43 this->setObjectLabel(
"Ifpack2::DatabaseSchwarz");
46 template <
class MatrixType>
51 , IsInitialized_(false)
56 , InitializeTime_(0.0)
62 , PatchTolerance_(1e-3)
63 , SkipDatabase_(false)
65 this->setObjectLabel(
"Ifpack2::DatabaseSchwarz");
69 template <
class MatrixType>
73 template <
class MatrixType>
77 IsInitialized_ =
false;
83 template <
class MatrixType>
86 this->setParametersImpl(const_cast<Teuchos::ParameterList&>(params));
89 template <
class MatrixType>
93 const int defaultPatchSize = 9;
94 const double defaultPatchTolerance = 1e-3;
95 const bool defaultSkipDatabase =
false;
96 const bool defaultVerbose =
false;
99 PatchSize_ = params.
get<
int>(
"database schwarz: patch size", defaultPatchSize);
102 PatchSize_ < 0, std::invalid_argument,
103 "Ifpack2::DatabaseSchwarz::setParameters: \"database schwarz: patch size\" parameter "
104 "must be a nonnegative integer. You gave a value of "
105 << PatchSize_ <<
".");
108 PatchTolerance_ = params.
get(
"database schwarz: patch tolerance", defaultPatchTolerance);
111 PatchTolerance_ <= 0, std::invalid_argument,
112 "Ifpack2::DatabaseSchwarz::setParameters: \"database schwarz: patch tolerance\" parameter "
113 "must be a positive double. You gave a value of "
114 << PatchTolerance_ <<
".");
117 SkipDatabase_ = params.
get<
bool>(
"database schwarz: skip database", defaultSkipDatabase);
120 Verbose_ = params.
get<
bool>(
"database schwarz: print database summary", defaultVerbose);
123 template <
class MatrixType>
125 (void)zeroStartingSolution;
128 template <
class MatrixType>
133 A.
is_null(), std::runtime_error,
134 "Ifpack2::DatabaseSchwarz::getComm: The input "
135 "matrix A is null. Please call setMatrix() with a nonnull input matrix "
136 "before calling this method.");
137 return A->getRowMap()->getComm();
140 template <
class MatrixType>
146 template <
class MatrixType>
147 Teuchos::RCP<
const Tpetra::CrsMatrix<
typename MatrixType::scalar_type,
148 typename MatrixType::local_ordinal_type,
149 typename MatrixType::global_ordinal_type,
150 typename MatrixType::node_type> >
156 return Teuchos::rcp_dynamic_cast<
const crs_matrix_type>(getMatrix());
159 template <
class MatrixType>
165 A.
is_null(), std::runtime_error,
166 "Ifpack2::DatabaseSchwarz::getDomainMap: The "
167 "input matrix A is null. Please call setMatrix() with a nonnull input "
168 "matrix before calling this method.");
169 return A->getDomainMap();
172 template <
class MatrixType>
178 A.
is_null(), std::runtime_error,
179 "Ifpack2::DatabaseSchwarz::getRangeMap: The "
180 "input matrix A is null. Please call setMatrix() with a nonnull input "
181 "matrix before calling this method.");
182 return A->getRangeMap();
185 template <
class MatrixType>
190 template <
class MatrixType>
192 return NumInitialize_;
195 template <
class MatrixType>
200 template <
class MatrixType>
205 template <
class MatrixType>
207 return InitializeTime_;
210 template <
class MatrixType>
215 template <
class MatrixType>
220 template <
class MatrixType>
222 return ComputeFlops_;
225 template <
class MatrixType>
230 template <
class MatrixType>
234 A.
is_null(), std::runtime_error,
235 "Ifpack2::DatabaseSchwarz::getNodeSmootherComplexity: "
236 "The input matrix A is null. Please call setMatrix() with a nonnull "
237 "input matrix, then call compute(), before calling this method.");
239 return A->getLocalNumRows() + A->getLocalNumEntries();
242 template <
class MatrixType>
244 apply(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
245 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
249 const std::string timerName(
"Ifpack2::DatabaseSchwarz::apply");
255 double startTime = timer->
wallTime();
264 !isComputed(), std::runtime_error,
265 "Ifpack2::DatabaseSchwarz::apply(): You must call the compute() method before "
266 "you may call apply().");
268 X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
269 "Ifpack2::DatabaseSchwarz::apply(): X and Y must have the same number of "
270 "columns. X.getNumVectors() = "
271 << X.getNumVectors() <<
" != "
272 <<
"Y.getNumVectors() = " << Y.getNumVectors() <<
".");
278 auto X_view = X.getLocalViewHost(Tpetra::Access::ReadOnly);
279 auto Y_view = Y.getLocalViewHost(Tpetra::Access::ReadWrite);
283 for (
unsigned int ipatch = 0; ipatch < NumPatches_; ipatch++) {
284 int idatabase = DatabaseIndices_[ipatch];
288 for (
unsigned int c = 0; c < X_view.extent(1); ++c) {
289 for (
unsigned int i = 0; i < x_patch.
size(); ++i) {
290 x_patch[i] = X_view(PatchIndices_[ipatch][i], c);
299 int* ipiv = &ipiv_[idatabase * PatchSize_];
301 lapack.
GETRS(
'N', DatabaseMatrices_[idatabase]->numRows(), numRhs,
302 DatabaseMatrices_[idatabase]->values(), DatabaseMatrices_[idatabase]->numRows(),
304 DatabaseMatrices_[idatabase]->numRows(), &INFO);
308 INFO < 0, std::logic_error,
309 "Ifpack2::DatabaseSchwarz::compute: "
310 "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
311 "incorrectly. INFO = "
313 "Please report this bug to the Ifpack2 developers.");
318 INFO > 0, std::runtime_error,
319 "Ifpack2::DatabaseSchwarz::compute: "
320 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
321 "computed U factor is exactly singular. U("
322 << INFO <<
"," << INFO <<
") "
323 "(one-based index i) is exactly zero. This probably means that the input "
324 "patch is singular.");
327 for (
unsigned int c = 0; c < Y_view.extent(1); ++c) {
328 for (
unsigned int i = 0; i < x_patch.
size(); ++i) {
329 Y_view(PatchIndices_[ipatch][i], c) += alpha * Weights_[PatchIndices_[ipatch][i]] * x_patch[i];
335 ApplyTime_ += (timer->
wallTime() - startTime);
338 template <
class MatrixType>
340 applyMat(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
341 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
344 X.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
345 "Ifpack2::DatabaseSchwarz::applyMat: X.getNumVectors() != Y.getNumVectors().");
349 A.is_null(), std::runtime_error,
350 "Ifpack2::DatabaseSchwarz::applyMat: The input "
351 "matrix A is null. Please call setMatrix() with a nonnull input matrix "
352 "before calling this method.");
354 A->apply(X, Y, mode);
357 template <
class MatrixType>
362 const std::string timerName(
"Ifpack2::DatabaseSchwarz::initialize");
367 IsInitialized_ =
true;
371 template <
class MatrixType>
373 const std::string timerName(
"Ifpack2::DatabaseSchwarz::compute");
379 double startTime = timer->
wallTime();
384 if (!isInitialized()) {
388 const int maxNnzPerRow = A_->getGlobalMaxNumRowEntries();
391 PatchIndices_.resize(0);
395 size_t num_entries = A_->getNumEntriesInLocalRow(irow);
400 typename row_matrix_type::nonconst_local_inds_host_view_type row_inds(
"row indices", maxNnzPerRow);
401 typename row_matrix_type::nonconst_values_host_view_type row_vals(
"row values", maxNnzPerRow);
402 A_->getLocalRowCopy(irow, row_inds, row_vals, num_entries);
405 bool is_new_patch =
true;
406 for (
size_t ipatch = 0; ipatch < PatchIndices_.size(); ++ipatch) {
407 for (
size_t i = 0; i < PatchIndices_[ipatch].size(); ++i) {
408 if (PatchIndices_[ipatch][i] == irow) {
409 is_new_patch =
false;
410 ipatch = PatchIndices_.size();
419 std::vector<typename row_matrix_type::local_ordinal_type> indices_vector = Teuchos::createVector(indices_array_view);
420 PatchIndices_.push_back(indices_vector);
429 DatabaseIndices_.resize(NumPatches_, -1);
430 Weights_.resize(A_->getLocalNumRows(), 0);
431 std::vector<double> index_count(A_->getLocalNumRows(), 0);
433 for (
unsigned int ipatch = 0; ipatch < NumPatches_; ++ipatch) {
435 DenseMatRCP patch_matrix =
Teuchos::rcp(
new DenseMatType(PatchSize_, PatchSize_));
436 auto indices_vector = PatchIndices_[ipatch];
439 index_count[indices_vector[i]]++;
441 typename row_matrix_type::nonconst_local_inds_host_view_type row_inds(
"row indices", maxNnzPerRow);
442 typename row_matrix_type::nonconst_values_host_view_type row_vals(
"row values", maxNnzPerRow);
444 A_->getLocalRowCopy(indices_vector[i], row_inds, row_vals, num_entries);
446 for (
size_t k = 0; k < num_entries; ++k) {
447 if (row_inds(k) == indices_vector[j]) {
448 (*patch_matrix)(i, j) = row_vals(k);
456 bool found_match =
false;
457 if (!SkipDatabase_) {
458 for (
size_t idatabase = 0; idatabase < DatabaseMatrices_.size(); ++idatabase) {
463 DenseMatRCP database_candidate = DatabaseMatrices_[idatabase];
473 DatabaseIndices_[ipatch] = idatabase;
482 DatabaseMatrices_.push_back(patch_matrix);
483 DatabaseIndices_[ipatch] = DatabaseMatrices_.size() - 1;
485 "Ifpack2::DatabaseSchwarz::compute: A matrix was added to the database, but appears to be null!"
486 "Please report this bug to the Ifpack2 developers.");
491 for (
unsigned int i = 0; i < index_count.size(); ++i) {
493 "Ifpack2::DatabaseSchwarz::compute: DOF " << i <<
" has no corresponding patch! "
494 "All DOFs must be able to locate in a patch to use this method! "
495 "Have you considered adjusting the patch size? Currently it is "
496 << PatchSize_ <<
".");
497 Weights_[i] = 1. / index_count[i];
499 DatabaseSize_ = DatabaseMatrices_.size();
502 std::vector<int> database_counts(DatabaseSize_, 0);
503 for (
unsigned int ipatch = 0; ipatch < NumPatches_; ++ipatch) {
504 database_counts[DatabaseIndices_[ipatch]]++;
510 ipiv_.resize(DatabaseSize_ * PatchSize_);
511 std::fill(ipiv_.begin(), ipiv_.end(), 0);
512 for (
unsigned int idatabase = 0; idatabase < DatabaseSize_; idatabase++) {
513 int* ipiv = &ipiv_[idatabase * PatchSize_];
515 lapack.
GETRF(DatabaseMatrices_[idatabase]->numRows(),
516 DatabaseMatrices_[idatabase]->numCols(),
517 DatabaseMatrices_[idatabase]->values(),
518 DatabaseMatrices_[idatabase]->stride(),
523 INFO < 0, std::logic_error,
524 "Ifpack2::DatabaseSchwarz::compute: "
525 "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
526 "incorrectly. INFO = "
528 "Please report this bug to the Ifpack2 developers.");
533 std::cout <<
"SINGULAR LOCAL MATRIX, COUNT=" << database_counts[idatabase] << std::endl;
536 INFO > 0, std::runtime_error,
537 "Ifpack2::DatabaseSchwarz::compute: "
538 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
539 "computed U factor is exactly singular. U("
540 << INFO <<
"," << INFO <<
") "
541 "(one-based index i) is exactly zero. This probably means that the input "
542 "patch is singular.");
548 ComputeTime_ += (timer->
wallTime() - startTime);
552 std::cout <<
"Ifpack2::DatabaseSchwarz()::Compute() summary\n";
553 std::cout <<
"Found " << NumPatches_ <<
" patches of size " << PatchSize_ <<
" in matrix A\n";
554 std::cout <<
"Database tol = " << PatchTolerance_ <<
"\n";
555 std::cout <<
"Database size = " << DatabaseSize_ <<
" patches\n";
559 template <
class MatrixType>
561 std::ostringstream out;
566 out <<
"\"Ifpack2::DatabaseSchwarz\": {";
567 out <<
"Initialized: " << (isInitialized() ?
"true" :
"false")
568 <<
", Computed: " << (isComputed() ?
"true" :
"false")
569 <<
", patch size: " << PatchSize_
570 <<
", patch tolerance: " << PatchTolerance_
571 <<
", skip database: " << (SkipDatabase_ ?
"true" :
"false")
572 <<
", print database summary: " << (Verbose_ ?
"true" :
"false");
574 if (getMatrix().is_null()) {
575 out <<
"Matrix: null";
577 out <<
"Global matrix dimensions: ["
578 << getMatrix()->getGlobalNumRows() <<
", "
579 << getMatrix()->getGlobalNumCols() <<
"]"
580 <<
", Global nnz: " << getMatrix()->getGlobalNumEntries();
587 template <
class MatrixType>
609 const int myRank = this->getComm()->getRank();
613 out <<
"\"Ifpack2::DatabaseSchwarz\":" << endl;
618 out <<
"Template parameters:" << endl;
621 out <<
"Scalar: " << TypeNameTraits<scalar_type>::name() << endl
622 <<
"LocalOrdinal: " << TypeNameTraits<local_ordinal_type>::name() << endl
623 <<
"GlobalOrdinal: " << TypeNameTraits<global_ordinal_type>::name() << endl
624 <<
"Device: " << TypeNameTraits<device_type>::name() << endl;
626 out <<
"Initialized: " << (isInitialized() ?
"true" :
"false") << endl
627 <<
"Computed: " << (isComputed() ?
"true" :
"false") << endl;
629 if (getMatrix().is_null()) {
630 out <<
"Matrix: null" << endl;
632 out <<
"Global matrix dimensions: ["
633 << getMatrix()->getGlobalNumRows() <<
", "
634 << getMatrix()->getGlobalNumCols() <<
"]" << endl
635 <<
"Global nnz: " << getMatrix()->getGlobalNumEntries() << endl;
642 #define IFPACK2_DATABASESCHWARZ_INSTANT(S, LO, GO, N) \
643 template class Ifpack2::DatabaseSchwarz<Tpetra::RowMatrix<S, LO, GO, N> >;
645 #endif // IFPACK2_DATABASESCHWARZ_DEF_HPP
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix for which this is a preconditioner.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:142
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_DatabaseSchwarz_decl.hpp:82
void apply(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &X, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, scalar_type alpha=Teuchos::ScalarTraits< scalar_type >::one(), scalar_type beta=Teuchos::ScalarTraits< scalar_type >::zero()) const
Apply the preconditioner to X, returning the result in Y. Y = alpha*Op(A)*X + beta*Y.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:244
Teuchos::RCP< const map_type > getRangeMap() const
The Tpetra::Map representing the range of this operator.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:175
double getApplyTime() const
The total time spent in all calls to apply().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:216
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:231
int getNumApply() const
The total number of successful calls to apply().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:201
void initialize()
Initialize the preconditioner.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:358
bool hasTransposeApply() const
Whether it's possible to apply the transpose of this operator.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:186
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
double getInitializeTime() const
The total time spent in all calls to initialize().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:206
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to a Teuchos::FancyOStream.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:589
void setParameters(const Teuchos::ParameterList ¶ms)
Set (or reset) parameters.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:84
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix is distributed.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:130
Teuchos::RCP< const map_type > getDomainMap() const
The Tpetra::Map representing the domain of this operator.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:162
virtual ~DatabaseSchwarz()
Destructor.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:70
double getComputeTime() const
The total time spent in all calls to compute().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:211
double getApplyFlops() const
The total number of floating-point operations taken by all calls to apply().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:226
void GETRF(const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, OrdinalType *IPIV, OrdinalType *info) const
void compute()
(Re)compute the left scaling, and (if applicable) estimate max and min eigenvalues of D_inv * A...
Definition: Ifpack2_DatabaseSchwarz_def.hpp:372
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
DatabaseSchwarz(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:27
Teuchos::RCP< const Tpetra::CrsMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > > getCrsMatrix() const
Attempt to return the matrix A as a Tpetra::CrsMatrix.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:152
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_DatabaseSchwarz_decl.hpp:91
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:74
void setZeroStartingSolution(bool zeroStartingSolution)
Set this preconditioner's parameters.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:124
double getComputeFlops() const
The total number of floating-point operations taken by all calls to compute().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:221
std::string description() const
A simple one-line description of this object.
Definition: Ifpack2_DatabaseSchwarz_def.hpp:560
int getNumInitialize() const
The total number of successful calls to initialize().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:191
static magnitudeType magnitude(T a)
Overlapping Schwarz where redundant patches are not stored explicitly.
Definition: Ifpack2_DatabaseSchwarz_decl.hpp:63
void applyMat(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &X, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS) const
Compute Y = Op(A)*X, where Op(A) is either A, , or .
Definition: Ifpack2_DatabaseSchwarz_def.hpp:340
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)
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_DatabaseSchwarz_decl.hpp:79
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_DatabaseSchwarz_decl.hpp:85
int getNumCompute() const
The total number of successful calls to compute().
Definition: Ifpack2_DatabaseSchwarz_def.hpp:196