55 #ifndef IFPACK2_ADDITIVESCHWARZ_DEF_HPP
56 #define IFPACK2_ADDITIVESCHWARZ_DEF_HPP
62 #include "Ifpack2_Details_LinearSolver.hpp"
63 #include "Ifpack2_Details_getParamTryingTypes.hpp"
65 #if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
66 #include "Zoltan2_TpetraRowGraphAdapter.hpp"
67 #include "Zoltan2_OrderingProblem.hpp"
68 #include "Zoltan2_OrderingSolution.hpp"
72 #include "Ifpack2_LocalFilter.hpp"
73 #include "Ifpack2_OverlappingRowMatrix.hpp"
74 #include "Ifpack2_Parameters.hpp"
75 #include "Ifpack2_ReorderFilter.hpp"
76 #include "Ifpack2_SingletonFilter.hpp"
82 #include "Teuchos_StandardParameterEntryValidators.hpp"
95 #ifdef HAVE_IFPACK2_DEBUG
104 using magnitude_type =
typename STS::magnitudeType;
110 for (
size_t j = 0; j < X.getNumVectors (); ++j) {
111 if (STM::isnaninf (norms[j])) {
121 #endif // HAVE_IFPACK2_DEBUG
125 template<
class MatrixType,
class LocalInverseType>
127 AdditiveSchwarz<MatrixType, LocalInverseType>::hasInnerPrecName ()
const
129 const char* options[4] = {
130 "inner preconditioner name",
131 "subdomain solver name",
132 "schwarz: inner preconditioner name",
133 "schwarz: subdomain solver name"
135 const int numOptions = 4;
137 for (
int k = 0; k < numOptions && ! match; ++k) {
138 if (List_.isParameter (options[k])) {
146 template<
class MatrixType,
class LocalInverseType>
148 AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecName ()
150 const char* options[4] = {
151 "inner preconditioner name",
152 "subdomain solver name",
153 "schwarz: inner preconditioner name",
154 "schwarz: subdomain solver name"
156 const int numOptions = 4;
157 for (
int k = 0; k < numOptions; ++k) {
158 List_.
remove (options[k],
false);
163 template<
class MatrixType,
class LocalInverseType>
165 AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecName ()
const
167 const char* options[4] = {
168 "inner preconditioner name",
169 "subdomain solver name",
170 "schwarz: inner preconditioner name",
171 "schwarz: subdomain solver name"
173 const int numOptions = 4;
178 for (
int k = 0; k < numOptions && ! match; ++k) {
180 List_.getEntryPtr (options[k]);
181 if (paramEnt !=
nullptr && paramEnt->
isType<std::string> ()) {
182 newName = Teuchos::getValue<std::string> (*paramEnt);
186 return match ? newName : defaultInnerPrecName ();
190 template<
class MatrixType,
class LocalInverseType>
192 AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecParams ()
194 const char* options[4] = {
195 "inner preconditioner parameters",
196 "subdomain solver parameters",
197 "schwarz: inner preconditioner parameters",
198 "schwarz: subdomain solver parameters"
200 const int numOptions = 4;
203 for (
int k = 0; k < numOptions; ++k) {
204 List_.remove (options[k],
false);
209 template<
class MatrixType,
class LocalInverseType>
210 std::pair<Teuchos::ParameterList, bool>
211 AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecParams ()
const
213 const char* options[4] = {
214 "inner preconditioner parameters",
215 "subdomain solver parameters",
216 "schwarz: inner preconditioner parameters",
217 "schwarz: subdomain solver parameters"
219 const int numOptions = 4;
224 for (
int k = 0; k < numOptions && ! match; ++k) {
225 if (List_.isSublist (options[k])) {
226 params = List_.
sublist (options[k]);
231 return std::make_pair (params, match);
234 template<
class MatrixType,
class LocalInverseType>
236 AdditiveSchwarz<MatrixType, LocalInverseType>::defaultInnerPrecName ()
243 template<
class MatrixType,
class LocalInverseType>
249 template<
class MatrixType,
class LocalInverseType>
252 const int overlapLevel) :
254 OverlapLevel_ (overlapLevel)
257 template<
class MatrixType,
class LocalInverseType>
263 Matrix_.is_null (), std::runtime_error,
"Ifpack2::AdditiveSchwarz::"
264 "getDomainMap: The matrix to precondition is null. You must either pass "
265 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
266 "input, before you may call this method.");
267 return Matrix_->getDomainMap ();
271 template<
class MatrixType,
class LocalInverseType>
276 Matrix_.is_null (), std::runtime_error,
"Ifpack2::AdditiveSchwarz::"
277 "getRangeMap: The matrix to precondition is null. You must either pass "
278 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
279 "input, before you may call this method.");
280 return Matrix_->getRangeMap ();
284 template<
class MatrixType,
class LocalInverseType>
291 template<
class MatrixType,
class LocalInverseType>
294 apply (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &B,
295 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &Y,
304 using Teuchos::rcp_dynamic_cast;
306 const char prefix[] =
"Ifpack2::AdditiveSchwarz::apply: ";
309 (! IsComputed_, std::runtime_error,
310 prefix <<
"isComputed() must be true before you may call apply().");
312 (Matrix_.is_null (), std::logic_error, prefix <<
313 "The input matrix A is null, but the preconditioner says that it has "
314 "been computed (isComputed() is true). This should never happen, since "
315 "setMatrix() should always mark the preconditioner as not computed if "
316 "its argument is null. "
317 "Please report this bug to the Ifpack2 developers.");
319 (Inverse_.is_null (), std::runtime_error,
320 prefix <<
"The subdomain solver is null. "
321 "This can only happen if you called setInnerPreconditioner() with a null "
322 "input, after calling initialize() or compute(). If you choose to call "
323 "setInnerPreconditioner() with a null input, you must then call it with "
324 "a nonnull input before you may call initialize() or compute().");
326 (B.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
327 prefix <<
"B and Y must have the same number of columns. B has " <<
328 B.getNumVectors () <<
" columns, but Y has " << Y.getNumVectors() <<
".");
330 (IsOverlapping_ && OverlappingMatrix_.is_null (), std::logic_error,
331 prefix <<
"The overlapping matrix is null. "
332 "This should never happen if IsOverlapping_ is true. "
333 "Please report this bug to the Ifpack2 developers.");
335 (! IsOverlapping_ && localMap_.is_null (), std::logic_error,
336 prefix <<
"localMap_ is null. "
337 "This should never happen if IsOverlapping_ is false. "
338 "Please report this bug to the Ifpack2 developers.");
340 (alpha != STS::one (), std::logic_error,
341 prefix <<
"Not implemented for alpha != 1.");
342 TEUCHOS_TEST_FOR_EXCEPTION
343 (beta != STS::zero (), std::logic_error,
344 prefix <<
"Not implemented for beta != 0.");
346 #ifdef HAVE_IFPACK2_DEBUG
348 const bool bad = anyBad (B);
349 TEUCHOS_TEST_FOR_EXCEPTION
350 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
351 "The 2-norm of the input B is NaN or Inf.");
353 #endif // HAVE_IFPACK2_DEBUG
355 #ifdef HAVE_IFPACK2_DEBUG
356 if (! ZeroStartingSolution_) {
357 const bool bad = anyBad (Y);
358 TEUCHOS_TEST_FOR_EXCEPTION
359 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
360 "On input, the initial guess Y has 2-norm NaN or Inf "
361 "(ZeroStartingSolution_ is false).");
363 #endif // HAVE_IFPACK2_DEBUG
365 const std::string timerName (
"Ifpack2::AdditiveSchwarz::apply");
366 RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
367 if (timer.is_null ()) {
368 timer = TimeMonitor::getNewCounter (timerName);
372 TimeMonitor timeMon (*timer);
375 const size_t numVectors = B.getNumVectors ();
379 if (ZeroStartingSolution_) {
384 MV* OverlappingB =
nullptr;
385 MV* OverlappingY =
nullptr;
387 RCP<const map_type> B_and_Y_map = IsOverlapping_ ?
388 OverlappingMatrix_->getRowMap () : localMap_;
389 if (overlapping_B_.get () ==
nullptr ||
390 overlapping_B_->getNumVectors () != numVectors) {
391 overlapping_B_.reset (
new MV (B_and_Y_map, numVectors,
false));
393 if (overlapping_Y_.get () ==
nullptr ||
394 overlapping_Y_->getNumVectors () != numVectors) {
395 overlapping_Y_.reset (
new MV (B_and_Y_map, numVectors,
false));
397 OverlappingB = overlapping_B_.get ();
398 OverlappingY = overlapping_Y_.get ();
401 OverlappingB->putScalar (ZERO);
402 OverlappingY->putScalar (ZERO);
405 RCP<MV> globalOverlappingB;
406 if (! IsOverlapping_) {
408 OverlappingB->offsetViewNonConst (Matrix_->getRowMap (), 0);
411 if (DistributedImporter_.is_null ()) {
415 DistributedImporter_ =
416 rcp (
new import_type (Matrix_->getRowMap (),
417 Matrix_->getDomainMap ()));
421 if (R_.get () ==
nullptr || R_->getNumVectors () != numVectors) {
422 R_.reset (
new MV (B.getMap (), numVectors,
false));
424 if (C_.get () ==
nullptr || C_->getNumVectors () != numVectors) {
425 C_.reset (
new MV (Y.getMap (), numVectors,
false));
434 for (
int ni=0; ni<NumIterations_; ++ni)
436 #ifdef HAVE_IFPACK2_DEBUG
438 const bool bad = anyBad (Y);
439 TEUCHOS_TEST_FOR_EXCEPTION
440 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
441 "At top of iteration " << ni <<
", the 2-norm of Y is NaN or Inf.");
443 #endif // HAVE_IFPACK2_DEBUG
445 Tpetra::deep_copy(*R, B);
450 if (!ZeroStartingSolution_ || ni > 0) {
452 Matrix_->apply (Y, *R, mode, -STS::one(), STS::one());
454 #ifdef HAVE_IFPACK2_DEBUG
456 const bool bad = anyBad (*R);
457 TEUCHOS_TEST_FOR_EXCEPTION
458 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
459 "At iteration " << ni <<
", the 2-norm of R (result of computing "
460 "residual with Y) is NaN or Inf.");
462 #endif // HAVE_IFPACK2_DEBUG
466 RCP<overlap_mat_type> overlapMatrix;
467 if (IsOverlapping_) {
468 overlapMatrix = rcp_dynamic_cast<overlap_mat_type> (OverlappingMatrix_);
469 TEUCHOS_TEST_FOR_EXCEPTION
470 (overlapMatrix.is_null (), std::logic_error, prefix <<
471 "IsOverlapping_ is true, but OverlappingMatrix_, while nonnull, is "
472 "not an OverlappingRowMatrix<row_matrix_type>. Please report this "
473 "bug to the Ifpack2 developers.");
477 if (IsOverlapping_) {
478 TEUCHOS_TEST_FOR_EXCEPTION
479 (overlapMatrix.is_null (), std::logic_error, prefix
480 <<
"overlapMatrix is null when it shouldn't be. "
481 "Please report this bug to the Ifpack2 developers.");
482 overlapMatrix->importMultiVector (*R, *OverlappingB, Tpetra::INSERT);
499 #ifdef HAVE_IFPACK2_DEBUG
501 const bool bad = anyBad (*OverlappingB);
502 TEUCHOS_TEST_FOR_EXCEPTION
503 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
504 "At iteration " << ni <<
", result of importMultiVector from R "
505 "to OverlappingB, has 2-norm NaN or Inf.");
507 #endif // HAVE_IFPACK2_DEBUG
509 globalOverlappingB->doImport (*R, *DistributedImporter_, Tpetra::INSERT);
511 #ifdef HAVE_IFPACK2_DEBUG
513 const bool bad = anyBad (*globalOverlappingB);
514 TEUCHOS_TEST_FOR_EXCEPTION
515 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
516 "At iteration " << ni <<
", result of doImport from R, has 2-norm "
519 #endif // HAVE_IFPACK2_DEBUG
522 #ifdef HAVE_IFPACK2_DEBUG
524 const bool bad = anyBad (*OverlappingB);
525 TEUCHOS_TEST_FOR_EXCEPTION
526 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
527 "At iteration " << ni <<
", right before localApply, the 2-norm of "
528 "OverlappingB is NaN or Inf.");
530 #endif // HAVE_IFPACK2_DEBUG
533 localApply(*OverlappingB, *OverlappingY);
535 #ifdef HAVE_IFPACK2_DEBUG
537 const bool bad = anyBad (*OverlappingY);
538 TEUCHOS_TEST_FOR_EXCEPTION
539 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
540 "At iteration " << ni <<
", after localApply and before export / "
541 "copy, the 2-norm of OverlappingY is NaN or Inf.");
543 #endif // HAVE_IFPACK2_DEBUG
545 #ifdef HAVE_IFPACK2_DEBUG
547 const bool bad = anyBad (*C);
548 TEUCHOS_TEST_FOR_EXCEPTION
549 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
550 "At iteration " << ni <<
", before export / copy, the 2-norm of C "
553 #endif // HAVE_IFPACK2_DEBUG
556 if (IsOverlapping_) {
557 TEUCHOS_TEST_FOR_EXCEPTION
558 (overlapMatrix.is_null (), std::logic_error, prefix
559 <<
"overlapMatrix is null when it shouldn't be. "
560 "Please report this bug to the Ifpack2 developers.");
561 overlapMatrix->exportMultiVector (*OverlappingY, *C, CombineMode_);
570 RCP<MV> C_view = C->offsetViewNonConst (OverlappingY->getMap (), 0);
571 Tpetra::deep_copy (*C_view, *OverlappingY);
574 #ifdef HAVE_IFPACK2_DEBUG
576 const bool bad = anyBad (*C);
577 TEUCHOS_TEST_FOR_EXCEPTION
578 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
579 "At iteration " << ni <<
", before Y := C + Y, the 2-norm of C "
582 #endif // HAVE_IFPACK2_DEBUG
584 #ifdef HAVE_IFPACK2_DEBUG
586 const bool bad = anyBad (Y);
587 TEUCHOS_TEST_FOR_EXCEPTION
588 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
589 "Before Y := C + Y, at iteration " << ni <<
", the 2-norm of Y "
592 #endif // HAVE_IFPACK2_DEBUG
594 Y.update(UpdateDamping_, *C, STS::one());
596 #ifdef HAVE_IFPACK2_DEBUG
598 const bool bad = anyBad (Y);
599 TEUCHOS_TEST_FOR_EXCEPTION
600 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
601 "At iteration " << ni <<
", after Y := C + Y, the 2-norm of Y "
604 #endif // HAVE_IFPACK2_DEBUG
609 #ifdef HAVE_IFPACK2_DEBUG
611 const bool bad = anyBad (Y);
612 TEUCHOS_TEST_FOR_EXCEPTION
613 (bad, std::runtime_error,
"Ifpack2::AdditiveSchwarz::apply: "
614 "The 2-norm of the output Y is NaN or Inf.");
616 #endif // HAVE_IFPACK2_DEBUG
622 ApplyTime_ = timer->totalElapsedTime ();
625 template<
class MatrixType,
class LocalInverseType>
628 localApply (MV& OverlappingB, MV& OverlappingY)
const
631 using Teuchos::rcp_dynamic_cast;
633 const size_t numVectors = OverlappingB.getNumVectors ();
634 if (FilterSingletons_) {
636 MV ReducedB (SingletonMatrix_->getRowMap (), numVectors);
637 MV ReducedY (SingletonMatrix_->getRowMap (), numVectors);
639 RCP<SingletonFilter<row_matrix_type> > singletonFilter =
642 (! SingletonMatrix_.is_null () && singletonFilter.is_null (),
643 std::logic_error,
"Ifpack2::AdditiveSchwarz::localApply: "
644 "SingletonFilter_ is nonnull but is not a SingletonFilter"
645 "<row_matrix_type>. This should never happen. Please report this bug "
646 "to the Ifpack2 developers.");
647 singletonFilter->SolveSingletons (OverlappingB, OverlappingY);
648 singletonFilter->CreateReducedRHS (OverlappingY, OverlappingB, ReducedB);
651 if (! UseReordering_) {
652 Inverse_->solve (ReducedY, ReducedB);
655 RCP<ReorderFilter<row_matrix_type> > rf =
656 rcp_dynamic_cast<ReorderFilter<row_matrix_type> > (ReorderedLocalizedMatrix_);
658 (! ReorderedLocalizedMatrix_.is_null () && rf.is_null (), std::logic_error,
659 "Ifpack2::AdditiveSchwarz::localApply: ReorderedLocalizedMatrix_ is "
660 "nonnull but is not a ReorderFilter<row_matrix_type>. This should "
661 "never happen. Please report this bug to the Ifpack2 developers.");
664 rf->permuteOriginalToReordered (ReducedB, ReorderedB);
665 Inverse_->solve (ReorderedY, ReorderedB);
666 rf->permuteReorderedToOriginal (ReorderedY, ReducedY);
670 singletonFilter->UpdateLHS (ReducedY, OverlappingY);
674 if (! UseReordering_) {
675 Inverse_->solve (OverlappingY, OverlappingB);
681 RCP<ReorderFilter<row_matrix_type> > rf =
682 rcp_dynamic_cast<ReorderFilter<row_matrix_type> > (ReorderedLocalizedMatrix_);
684 (! ReorderedLocalizedMatrix_.is_null () && rf.is_null (), std::logic_error,
685 "Ifpack2::AdditiveSchwarz::localApply: ReorderedLocalizedMatrix_ is "
686 "nonnull but is not a ReorderFilter<row_matrix_type>. This should "
687 "never happen. Please report this bug to the Ifpack2 developers.");
688 rf->permuteOriginalToReordered (OverlappingB, ReorderedB);
689 Inverse_->solve (ReorderedY, ReorderedB);
690 rf->permuteReorderedToOriginal (ReorderedY, OverlappingY);
696 template<
class MatrixType,
class LocalInverseType>
704 this->setParameterList (Teuchos::rcpFromRef (List_));
709 template<
class MatrixType,
class LocalInverseType>
713 using Tpetra::CombineMode;
719 using Teuchos::rcp_dynamic_cast;
721 using Details::getParamTryingTypes;
722 const char prefix[] =
"Ifpack2::AdditiveSchwarz: ";
727 this->setParameterList (
rcp (
new ParameterList ()));
734 plist.
is_null (), std::logic_error,
"Ifpack2::AdditiveSchwarz::"
735 "setParameterList: plist is null. This should never happen, since the "
736 "method should have replaced a null input list with a nonnull empty list "
737 "by this point. Please report this bug to the Ifpack2 developers.");
758 const std::string cmParamName (
"schwarz: combine mode");
759 const ParameterEntry* cmEnt = plist->
getEntryPtr (cmParamName);
760 if (cmEnt !=
nullptr) {
761 if (cmEnt->isType<CombineMode> ()) {
762 CombineMode_ = Teuchos::getValue<CombineMode> (*cmEnt);
764 else if (cmEnt->isType<
int> ()) {
765 const int cm = Teuchos::getValue<int> (*cmEnt);
766 CombineMode_ =
static_cast<CombineMode
> (cm);
768 else if (cmEnt->isType<std::string> ()) {
773 const ParameterEntry& validEntry =
775 RCP<const ParameterEntryValidator> v = validEntry.validator ();
776 using vs2e_type = StringToIntegralParameterEntryValidator<CombineMode>;
777 RCP<const vs2e_type> vs2e = rcp_dynamic_cast<
const vs2e_type> (v,
true);
779 const ParameterEntry& inputEntry = plist->
getEntry (cmParamName);
780 CombineMode_ = vs2e->getIntegralValue (inputEntry, cmParamName);
784 OverlapLevel_ = plist->
get (
"schwarz: overlap level", OverlapLevel_);
790 UseReordering_ = plist->
get (
"schwarz: use reordering", UseReordering_);
792 #if !defined(HAVE_IFPACK2_XPETRA) || !defined(HAVE_IFPACK2_ZOLTAN2)
794 UseReordering_, std::invalid_argument,
"Ifpack2::AdditiveSchwarz::"
795 "setParameters: You specified \"schwarz: use reordering\" = true. "
796 "This is only valid when Trilinos was built with Ifpack2, Xpetra, and "
797 "Zoltan2 enabled. Either Xpetra or Zoltan2 was not enabled in your build "
809 FilterSingletons_ = plist->
get (
"schwarz: filter singletons", FilterSingletons_);
812 getParamTryingTypes<scalar_type, scalar_type, double>
813 (UpdateDamping_, *plist,
"schwarz: update damping", prefix);
848 if (! Inverse_.is_null ()) {
851 if (hasInnerPrecName () && innerPrecName () !=
"CUSTOM") {
854 Inverse_ = Teuchos::null;
859 std::pair<ParameterList, bool> result = innerPrecParams ();
863 Inverse_->setParameters (
rcp (
new ParameterList (result.first)));
868 NumIterations_ = plist->get (
"schwarz: num iterations", NumIterations_);
869 ZeroStartingSolution_ =
870 plist->get (
"schwarz: zero starting solution", ZeroStartingSolution_);
875 template<
class MatrixType,
class LocalInverseType>
881 using Teuchos::parameterList;
883 using Teuchos::rcp_const_cast;
885 if (validParams_.is_null ()) {
886 const int overlapLevel = 0;
887 const bool useReordering =
false;
888 const bool filterSingletons =
false;
889 const int numIterations = 1;
890 const bool zeroStartingSolution =
true;
892 ParameterList reorderingSublist;
893 reorderingSublist.set (
"order_method", std::string (
"rcm"));
895 RCP<ParameterList> plist = parameterList (
"Ifpack2::AdditiveSchwarz");
897 Tpetra::setCombineModeParameter (*plist,
"schwarz: combine mode");
898 plist->set (
"schwarz: overlap level", overlapLevel);
899 plist->set (
"schwarz: use reordering", useReordering);
900 plist->set (
"schwarz: reordering list", reorderingSublist);
903 plist->set (
"schwarz: compute condest",
false);
904 plist->set (
"schwarz: filter singletons", filterSingletons);
905 plist->set (
"schwarz: num iterations", numIterations);
906 plist->set (
"schwarz: zero starting solution", zeroStartingSolution);
907 plist->set (
"schwarz: update damping", updateDamping);
917 validParams_ = rcp_const_cast<
const ParameterList> (plist);
923 template<
class MatrixType,
class LocalInverseType>
926 using Tpetra::global_size_t;
933 const std::string timerName (
"Ifpack2::AdditiveSchwarz::initialize");
934 RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
935 if (timer.is_null ()) {
936 timer = TimeMonitor::getNewCounter (timerName);
940 TimeMonitor timeMon (*timer);
943 Matrix_.is_null (), std::runtime_error,
"Ifpack2::AdditiveSchwarz::"
944 "initialize: The matrix to precondition is null. You must either pass "
945 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
946 "input, before you may call this method.");
948 IsInitialized_ =
false;
950 overlapping_B_.reset (
nullptr);
951 overlapping_Y_.reset (
nullptr);
955 RCP<const Teuchos::Comm<int> > comm = Matrix_->getComm ();
956 RCP<const map_type> rowMap = Matrix_->getRowMap ();
957 const global_size_t INVALID =
962 if (comm->getSize () == 1) {
964 IsOverlapping_ =
false;
965 }
else if (OverlapLevel_ != 0) {
966 IsOverlapping_ =
true;
969 if (OverlapLevel_ == 0) {
971 RCP<const SerialComm<int> > localComm (
new SerialComm<int> ());
975 rcp (
new map_type (INVALID, rowMap->getNodeNumElements (),
976 indexBase, localComm));
980 if (IsOverlapping_) {
986 if (! Inverse_.is_null ()) {
987 Inverse_->symbolic ();
992 IsInitialized_ =
true;
997 InitializeTime_ = timer->totalElapsedTime ();
1001 template<
class MatrixType,
class LocalInverseType>
1004 return IsInitialized_;
1008 template<
class MatrixType,
class LocalInverseType>
1015 if (! IsInitialized_) {
1020 ! isInitialized (), std::logic_error,
"Ifpack2::AdditiveSchwarz::compute: "
1021 "The preconditioner is not yet initialized, "
1022 "even though initialize() supposedly has been called. "
1023 "This should never happen. "
1024 "Please report this bug to the Ifpack2 developers.");
1027 Inverse_.is_null (), std::runtime_error,
1028 "Ifpack2::AdditiveSchwarz::compute: The subdomain solver is null. "
1029 "This can only happen if you called setInnerPreconditioner() with a null "
1030 "input, after calling initialize() or compute(). If you choose to call "
1031 "setInnerPreconditioner() with a null input, you must then call it with a "
1032 "nonnull input before you may call initialize() or compute().");
1034 const std::string timerName (
"Ifpack2::AdditiveSchwarz::compute");
1035 RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
1036 if (timer.is_null ()) {
1037 timer = TimeMonitor::getNewCounter (timerName);
1041 TimeMonitor timeMon (*timer);
1043 IsComputed_ =
false;
1044 Inverse_->numeric ();
1052 ComputeTime_ = timer->totalElapsedTime ();
1057 template<
class MatrixType,
class LocalInverseType>
1064 template<
class MatrixType,
class LocalInverseType>
1067 return NumInitialize_;
1071 template<
class MatrixType,
class LocalInverseType>
1078 template<
class MatrixType,
class LocalInverseType>
1085 template<
class MatrixType,
class LocalInverseType>
1088 return InitializeTime_;
1092 template<
class MatrixType,
class LocalInverseType>
1095 return ComputeTime_;
1099 template<
class MatrixType,
class LocalInverseType>
1106 template<
class MatrixType,
class LocalInverseType>
1109 std::ostringstream out;
1111 out <<
"\"Ifpack2::AdditiveSchwarz\": {";
1112 if (this->getObjectLabel () !=
"") {
1113 out <<
"Label: \"" << this->getObjectLabel () <<
"\", ";
1115 out <<
"Initialized: " << (isInitialized () ?
"true" :
"false")
1116 <<
", Computed: " << (isComputed () ?
"true" :
"false")
1117 <<
", Iterations: " << NumIterations_
1118 <<
", Overlap level: " << OverlapLevel_
1119 <<
", Subdomain reordering: \"" << ReorderingAlgorithm_ <<
"\"";
1120 out <<
", Combine mode: \"";
1121 if (CombineMode_ == Tpetra::INSERT) {
1123 }
else if (CombineMode_ == Tpetra::ADD) {
1125 }
else if (CombineMode_ == Tpetra::REPLACE) {
1127 }
else if (CombineMode_ == Tpetra::ABSMAX) {
1129 }
else if (CombineMode_ == Tpetra::ZERO) {
1133 if (Matrix_.is_null ()) {
1134 out <<
", Matrix: null";
1137 out <<
", Global matrix dimensions: ["
1138 << Matrix_->getGlobalNumRows () <<
", "
1139 << Matrix_->getGlobalNumCols () <<
"]";
1141 out <<
", Inner solver: ";
1142 if (! Inverse_.is_null ()) {
1148 out <<
"{" <<
"Some inner solver" <<
"}";
1159 template<
class MatrixType,
class LocalInverseType>
1169 const int myRank = Matrix_->getComm ()->getRank ();
1170 const int numProcs = Matrix_->getComm ()->getSize ();
1178 out <<
"\"Ifpack2::AdditiveSchwarz\":";
1182 out <<
"MatrixType: " << TypeNameTraits<MatrixType>::name () << endl;
1183 out <<
"LocalInverseType: " << TypeNameTraits<LocalInverseType>::name () << endl;
1184 if (this->getObjectLabel () !=
"") {
1185 out <<
"Label: \"" << this->getObjectLabel () <<
"\"" << endl;
1188 out <<
"Overlap level: " << OverlapLevel_ << endl
1189 <<
"Combine mode: \"";
1190 if (CombineMode_ == Tpetra::INSERT) {
1192 }
else if (CombineMode_ == Tpetra::ADD) {
1194 }
else if (CombineMode_ == Tpetra::REPLACE) {
1196 }
else if (CombineMode_ == Tpetra::ABSMAX) {
1198 }
else if (CombineMode_ == Tpetra::ZERO) {
1202 <<
"Subdomain reordering: \"" << ReorderingAlgorithm_ <<
"\"" << endl;
1205 if (Matrix_.is_null ()) {
1207 out <<
"Matrix: null" << endl;
1212 out <<
"Matrix:" << endl;
1215 Matrix_->getComm ()->barrier ();
1220 out <<
"Number of initialize calls: " << getNumInitialize () << endl
1221 <<
"Number of compute calls: " << getNumCompute () << endl
1222 <<
"Number of apply calls: " << getNumApply () << endl
1223 <<
"Total time in seconds for initialize: " << getInitializeTime () << endl
1224 <<
"Total time in seconds for compute: " << getComputeTime () << endl
1225 <<
"Total time in seconds for apply: " << getApplyTime () << endl;
1228 if (Inverse_.is_null ()) {
1230 out <<
"Subdomain solver: null" << endl;
1236 out <<
"Subdomain solver: not null" << endl;
1240 for (
int p = 0; p < numProcs; ++p) {
1242 out <<
"Subdomain solver on Process " << myRank <<
":";
1243 if (Inverse_.is_null ()) {
1244 out <<
"null" << endl;
1252 out <<
"null" << endl;
1256 Matrix_->getComm ()->barrier ();
1257 Matrix_->getComm ()->barrier ();
1258 Matrix_->getComm ()->barrier ();
1263 Matrix_->getComm ()->barrier ();
1268 template<
class MatrixType,
class LocalInverseType>
1278 template<
class MatrixType,
class LocalInverseType>
1281 return OverlapLevel_;
1285 template<
class MatrixType,
class LocalInverseType>
1289 using Teuchos::MpiComm;
1295 using Teuchos::rcp_dynamic_cast;
1296 using Teuchos::rcpFromRef;
1299 Matrix_.is_null (), std::runtime_error,
"Ifpack2::AdditiveSchwarz::"
1300 "initialize: The matrix to precondition is null. You must either pass "
1301 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
1302 "input, before you may call this method.");
1305 RCP<row_matrix_type> LocalizedMatrix;
1309 RCP<row_matrix_type> ActiveMatrix;
1312 if (! OverlappingMatrix_.is_null ()) {
1316 LocalizedMatrix =
rcp (
new LocalFilter<row_matrix_type> (Matrix_));
1321 LocalizedMatrix.is_null (), std::logic_error,
1322 "Ifpack2::AdditiveSchwarz::setup: LocalizedMatrix is null, after the code "
1323 "that claimed to have created it. This should never be the case. Please "
1324 "report this bug to the Ifpack2 developers.");
1327 ActiveMatrix = LocalizedMatrix;
1330 if (FilterSingletons_) {
1331 SingletonMatrix_ =
rcp (
new SingletonFilter<row_matrix_type> (LocalizedMatrix));
1332 ActiveMatrix = SingletonMatrix_;
1336 if (UseReordering_) {
1337 #if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
1339 typedef ReorderFilter<row_matrix_type> reorder_filter_type;
1341 ReorderingAlgorithm_ = zlist.
get<std::string> (
"order_method",
"rcm");
1343 ArrayRCP<local_ordinal_type> perm;
1344 ArrayRCP<local_ordinal_type> revperm;
1346 if(ReorderingAlgorithm_ ==
"user") {
1353 typedef Tpetra::RowGraph
1354 <local_ordinal_type, global_ordinal_type, node_type> row_graph_type;
1355 typedef Zoltan2::TpetraRowGraphAdapter<row_graph_type> z2_adapter_type;
1356 RCP<const row_graph_type> constActiveGraph =
1357 Teuchos::rcp_const_cast<
const row_graph_type>(ActiveMatrix->getGraph());
1358 z2_adapter_type Zoltan2Graph (constActiveGraph);
1360 typedef Zoltan2::OrderingProblem<z2_adapter_type> ordering_problem_type;
1365 RCP<const MpiComm<int> > mpicomm =
1366 rcp_dynamic_cast<
const MpiComm<int> > (ActiveMatrix->getComm ());
1367 if (mpicomm == Teuchos::null) {
1368 myRawComm = MPI_COMM_SELF;
1370 myRawComm = * (mpicomm->getRawMpiComm ());
1372 ordering_problem_type MyOrderingProblem (&Zoltan2Graph, &zlist, myRawComm);
1374 ordering_problem_type MyOrderingProblem (&Zoltan2Graph, &zlist);
1376 MyOrderingProblem.solve ();
1379 typedef Zoltan2::LocalOrderingSolution<local_ordinal_type>
1380 ordering_solution_type;
1382 ordering_solution_type sol (*MyOrderingProblem.getLocalOrderingSolution());
1388 perm = sol.getPermutationRCPConst (
true);
1389 revperm = sol.getPermutationRCPConst ();
1393 ReorderedLocalizedMatrix_ =
rcp (
new reorder_filter_type (ActiveMatrix, perm, revperm));
1396 ActiveMatrix = ReorderedLocalizedMatrix_;
1401 true, std::logic_error,
"Ifpack2::AdditiveSchwarz::setup: "
1402 "The Zoltan2 and Xpetra packages must be enabled in order "
1403 "to support reordering.");
1407 innerMatrix_ = ActiveMatrix;
1410 innerMatrix_.is_null (), std::logic_error,
"Ifpack2::AdditiveSchwarz::"
1411 "setup: Inner matrix is null right before constructing inner solver. "
1412 "Please report this bug to the Ifpack2 developers.");
1415 if (Inverse_.is_null ()) {
1416 const std::string innerName = innerPrecName ();
1418 innerName ==
"INVALID", std::logic_error,
1419 "Ifpack2::AdditiveSchwarz::initialize: AdditiveSchwarz doesn't "
1420 "know how to create an instance of your LocalInverseType \""
1422 "Please talk to the Ifpack2 developers for details.");
1425 innerName ==
"CUSTOM", std::runtime_error,
"Ifpack2::AdditiveSchwarz::"
1426 "initialize: If the \"inner preconditioner name\" parameter (or any "
1427 "alias thereof) has the value \"CUSTOM\", then you must first call "
1428 "setInnerPreconditioner with a nonnull inner preconditioner input before "
1429 "you may call initialize().");
1434 Ifpack2::Details::registerLinearSolverFactory ();
1439 typedef typename MV::mag_type MT;
1440 RCP<inner_solver_type> innerPrec =
1441 Trilinos::Details::getLinearSolver<MV, OP, MT> (
"Ifpack2", innerName);
1443 innerPrec.is_null (), std::logic_error,
1444 "Ifpack2::AdditiveSchwarz::setup: Failed to create inner preconditioner "
1445 "with name \"" << innerName <<
"\".");
1446 innerPrec->setMatrix (innerMatrix_);
1450 std::pair<Teuchos::ParameterList, bool> result = innerPrecParams ();
1451 if (result.second) {
1454 innerPrec->setParameters (rcp (
new ParameterList (result.first)));
1456 Inverse_ = innerPrec;
1458 else if (Inverse_->getMatrix ().getRawPtr () != innerMatrix_.getRawPtr ()) {
1462 Inverse_->setMatrix (innerMatrix_);
1465 Inverse_.is_null (), std::logic_error,
"Ifpack2::AdditiveSchwarz::"
1466 "setup: Inverse_ is null right after we were supposed to have created it."
1467 " Please report this bug to the Ifpack2 developers.");
1477 template<
class MatrixType,
class LocalInverseType>
1481 global_ordinal_type,
1484 if (! innerPrec.is_null ()) {
1487 can_change_type* innerSolver =
dynamic_cast<can_change_type*
> (&*innerPrec);
1489 innerSolver == NULL, std::invalid_argument,
"Ifpack2::AdditiveSchwarz::"
1490 "setInnerPreconditioner: The input preconditioner does not implement the "
1491 "setMatrix() feature. Only input preconditioners that inherit from "
1492 "Ifpack2::Details::CanChangeMatrix implement this feature.");
1509 innerSolver->setMatrix (innerMatrix_);
1519 removeInnerPrecName ();
1520 removeInnerPrecParams ();
1521 List_.set (
"inner preconditioner name",
"CUSTOM");
1525 if (isInitialized ()) {
1526 innerPrec->initialize ();
1528 if (isComputed ()) {
1529 innerPrec->compute ();
1541 global_ordinal_type,
node_type> inner_solver_impl_type;
1542 Inverse_ =
Teuchos::rcp (
new inner_solver_impl_type (innerPrec,
"CUSTOM"));
1545 template<
class MatrixType,
class LocalInverseType>
1550 if (A.
getRawPtr () != Matrix_.getRawPtr ()) {
1551 IsInitialized_ =
false;
1552 IsComputed_ =
false;
1555 OverlappingMatrix_ = Teuchos::null;
1556 ReorderedLocalizedMatrix_ = Teuchos::null;
1557 innerMatrix_ = Teuchos::null;
1558 SingletonMatrix_ = Teuchos::null;
1559 localMap_ = Teuchos::null;
1560 overlapping_B_.reset (
nullptr);
1561 overlapping_Y_.reset (
nullptr);
1564 DistributedImporter_ = Teuchos::null;
1575 #define IFPACK2_ADDITIVESCHWARZ_INSTANT(S,LO,GO,N) \
1576 template class Ifpack2::AdditiveSchwarz< Tpetra::RowMatrix<S, LO, GO, N> >;
1578 #endif // IFPACK2_ADDITIVESCHWARZ_DECL_HPP
Mix-in interface for preconditioners that can change their matrix after construction.
Definition: Ifpack2_Details_CanChangeMatrix.hpp:93
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
Set the preconditioner's parameters.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:711
virtual void compute()
Computes all (coefficient) data necessary to apply the preconditioner.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1009
virtual 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, putting the result in Y.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:294
basic_OSTab< char > OSTab
virtual int getNumApply() const
Returns the number of calls to apply().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1079
T & get(const std::string &name, T def_value)
virtual bool isInitialized() const
Returns true if the preconditioner has been successfully initialized, false otherwise.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1002
virtual double getInitializeTime() const
Returns the time spent in initialize().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1086
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to an FancyOStream object.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1162
virtual Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getDomainMap() const
The domain Map of this operator.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:260
virtual double getComputeTime() const
Returns the time spent in compute().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1093
std::string description() const
Return a simple one-line description of this object.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1107
virtual std::ostream & print(std::ostream &os) const
Prints basic information on iostream. This function is used by operator<<.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1269
AdditiveSchwarz(const Teuchos::RCP< const row_matrix_type > &A)
Constructor that takes a matrix.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:245
virtual double getApplyTime() const
Returns the time spent in apply().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1100
typename MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:322
virtual void initialize()
Computes all (graph-related) data necessary to initialize the preconditioner.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:924
ParameterEntry * getEntryPtr(const std::string &name)
bool registeredSomeLinearSolverFactory(const std::string &packageName)
typename MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:319
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual void setInnerPreconditioner(const Teuchos::RCP< Preconditioner< scalar_type, local_ordinal_type, global_ordinal_type, node_type > > &innerPrec)
Set the inner preconditioner.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1479
Ifpack2's implementation of Trilinos::Details::LinearSolver interface.
Definition: Ifpack2_Details_LinearSolver_decl.hpp:105
virtual std::string description() const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Get a list of the preconditioner's default parameters.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:878
Interface for all Ifpack2 preconditioners.
Definition: Ifpack2_Preconditioner.hpp:107
virtual Teuchos::RCP< const row_matrix_type > getMatrix() const
The input matrix.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:285
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
Declaration of interface for preconditioners that can change their matrix after construction.
virtual Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRangeMap() const
The range Map of this operator.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:273
virtual void setParameters(const Teuchos::ParameterList &plist)
Set the preconditioner's parameters.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:698
virtual int getNumCompute() const
Returns the number of calls to compute().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1072
Sparse matrix (Tpetra::RowMatrix subclass) with ghost rows.
Definition: Ifpack2_OverlappingRowMatrix_decl.hpp:58
Additive Schwarz domain decomposition for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:282
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
virtual bool isComputed() const
Returns true if the preconditioner has been successfully computed, false otherwise.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1058
Access only local rows and columns of a sparse matrix.
Definition: Ifpack2_LocalFilter_decl.hpp:160
ParameterEntry & getEntry(const std::string &name)
void registerLinearSolverFactory()
Filter based on matrix entries.
Definition: Ifpack2_SingletonFilter_decl.hpp:64
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1547
void getValidParameters(Teuchos::ParameterList ¶ms)
Fills a list which contains all the parameters possibly used by Ifpack2.
Definition: Ifpack2_Parameters.cpp:51
virtual int getOverlapLevel() const
Returns the level of overlap.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1279
typename MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:313
virtual void describe(FancyOStream &out, const EVerbosityLevel verbLevel=verbLevel_default) const
virtual int getNumInitialize() const
Returns the number of calls to initialize().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1065