Ifpack2 Templated Preconditioning Package Version 1.0
Loading...
Searching...
No Matches
Ifpack2_DatabaseSchwarz_def.hpp
1/*@HEADER
2// ***********************************************************************
3//
4// Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
5// Copyright (2009) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ***********************************************************************
40//@HEADER
41*/
42
43#ifndef IFPACK2_DATABASESCHWARZ_DEF_HPP
44#define IFPACK2_DATABASESCHWARZ_DEF_HPP
45
46#include "Ifpack2_Parameters.hpp"
47#include "Teuchos_TimeMonitor.hpp"
48#include "Tpetra_CrsMatrix.hpp"
49#include "Teuchos_FancyOStream.hpp"
50#include "Teuchos_oblackholestream.hpp"
51#include "Teuchos_TypeNameTraits.hpp"
52#include "Teuchos_LAPACK.hpp"
53#include <iostream>
54#include <sstream>
55
56
57namespace Ifpack2 {
58
59template<class MatrixType>
61DatabaseSchwarz (const Teuchos::RCP<const row_matrix_type>& A)
62 : A_(A),
63 IsInitialized_(false),
64 IsComputed_(false),
65 NumInitialize_(0),
66 NumCompute_(0),
67 NumApply_(0),
68 InitializeTime_(0.0),
69 ComputeTime_(0.0),
70 ApplyTime_(0.0),
71 ComputeFlops_(0.0),
72 ApplyFlops_(0.0),
73 PatchSize_(9),
74 PatchTolerance_(1e-3),
75 SkipDatabase_(false),
76 Verbose_(false)
77{
78 this->setObjectLabel("Ifpack2::DatabaseSchwarz");
79}
80
81
82template<class MatrixType>
84DatabaseSchwarz (const Teuchos::RCP<const row_matrix_type>& A,
85 Teuchos::ParameterList& params)
86 : A_(A),
87 IsInitialized_(false),
88 IsComputed_(false),
89 NumInitialize_(0),
90 NumCompute_(0),
91 NumApply_(0),
92 InitializeTime_(0.0),
93 ComputeTime_(0.0),
94 ApplyTime_(0.0),
95 ComputeFlops_(0.0),
96 ApplyFlops_(0.0),
97 PatchSize_(9),
98 PatchTolerance_(1e-3),
99 SkipDatabase_(false),
100 Verbose_(false)
101{
102 this->setObjectLabel("Ifpack2::DatabaseSchwarz");
103 this->setParameters(params);
104}
105
106
107template<class MatrixType>
110
111
112template<class MatrixType>
113void DatabaseSchwarz<MatrixType>::setMatrix(const Teuchos::RCP<const row_matrix_type>& A)
114{
115 // ASSERT NON-NULL INPUT
116 if (A.getRawPtr() != A_.getRawPtr()) {
117 IsInitialized_ = false;
118 IsComputed_ = false;
119 A_ = A;
120 }
121}
122
123
124template<class MatrixType>
125void
126DatabaseSchwarz<MatrixType>::setParameters(const Teuchos::ParameterList& params)
127{
128 // GH: Copied from CAG and others. Yes, const_cast bad.
129 this->setParametersImpl(const_cast<Teuchos::ParameterList&>(params));
130}
131
132
133template<class MatrixType>
134void
135DatabaseSchwarz<MatrixType>::setParametersImpl(Teuchos::ParameterList& params)
136{
137 // GH: since patch size varies dramatically, it doesn't make sense to force a default size
138 // but I don't know if it's any better to throw if the user doesn't provide a patch size
139 const int defaultPatchSize = 9;
140 const double defaultPatchTolerance = 1e-3;
141 const bool defaultSkipDatabase = false;
142 const bool defaultVerbose = false;
143
144 // the size of patch to search for
145 PatchSize_ = params.get<int>("database schwarz: patch size",defaultPatchSize);
146
147 TEUCHOS_TEST_FOR_EXCEPTION(
148 PatchSize_ < 0, std::invalid_argument,
149 "Ifpack2::DatabaseSchwarz::setParameters: \"database schwarz: patch size\" parameter "
150 "must be a nonnegative integer. You gave a value of " << PatchSize_ << ".");
151
152 // the tolerance at which two patch matrices are considered "equal"
153 PatchTolerance_ = params.get("database schwarz: patch tolerance", defaultPatchTolerance);
154
155 TEUCHOS_TEST_FOR_EXCEPTION(
156 PatchTolerance_ <= 0, std::invalid_argument,
157 "Ifpack2::DatabaseSchwarz::setParameters: \"database schwarz: patch tolerance\" parameter "
158 "must be a positive double. You gave a value of " << PatchTolerance_ << ".");
159
160 // whether to skip the database computation and invert all patches or not
161 SkipDatabase_ = params.get<bool>("database schwarz: skip database",defaultSkipDatabase);
162
163 // verbosity: controls whether to print a database summary at the end of the compute phase
164 Verbose_ = params.get<bool>("database schwarz: print database summary",defaultVerbose);
165}
166
167
168template<class MatrixType>
169void
171{
172 (void) zeroStartingSolution;
173}
174
175template<class MatrixType>
176Teuchos::RCP<const Teuchos::Comm<int> >
178{
179 Teuchos::RCP<const row_matrix_type> A = getMatrix();
180 TEUCHOS_TEST_FOR_EXCEPTION(
181 A.is_null(), std::runtime_error, "Ifpack2::DatabaseSchwarz::getComm: The input "
182 "matrix A is null. Please call setMatrix() with a nonnull input matrix "
183 "before calling this method.");
184 return A->getRowMap()->getComm();
185}
186
187
188template<class MatrixType>
189Teuchos::RCP<const typename DatabaseSchwarz<MatrixType>::row_matrix_type>
191{
192 return A_;
193}
194
195
196template<class MatrixType>
197Teuchos::RCP<const Tpetra::CrsMatrix<typename MatrixType::scalar_type,
198 typename MatrixType::local_ordinal_type,
199 typename MatrixType::global_ordinal_type,
200 typename MatrixType::node_type> >
202getCrsMatrix() const {
203 typedef Tpetra::CrsMatrix<scalar_type, local_ordinal_type,
204 global_ordinal_type, node_type> crs_matrix_type;
205 return Teuchos::rcp_dynamic_cast<const crs_matrix_type> (getMatrix());
206}
207
208
209template<class MatrixType>
210Teuchos::RCP<const typename DatabaseSchwarz<MatrixType>::map_type>
212getDomainMap() const
213{
214 Teuchos::RCP<const row_matrix_type> A = getMatrix();
215 TEUCHOS_TEST_FOR_EXCEPTION(
216 A.is_null(), std::runtime_error, "Ifpack2::DatabaseSchwarz::getDomainMap: The "
217 "input matrix A is null. Please call setMatrix() with a nonnull input "
218 "matrix before calling this method.");
219 return A->getDomainMap();
220}
221
222
223template<class MatrixType>
224Teuchos::RCP<const typename DatabaseSchwarz<MatrixType>::map_type>
226getRangeMap() const
227{
228 Teuchos::RCP<const row_matrix_type> A = getMatrix();
229 TEUCHOS_TEST_FOR_EXCEPTION(
230 A.is_null(), std::runtime_error, "Ifpack2::DatabaseSchwarz::getRangeMap: The "
231 "input matrix A is null. Please call setMatrix() with a nonnull input "
232 "matrix before calling this method.");
233 return A->getRangeMap();
234}
235
236
237template<class MatrixType>
239 return false;
240}
241
242
243template<class MatrixType>
245 return NumInitialize_;
246}
247
248
249template<class MatrixType>
251 return NumCompute_;
252}
253
254
255template<class MatrixType>
257 return NumApply_;
258}
259
260
261template<class MatrixType>
263 return InitializeTime_;
264}
265
266
267template<class MatrixType>
269 return ComputeTime_;
270}
271
272
273template<class MatrixType>
275 return ApplyTime_;
276}
277
278
279template<class MatrixType>
281 return ComputeFlops_;
282}
283
284
285template<class MatrixType>
287 return ApplyFlops_;
288}
289
290template<class MatrixType>
292 Teuchos::RCP<const row_matrix_type> A = getMatrix();
293 TEUCHOS_TEST_FOR_EXCEPTION(
294 A.is_null(), std::runtime_error, "Ifpack2::DatabaseSchwarz::getNodeSmootherComplexity: "
295 "The input matrix A is null. Please call setMatrix() with a nonnull "
296 "input matrix, then call compute(), before calling this method.");
297 // DatabaseSchwarz costs roughly one apply + one diagonal inverse per iteration
298 return A->getLocalNumRows() + A->getLocalNumEntries();
299}
300
301
302
303template<class MatrixType>
304void
306apply(const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
307 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
308 Teuchos::ETransp mode,
309 scalar_type alpha,
310 scalar_type beta) const
311{
312 const std::string timerName ("Ifpack2::DatabaseSchwarz::apply");
313 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
314 if (timer.is_null()) {
315 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
316 }
317
318 double startTime = timer->wallTime();
319
320 // Start timing here.
321 {
322 Teuchos::TimeMonitor timeMon (*timer);
323
324 // compute() calls initialize() if it hasn't already been called.
325 // Thus, we only need to check isComputed().
326 TEUCHOS_TEST_FOR_EXCEPTION(
327 ! isComputed(), std::runtime_error,
328 "Ifpack2::DatabaseSchwarz::apply(): You must call the compute() method before "
329 "you may call apply().");
330 TEUCHOS_TEST_FOR_EXCEPTION(
331 X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
332 "Ifpack2::DatabaseSchwarz::apply(): X and Y must have the same number of "
333 "columns. X.getNumVectors() = " << X.getNumVectors() << " != "
334 << "Y.getNumVectors() = " << Y.getNumVectors() << ".");
335
336 // 1. Compute beta*Y
337 Y.scale(beta);
338
339 // 2. Solve prec on X
340 auto X_view = X.getLocalViewHost(Tpetra::Access::ReadOnly);
341 auto Y_view = Y.getLocalViewHost(Tpetra::Access::ReadWrite);
342
343 Teuchos::LAPACK<int, typename row_matrix_type::scalar_type> lapack;
344 int INFO = 0;
345 for(unsigned int ipatch=0; ipatch<NumPatches_; ipatch++) {
346 int idatabase = DatabaseIndices_[ipatch];
347
348 // 2a. Split X into Xk on each local patch
349 Teuchos::Array<typename row_matrix_type::scalar_type> x_patch(PatchSize_);
350 for(unsigned int c=0; c<X_view.extent(1); ++c) {
351 for(unsigned int i=0; i<x_patch.size(); ++i) {
352 x_patch[i] = X_view(PatchIndices_[ipatch][i],c);
353 }
354 }
355
356 // 2b. Solve each using Lapack::GETRS
357 // GH: TODO: can improve this by grouping all patches such that DatabaseIndices_[ipatch] is equal
358 // in the compute phase and then utilizing the multiple RHS capability here.
359 int numRhs = 1;
360
361 int* ipiv = &ipiv_[idatabase*PatchSize_];
362
363 lapack.GETRS('N', DatabaseMatrices_[idatabase]->numRows(), numRhs,
364 DatabaseMatrices_[idatabase]->values(), DatabaseMatrices_[idatabase]->numRows(),
365 ipiv, x_patch.getRawPtr(),
366 DatabaseMatrices_[idatabase]->numRows(), &INFO);
367
368 // INFO < 0 is a bug.
369 TEUCHOS_TEST_FOR_EXCEPTION(
370 INFO < 0, std::logic_error, "Ifpack2::DatabaseSchwarz::compute: "
371 "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
372 "incorrectly. INFO = " << INFO << " < 0. "
373 "Please report this bug to the Ifpack2 developers.");
374 // INFO > 0 means the matrix is singular. This is probably an issue
375 // either with the choice of rows the rows we extracted, or with the
376 // input matrix itself.
377 TEUCHOS_TEST_FOR_EXCEPTION(
378 INFO > 0, std::runtime_error, "Ifpack2::DatabaseSchwarz::compute: "
379 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
380 "computed U factor is exactly singular. U(" << INFO << "," << INFO << ") "
381 "(one-based index i) is exactly zero. This probably means that the input "
382 "patch is singular.");
383
384 // 2c. Add alpha*weights*Xk into Y for each Xk
385 for(unsigned int c=0; c<Y_view.extent(1); ++c) {
386 for(unsigned int i=0; i<x_patch.size(); ++i) {
387 Y_view(PatchIndices_[ipatch][i],c) += alpha*Weights_[PatchIndices_[ipatch][i]]*x_patch[i];
388 }
389 }
390 }
391 }
392 ++NumApply_;
393 ApplyTime_ += (timer->wallTime() - startTime);
394}
395
396
397template<class MatrixType>
398void
400applyMat (const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
401 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
402 Teuchos::ETransp mode) const
403{
404 TEUCHOS_TEST_FOR_EXCEPTION(
405 X.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
406 "Ifpack2::DatabaseSchwarz::applyMat: X.getNumVectors() != Y.getNumVectors().");
407
408 Teuchos::RCP<const row_matrix_type> A = getMatrix();
409 TEUCHOS_TEST_FOR_EXCEPTION(
410 A.is_null(), std::runtime_error, "Ifpack2::DatabaseSchwarz::applyMat: The input "
411 "matrix A is null. Please call setMatrix() with a nonnull input matrix "
412 "before calling this method.");
413
414 A->apply (X, Y, mode);
415}
416
417
418template<class MatrixType>
420 // We create the timer, but this method doesn't do anything, so
421 // there is no need to start the timer. The resulting total time
422 // will always be zero.
423 const std::string timerName ("Ifpack2::DatabaseSchwarz::initialize");
424 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
425 if (timer.is_null()) {
426 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
427 }
428 IsInitialized_ = true;
429 ++NumInitialize_;
430}
431
432
433template<class MatrixType>
435{
436 const std::string timerName ("Ifpack2::DatabaseSchwarz::compute");
437 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
438 if (timer.is_null()) {
439 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
440 }
441
442 double startTime = timer->wallTime();
443
444 // Start timing here.
445 {
446 Teuchos::TimeMonitor timeMon(*timer);
447 if (!isInitialized()) {
448 initialize();
449 }
450 IsComputed_ = false;
451 const int maxNnzPerRow = A_->getGlobalMaxNumRowEntries();
452
453 // Phase 1: Loop over rows of A_, construct patch indices, and construct patch matrices
454 PatchIndices_.resize(0);
455 NumPatches_ = 0;
456 // loop over potential candidates by checking rows of A_
457 for(local_ordinal_type irow=0; irow < (local_ordinal_type) A_->getLocalNumRows(); ++irow) {
458 size_t num_entries = A_->getNumEntriesInLocalRow(irow);
459
460 // if irow is a potential patch candidate
461 if((local_ordinal_type) num_entries == PatchSize_) {
462 // grab row irow of A_
463 typename row_matrix_type::nonconst_local_inds_host_view_type row_inds("row indices", maxNnzPerRow);
464 typename row_matrix_type::nonconst_values_host_view_type row_vals("row values", maxNnzPerRow);
465 A_->getLocalRowCopy(irow, row_inds, row_vals, num_entries);
466
467 // check if we've added DOF irow before
468 bool is_new_patch = true;
469 for(size_t ipatch=0; ipatch<PatchIndices_.size(); ++ipatch) {
470 for(size_t i=0; i<PatchIndices_[ipatch].size(); ++i) {
471 if(PatchIndices_[ipatch][i] == irow) {
472 is_new_patch = false;
473 ipatch=PatchIndices_.size(); // likely the ugliest way to break out other than using goto TheEnd:
474 break;
475 }
476 }
477 }
478
479 // if this patch is new, append the indices
480 if(is_new_patch) {
481 Teuchos::ArrayView<typename row_matrix_type::local_ordinal_type> indices_array_view(row_inds.data(),num_entries);
482 std::vector<typename row_matrix_type::local_ordinal_type> indices_vector = Teuchos::createVector(indices_array_view);
483 PatchIndices_.push_back(indices_vector);
484 NumPatches_++;
485 }
486 }
487 }
488
489 // Phase 2: construct the list of local patch matrices
490 typedef typename Teuchos::SerialDenseMatrix<typename row_matrix_type::local_ordinal_type,typename row_matrix_type::scalar_type> DenseMatType;
491 typedef Teuchos::RCP<DenseMatType> DenseMatRCP;
492 DatabaseIndices_.resize(NumPatches_,-1);
493 Weights_.resize(A_->getLocalNumRows(),0);
494 std::vector<double> index_count(A_->getLocalNumRows(),0);
495 // compute the local patch matrix A_k by grabbing values from the rows of A_
496 for(unsigned int ipatch=0; ipatch< NumPatches_; ++ipatch) {
497 // form a local patch matrix and grab the indices for its rows/columns
498 DenseMatRCP patch_matrix = Teuchos::rcp(new DenseMatType(PatchSize_, PatchSize_));
499 auto indices_vector = PatchIndices_[ipatch];
500
501 for(local_ordinal_type i=0; i<PatchSize_; ++i) {
502 index_count[indices_vector[i]]++;
503 // grab each row from A_ and throw them into patch_matrix
504 typename row_matrix_type::nonconst_local_inds_host_view_type row_inds("row indices", maxNnzPerRow);
505 typename row_matrix_type::nonconst_values_host_view_type row_vals("row values", maxNnzPerRow);
506 size_t num_entries;
507 A_->getLocalRowCopy(indices_vector[i], row_inds, row_vals, num_entries);
508 for(local_ordinal_type j=0; j<PatchSize_; ++j) {
509 for(size_t k=0; k<num_entries; ++k) {
510 if(row_inds(k) == indices_vector[j]) {
511 (*patch_matrix)(i,j) = row_vals(k);
512 }
513 }
514 }
515 }
516
517 // check if the local patch matrix has been seen before
518 // this is skipped and the patch is stored anyway if SkipDatabase_ is true
519 bool found_match = false;
520 if(!SkipDatabase_) {
521 for(size_t idatabase=0; idatabase<DatabaseMatrices_.size(); ++idatabase) {
522
523 // sum errors
524 typename Teuchos::ScalarTraits<typename row_matrix_type::scalar_type>::magnitudeType abserror = 0.0;
525 for(local_ordinal_type irow=0; irow<PatchSize_; irow++) {
526 for(local_ordinal_type icol=0; icol<PatchSize_; ++icol) {
527 DenseMatRCP database_candidate = DatabaseMatrices_[idatabase];
528 abserror += Teuchos::ScalarTraits<typename row_matrix_type::scalar_type>::magnitude((*patch_matrix)(irow,icol)-(*database_candidate)(irow,icol));
529 }
530 // break out early if we finish a row and the error is already too high
531 if(abserror > Teuchos::as<typename Teuchos::ScalarTraits<typename row_matrix_type::scalar_type>::magnitudeType>(PatchTolerance_))
532 break;
533 }
534
535 // check if this error is acceptable; if so, mark the match and break
536 if(abserror < Teuchos::as<typename Teuchos::ScalarTraits<typename row_matrix_type::scalar_type>::magnitudeType>(PatchTolerance_)) {
537 DatabaseIndices_[ipatch] = idatabase;
538 found_match = true;
539 break;
540 }
541 }
542 }
543
544 // if no match was found, append patch_matrix to the database
545 if(!found_match) {
546 DatabaseMatrices_.push_back(patch_matrix);
547 DatabaseIndices_[ipatch] = DatabaseMatrices_.size()-1;
548 TEUCHOS_TEST_FOR_EXCEPTION(DatabaseMatrices_[DatabaseMatrices_.size()-1].is_null(), std::logic_error,
549 "Ifpack2::DatabaseSchwarz::compute: A matrix was added to the database, but appears to be null!"
550 "Please report this bug to the Ifpack2 developers.");
551 }
552 }
553
554 // compute proc-local overlap weights
555 for(unsigned int i=0; i<index_count.size(); ++i) {
556 TEUCHOS_TEST_FOR_EXCEPTION(index_count[i] == 0.0, std::logic_error,
557 "Ifpack2::DatabaseSchwarz::compute: DOF " << i << " has no corresponding patch! "
558 "All DOFs must be able to locate in a patch to use this method! "
559 "Have you considered adjusting the patch size? Currently it is " << PatchSize_ << ".");
560 Weights_[i] = 1./index_count[i];
561 }
562 DatabaseSize_ = DatabaseMatrices_.size();
563
564 // compute how many patches refer to a given database entry
565 std::vector<int> database_counts(DatabaseSize_,0);
566 for(unsigned int ipatch=0; ipatch<NumPatches_; ++ipatch) {
567 database_counts[DatabaseIndices_[ipatch]]++;
568 }
569
570 // Phase 3: factor the patches using LAPACK (GETRF for factorization)
571 Teuchos::LAPACK<int, typename row_matrix_type::scalar_type> lapack;
572 int INFO = 0;
573 ipiv_.resize(DatabaseSize_*PatchSize_);
574 std::fill(ipiv_.begin (), ipiv_.end (), 0);
575 for(unsigned int idatabase=0; idatabase<DatabaseSize_; idatabase++) {
576 int* ipiv = &ipiv_[idatabase*PatchSize_];
577
578 lapack.GETRF(DatabaseMatrices_[idatabase]->numRows(),
579 DatabaseMatrices_[idatabase]->numCols(),
580 DatabaseMatrices_[idatabase]->values(),
581 DatabaseMatrices_[idatabase]->stride(),
582 ipiv, &INFO);
583
584 // INFO < 0 is a bug.
585 TEUCHOS_TEST_FOR_EXCEPTION(
586 INFO < 0, std::logic_error, "Ifpack2::DatabaseSchwarz::compute: "
587 "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
588 "incorrectly. INFO = " << INFO << " < 0. "
589 "Please report this bug to the Ifpack2 developers.");
590 // INFO > 0 means the matrix is singular. This is probably an issue
591 // either with the choice of rows the rows we extracted, or with the
592 // input matrix itself.
593 if(INFO > 0) {
594 std::cout << "SINGULAR LOCAL MATRIX, COUNT=" << database_counts[idatabase] << std::endl;
595 }
596 TEUCHOS_TEST_FOR_EXCEPTION(
597 INFO > 0, std::runtime_error, "Ifpack2::DatabaseSchwarz::compute: "
598 "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
599 "computed U factor is exactly singular. U(" << INFO << "," << INFO << ") "
600 "(one-based index i) is exactly zero. This probably means that the input "
601 "patch is singular.");
602 }
603 }
604 IsComputed_ = true;
605 ++NumCompute_;
606
607 ComputeTime_ += (timer->wallTime() - startTime);
608
609 // print a summary after compute finishes if Verbose_ is true (TODO: fancyostream)
610 if(Verbose_) {
611 std::cout << "Ifpack2::DatabaseSchwarz()::Compute() summary\n";
612 std::cout << "Found " << NumPatches_ << " patches of size " << PatchSize_ << " in matrix A\n";
613 std::cout << "Database tol = " << PatchTolerance_ << "\n";
614 std::cout << "Database size = " << DatabaseSize_ << " patches\n";
615 }
616}
617
618
619template <class MatrixType>
621 std::ostringstream out;
622
623 // Output is a valid YAML dictionary in flow style. If you don't
624 // like everything on a single line, you should call describe()
625 // instead.
626 out << "\"Ifpack2::DatabaseSchwarz\": {";
627 out << "Initialized: " << (isInitialized() ? "true" : "false")
628 << ", Computed: " << (isComputed() ? "true" : "false")
629 << ", patch size: " << PatchSize_
630 << ", patch tolerance: " << PatchTolerance_
631 << ", skip database: " << (SkipDatabase_ ? "true" : "false")
632 << ", print database summary: " << (Verbose_ ? "true" : "false");
633
634 if (getMatrix().is_null()) {
635 out << "Matrix: null";
636 }
637 else {
638 out << "Global matrix dimensions: ["
639 << getMatrix()->getGlobalNumRows() << ", "
640 << getMatrix()->getGlobalNumCols() << "]"
641 << ", Global nnz: " << getMatrix()->getGlobalNumEntries();
642 }
643
644 out << "}";
645 return out.str();
646}
647
648
649template <class MatrixType>
651describe (Teuchos::FancyOStream& out,
652 const Teuchos::EVerbosityLevel verbLevel) const
653{
654 using Teuchos::TypeNameTraits;
655 using std::endl;
656
657 // Default verbosity level is VERB_LOW
658 const Teuchos::EVerbosityLevel vl =
659 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
660
661 if (vl == Teuchos::VERB_NONE) {
662 return; // print NOTHING, not even the class name
663 }
664
665 // By convention, describe() starts with a tab.
666 //
667 // This does affect all processes on which it's valid to print to
668 // 'out'. However, it does not actually print spaces to 'out'
669 // unless operator<< gets called, so it's safe to use on all
670 // processes.
671 Teuchos::OSTab tab0 (out);
672 const int myRank = this->getComm()->getRank();
673 if (myRank == 0) {
674 // Output is a valid YAML dictionary.
675 // In particular, we quote keys with colons in them.
676 out << "\"Ifpack2::DatabaseSchwarz\":" << endl;
677 }
678
679 Teuchos::OSTab tab1 (out);
680 if (vl >= Teuchos::VERB_LOW && myRank == 0) {
681 out << "Template parameters:" << endl;
682 {
683 Teuchos::OSTab tab2 (out);
684 out << "Scalar: " << TypeNameTraits<scalar_type>::name() << endl
685 << "LocalOrdinal: " << TypeNameTraits<local_ordinal_type>::name() << endl
686 << "GlobalOrdinal: " << TypeNameTraits<global_ordinal_type>::name() << endl
687 << "Device: " << TypeNameTraits<device_type>::name() << endl;
688 }
689 out << "Initialized: " << (isInitialized() ? "true" : "false") << endl
690 << "Computed: " << (isComputed() ? "true" : "false") << endl;
691
692 if (getMatrix().is_null()) {
693 out << "Matrix: null" << endl;
694 }
695 else {
696 out << "Global matrix dimensions: ["
697 << getMatrix()->getGlobalNumRows() << ", "
698 << getMatrix()->getGlobalNumCols() << "]" << endl
699 << "Global nnz: " << getMatrix()->getGlobalNumEntries() << endl;
700 }
701 }
702}
703
704
705
706}//namespace Ifpack2
707
708#define IFPACK2_DATABASESCHWARZ_INSTANT(S,LO,GO,N) \
709 template class Ifpack2::DatabaseSchwarz< Tpetra::RowMatrix<S, LO, GO, N> >;
710
711#endif // IFPACK2_DATABASESCHWARZ_DEF_HPP
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:306
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:202
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition Ifpack2_DatabaseSchwarz_decl.hpp:127
void setParameters(const Teuchos::ParameterList &params)
Set (or reset) parameters.
Definition Ifpack2_DatabaseSchwarz_def.hpp:126
bool isInitialized() const
Definition Ifpack2_DatabaseSchwarz_decl.hpp:205
bool hasTransposeApply() const
Whether it's possible to apply the transpose of this operator.
Definition Ifpack2_DatabaseSchwarz_def.hpp:238
double getComputeFlops() const
The total number of floating-point operations taken by all calls to compute().
Definition Ifpack2_DatabaseSchwarz_def.hpp:280
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:651
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:400
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition Ifpack2_DatabaseSchwarz_def.hpp:291
int getNumApply() const
The total number of successful calls to apply().
Definition Ifpack2_DatabaseSchwarz_def.hpp:256
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition Ifpack2_DatabaseSchwarz_decl.hpp:121
DatabaseSchwarz(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition Ifpack2_DatabaseSchwarz_def.hpp:61
bool isComputed() const
Whether compute() has been called at least once.
Definition Ifpack2_DatabaseSchwarz_decl.hpp:214
Teuchos::RCP< const map_type > getDomainMap() const
The Tpetra::Map representing the domain of this operator.
Definition Ifpack2_DatabaseSchwarz_def.hpp:212
virtual ~DatabaseSchwarz()
Destructor.
Definition Ifpack2_DatabaseSchwarz_def.hpp:108
void setZeroStartingSolution(bool zeroStartingSolution)
Set this preconditioner's parameters.
Definition Ifpack2_DatabaseSchwarz_def.hpp:170
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition Ifpack2_DatabaseSchwarz_decl.hpp:118
int getNumCompute() const
The total number of successful calls to compute().
Definition Ifpack2_DatabaseSchwarz_def.hpp:250
double getComputeTime() const
The total time spent in all calls to compute().
Definition Ifpack2_DatabaseSchwarz_def.hpp:268
double getApplyTime() const
The total time spent in all calls to apply().
Definition Ifpack2_DatabaseSchwarz_def.hpp:274
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition Ifpack2_DatabaseSchwarz_def.hpp:113
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition Ifpack2_DatabaseSchwarz_decl.hpp:115
Teuchos::RCP< const row_matrix_type > A_
The matrix for which this is a preconditioner.
Definition Ifpack2_DatabaseSchwarz_decl.hpp:265
double getInitializeTime() const
The total time spent in all calls to initialize().
Definition Ifpack2_DatabaseSchwarz_def.hpp:262
Teuchos::RCP< const map_type > getRangeMap() const
The Tpetra::Map representing the range of this operator.
Definition Ifpack2_DatabaseSchwarz_def.hpp:226
void compute()
(Re)compute the left scaling, and (if applicable) estimate max and min eigenvalues of D_inv * A.
Definition Ifpack2_DatabaseSchwarz_def.hpp:434
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix is distributed.
Definition Ifpack2_DatabaseSchwarz_def.hpp:177
int getNumInitialize() const
The total number of successful calls to initialize().
Definition Ifpack2_DatabaseSchwarz_def.hpp:244
double getApplyFlops() const
The total number of floating-point operations taken by all calls to apply().
Definition Ifpack2_DatabaseSchwarz_def.hpp:286
std::string description() const
A simple one-line description of this object.
Definition Ifpack2_DatabaseSchwarz_def.hpp:620
void initialize()
Initialize the preconditioner.
Definition Ifpack2_DatabaseSchwarz_def.hpp:419
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix for which this is a preconditioner.
Definition Ifpack2_DatabaseSchwarz_def.hpp:190
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:74