22#ifndef IFPACK2_ADDITIVESCHWARZ_DEF_HPP
23#define IFPACK2_ADDITIVESCHWARZ_DEF_HPP
26#include "Trilinos_Details_LinearSolverFactory.hpp"
30#include "Ifpack2_Details_LinearSolver.hpp"
31#include "Ifpack2_Details_getParamTryingTypes.hpp"
33#if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
34#include "Zoltan2_TpetraRowGraphAdapter.hpp"
35#include "Zoltan2_OrderingProblem.hpp"
36#include "Zoltan2_OrderingSolution.hpp"
40#include "Ifpack2_Parameters.hpp"
41#include "Ifpack2_LocalFilter.hpp"
42#include "Ifpack2_ReorderFilter.hpp"
43#include "Ifpack2_SingletonFilter.hpp"
44#include "Ifpack2_Details_AdditiveSchwarzFilter.hpp"
47#include "Teuchos_DefaultMpiComm.hpp"
50#include "Teuchos_StandardParameterEntryValidators.hpp"
53#include <Tpetra_BlockMultiVector.hpp>
64#ifdef HAVE_IFPACK2_DEBUG
69bool anyBad(
const MV& X) {
70 using STS = Teuchos::ScalarTraits<typename MV::scalar_type>;
71 using magnitude_type =
typename STS::magnitudeType;
72 using STM = Teuchos::ScalarTraits<magnitude_type>;
74 Teuchos::Array<magnitude_type> norms(X.getNumVectors());
77 for (
size_t j = 0; j < X.getNumVectors(); ++j) {
78 if (STM::isnaninf(norms[j])) {
92template <
class MatrixType,
class LocalInverseType>
93bool AdditiveSchwarz<MatrixType, LocalInverseType>::hasInnerPrecName()
const {
94 const char* options[4] = {
95 "inner preconditioner name",
96 "subdomain solver name",
97 "schwarz: inner preconditioner name",
98 "schwarz: subdomain solver name"};
99 const int numOptions = 4;
101 for (
int k = 0; k < numOptions && !match; ++k) {
102 if (List_.isParameter(options[k])) {
109template <
class MatrixType,
class LocalInverseType>
110void AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecName() {
111 const char* options[4] = {
112 "inner preconditioner name",
113 "subdomain solver name",
114 "schwarz: inner preconditioner name",
115 "schwarz: subdomain solver name"};
116 const int numOptions = 4;
117 for (
int k = 0; k < numOptions; ++k) {
118 List_.remove(options[k],
false);
122template <
class MatrixType,
class LocalInverseType>
124AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecName()
const {
125 const char* options[4] = {
126 "inner preconditioner name",
127 "subdomain solver name",
128 "schwarz: inner preconditioner name",
129 "schwarz: subdomain solver name"};
130 const int numOptions = 4;
135 for (
int k = 0; k < numOptions && !match; ++k) {
136 const Teuchos::ParameterEntry* paramEnt =
137 List_.getEntryPtr(options[k]);
138 if (paramEnt !=
nullptr && paramEnt->isType<std::string>()) {
139 newName = Teuchos::getValue<std::string>(*paramEnt);
143 return match ? newName : defaultInnerPrecName();
146template <
class MatrixType,
class LocalInverseType>
147void AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecParams() {
148 const char* options[4] = {
149 "inner preconditioner parameters",
150 "subdomain solver parameters",
151 "schwarz: inner preconditioner parameters",
152 "schwarz: subdomain solver parameters"};
153 const int numOptions = 4;
156 for (
int k = 0; k < numOptions; ++k) {
157 List_.remove(options[k],
false);
161template <
class MatrixType,
class LocalInverseType>
162std::pair<Teuchos::ParameterList, bool>
163AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecParams()
const {
164 const char* options[4] = {
165 "inner preconditioner parameters",
166 "subdomain solver parameters",
167 "schwarz: inner preconditioner parameters",
168 "schwarz: subdomain solver parameters"};
169 const int numOptions = 4;
170 Teuchos::ParameterList params;
174 for (
int k = 0; k < numOptions && !match; ++k) {
175 if (List_.isSublist(options[k])) {
176 params = List_.sublist(options[k]);
181 return std::make_pair(params, match);
184template <
class MatrixType,
class LocalInverseType>
186AdditiveSchwarz<MatrixType, LocalInverseType>::defaultInnerPrecName() {
192template <
class MatrixType,
class LocalInverseType>
197template <
class MatrixType,
class LocalInverseType>
200 const Teuchos::RCP<const coord_type>& coordinates)
202 , Coordinates_(coordinates) {}
204template <
class MatrixType,
class LocalInverseType>
207 const int overlapLevel)
209 , OverlapLevel_(overlapLevel) {}
211template <
class MatrixType,
class LocalInverseType>
212Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type>>
215 TEUCHOS_TEST_FOR_EXCEPTION(
216 Matrix_.is_null(), std::runtime_error,
217 "Ifpack2::AdditiveSchwarz::"
218 "getDomainMap: The matrix to precondition is null. You must either pass "
219 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
220 "input, before you may call this method.");
221 return Matrix_->getDomainMap();
224template <
class MatrixType,
class LocalInverseType>
225Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type>>
227 TEUCHOS_TEST_FOR_EXCEPTION(
228 Matrix_.is_null(), std::runtime_error,
229 "Ifpack2::AdditiveSchwarz::"
230 "getRangeMap: The matrix to precondition is null. You must either pass "
231 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
232 "input, before you may call this method.");
233 return Matrix_->getRangeMap();
236template <
class MatrixType,
class LocalInverseType>
241template <
class MatrixType,
class LocalInverseType>
242Teuchos::RCP<const Tpetra::MultiVector<typename Teuchos::ScalarTraits<typename MatrixType::scalar_type>::magnitudeType,
typename MatrixType::local_ordinal_type,
typename MatrixType::global_ordinal_type,
typename MatrixType::node_type>>
AdditiveSchwarz<MatrixType, LocalInverseType>::getCoord()
const {
248template <
class MatrixType,
class map_type>
249Teuchos::RCP<const map_type>
250pointMapFromMeshMap(
const Teuchos::RCP<const map_type>& meshMap,
const typename MatrixType::local_ordinal_type blockSize) {
251 using BMV = Tpetra::BlockMultiVector<
252 typename MatrixType::scalar_type,
253 typename MatrixType::local_ordinal_type,
254 typename MatrixType::global_ordinal_type,
255 typename MatrixType::node_type>;
257 if (blockSize == 1)
return meshMap;
259 return Teuchos::RCP<const map_type>(
new map_type(BMV::makePointMap(*meshMap, blockSize)));
262template <
typename MV,
typename Map>
263void resetMultiVecIfNeeded(std::unique_ptr<MV>& mv_ptr,
const Map& map,
const size_t numVectors,
bool initialize) {
264 if (!mv_ptr || mv_ptr->getNumVectors() != numVectors) {
265 mv_ptr.reset(
new MV(map, numVectors, initialize));
271template <
class MatrixType,
class LocalInverseType>
273 apply(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& B,
274 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
275 Teuchos::ETransp mode,
280 using Teuchos::rcp_dynamic_cast;
282 using Teuchos::TimeMonitor;
283 typedef Teuchos::ScalarTraits<scalar_type> STS;
284 const char prefix[] =
"Ifpack2::AdditiveSchwarz::apply: ";
286 TEUCHOS_TEST_FOR_EXCEPTION(!IsComputed_, std::runtime_error,
287 prefix <<
"isComputed() must be true before you may call apply().");
288 TEUCHOS_TEST_FOR_EXCEPTION(Matrix_.is_null(), std::logic_error, prefix <<
"The input matrix A is null, but the preconditioner says that it has "
289 "been computed (isComputed() is true). This should never happen, since "
290 "setMatrix() should always mark the preconditioner as not computed if "
291 "its argument is null. "
292 "Please report this bug to the Ifpack2 developers.");
293 TEUCHOS_TEST_FOR_EXCEPTION(Inverse_.is_null(), std::runtime_error,
294 prefix <<
"The subdomain solver is null. "
295 "This can only happen if you called setInnerPreconditioner() with a null "
296 "input, after calling initialize() or compute(). If you choose to call "
297 "setInnerPreconditioner() with a null input, you must then call it with "
298 "a nonnull input before you may call initialize() or compute().");
299 TEUCHOS_TEST_FOR_EXCEPTION(B.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
300 prefix <<
"B and Y must have the same number of columns. B has " << B.getNumVectors() <<
" columns, but Y has " << Y.getNumVectors() <<
".");
301 TEUCHOS_TEST_FOR_EXCEPTION(IsOverlapping_ && OverlappingMatrix_.is_null(), std::logic_error,
302 prefix <<
"The overlapping matrix is null. "
303 "This should never happen if IsOverlapping_ is true. "
304 "Please report this bug to the Ifpack2 developers.");
305 TEUCHOS_TEST_FOR_EXCEPTION(!IsOverlapping_ && localMap_.is_null(), std::logic_error,
306 prefix <<
"localMap_ is null. "
307 "This should never happen if IsOverlapping_ is false. "
308 "Please report this bug to the Ifpack2 developers.");
309 TEUCHOS_TEST_FOR_EXCEPTION(alpha != STS::one(), std::logic_error,
310 prefix <<
"Not implemented for alpha != 1.");
311 TEUCHOS_TEST_FOR_EXCEPTION(beta != STS::zero(), std::logic_error,
312 prefix <<
"Not implemented for beta != 0.");
314#ifdef HAVE_IFPACK2_DEBUG
316 const bool bad = anyBad(B);
317 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
318 "Ifpack2::AdditiveSchwarz::apply: "
319 "The 2-norm of the input B is NaN or Inf.");
323#ifdef HAVE_IFPACK2_DEBUG
324 if (!ZeroStartingSolution_) {
325 const bool bad = anyBad(Y);
326 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
327 "Ifpack2::AdditiveSchwarz::apply: "
328 "On input, the initial guess Y has 2-norm NaN or Inf "
329 "(ZeroStartingSolution_ is false).");
333 const std::string timerName(
"Ifpack2::AdditiveSchwarz::apply");
334 RCP<Time> timer = TimeMonitor::lookupCounter(timerName);
335 if (timer.is_null()) {
336 timer = TimeMonitor::getNewCounter(timerName);
338 double startTime = timer->wallTime();
341 TimeMonitor timeMon(*timer);
343 const scalar_type ZERO = Teuchos::ScalarTraits<scalar_type>::zero();
344 const size_t numVectors = B.getNumVectors();
348 if (ZeroStartingSolution_) {
353 MV* OverlappingB =
nullptr;
354 MV* OverlappingY =
nullptr;
356 RCP<const map_type> B_and_Y_map = pointMapFromMeshMap<MatrixType>(IsOverlapping_ ? OverlappingMatrix_->getRowMap() : localMap_, Matrix_->getBlockSize());
357 resetMultiVecIfNeeded(overlapping_B_, B_and_Y_map, numVectors,
false);
358 resetMultiVecIfNeeded(overlapping_Y_, B_and_Y_map, numVectors,
false);
359 OverlappingB = overlapping_B_.get();
360 OverlappingY = overlapping_Y_.get();
363 OverlappingB->putScalar(ZERO);
364 OverlappingY->putScalar(ZERO);
367 RCP<MV> globalOverlappingB;
368 if (!IsOverlapping_) {
369 auto matrixPointRowMap = pointMapFromMeshMap<MatrixType>(Matrix_->getRowMap(), Matrix_->getBlockSize());
372 OverlappingB->offsetViewNonConst(matrixPointRowMap, 0);
375 if (DistributedImporter_.is_null()) {
379 DistributedImporter_ =
380 rcp(
new import_type(matrixPointRowMap,
381 Matrix_->getDomainMap()));
385 resetMultiVecIfNeeded(R_, B.getMap(), numVectors,
false);
386 resetMultiVecIfNeeded(C_, Y.getMap(), numVectors,
false);
389 Teuchos::ArrayRCP<scalar_type> dataNumOverlapCopies;
390 if (IsOverlapping_ && AvgOverlap_) {
391 if (num_overlap_copies_.get() ==
nullptr) {
392 num_overlap_copies_.reset(
new MV(Y.getMap(), 1,
false));
393 RCP<MV> onesVec(
new MV(OverlappingMatrix_->getRowMap(), 1,
false));
394 onesVec->putScalar(Teuchos::ScalarTraits<scalar_type>::one());
395 rcp_dynamic_cast<OverlappingRowMatrix<row_matrix_type>>(OverlappingMatrix_)->exportMultiVector(*onesVec, *(num_overlap_copies_.get()), CombineMode_);
397 dataNumOverlapCopies = num_overlap_copies_.get()->getDataNonConst(0);
407 for (
int ni = 0; ni < NumIterations_; ++ni) {
408#ifdef HAVE_IFPACK2_DEBUG
410 const bool bad = anyBad(Y);
411 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
412 "Ifpack2::AdditiveSchwarz::apply: "
413 "At top of iteration "
414 << ni <<
", the 2-norm of Y is NaN or Inf.");
418 Tpetra::deep_copy(*R, B);
423 if (!ZeroStartingSolution_ || ni > 0) {
425 Matrix_->apply(Y, *R, mode, -STS::one(), STS::one());
427#ifdef HAVE_IFPACK2_DEBUG
429 const bool bad = anyBad(*R);
430 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
431 "Ifpack2::AdditiveSchwarz::apply: "
433 << ni <<
", the 2-norm of R (result of computing "
434 "residual with Y) is NaN or Inf.");
440 if (IsOverlapping_) {
441 TEUCHOS_TEST_FOR_EXCEPTION(OverlappingMatrix_.is_null(), std::logic_error, prefix <<
"IsOverlapping_ is true, but OverlappingMatrix_, while nonnull, is "
442 "not an OverlappingRowMatrix<row_matrix_type>. Please report this "
443 "bug to the Ifpack2 developers.");
444 OverlappingMatrix_->importMultiVector(*R, *OverlappingB, Tpetra::INSERT);
461#ifdef HAVE_IFPACK2_DEBUG
463 const bool bad = anyBad(*OverlappingB);
464 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
465 "Ifpack2::AdditiveSchwarz::apply: "
467 << ni <<
", result of importMultiVector from R "
468 "to OverlappingB, has 2-norm NaN or Inf.");
472 globalOverlappingB->doImport(*R, *DistributedImporter_, Tpetra::INSERT);
474#ifdef HAVE_IFPACK2_DEBUG
476 const bool bad = anyBad(*globalOverlappingB);
477 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
478 "Ifpack2::AdditiveSchwarz::apply: "
480 << ni <<
", result of doImport from R, has 2-norm "
486#ifdef HAVE_IFPACK2_DEBUG
488 const bool bad = anyBad(*OverlappingB);
489 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
490 "Ifpack2::AdditiveSchwarz::apply: "
492 << ni <<
", right before localApply, the 2-norm of "
493 "OverlappingB is NaN or Inf.");
498 localApply(*OverlappingB, *OverlappingY);
500#ifdef HAVE_IFPACK2_DEBUG
502 const bool bad = anyBad(*OverlappingY);
503 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
504 "Ifpack2::AdditiveSchwarz::apply: "
506 << ni <<
", after localApply and before export / "
507 "copy, the 2-norm of OverlappingY is NaN or Inf.");
511#ifdef HAVE_IFPACK2_DEBUG
513 const bool bad = anyBad(*C);
514 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
515 "Ifpack2::AdditiveSchwarz::apply: "
517 << ni <<
", before export / copy, the 2-norm of C "
523 if (IsOverlapping_) {
524 TEUCHOS_TEST_FOR_EXCEPTION(OverlappingMatrix_.is_null(), std::logic_error, prefix <<
"OverlappingMatrix_ is null when it shouldn't be. "
525 "Please report this bug to the Ifpack2 developers.");
526 OverlappingMatrix_->exportMultiVector(*OverlappingY, *C, CombineMode_);
530 Teuchos::ArrayRCP<scalar_type> dataC = C->getDataNonConst(0);
531 for (
int i = 0; i < (int)C->getMap()->getLocalNumElements(); i++) {
532 dataC[i] = dataC[i] / dataNumOverlapCopies[i];
542 RCP<MV> C_view = C->offsetViewNonConst(OverlappingY->getMap(), 0);
543 Tpetra::deep_copy(*C_view, *OverlappingY);
546#ifdef HAVE_IFPACK2_DEBUG
548 const bool bad = anyBad(*C);
549 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
550 "Ifpack2::AdditiveSchwarz::apply: "
552 << ni <<
", before Y := C + Y, the 2-norm of C "
557#ifdef HAVE_IFPACK2_DEBUG
559 const bool bad = anyBad(Y);
560 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
561 "Ifpack2::AdditiveSchwarz::apply: "
562 "Before Y := C + Y, at iteration "
563 << ni <<
", the 2-norm of Y "
568 Y.update(UpdateDamping_, *C, STS::one());
570#ifdef HAVE_IFPACK2_DEBUG
572 const bool bad = anyBad(Y);
573 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
574 "Ifpack2::AdditiveSchwarz::apply: "
576 << ni <<
", after Y := C + Y, the 2-norm of Y "
584#ifdef HAVE_IFPACK2_DEBUG
586 const bool bad = anyBad(Y);
587 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
588 "Ifpack2::AdditiveSchwarz::apply: "
589 "The 2-norm of the output Y is NaN or Inf.");
595 ApplyTime_ += (timer->wallTime() - startTime);
598template <
class MatrixType,
class LocalInverseType>
600 localApply(MV& OverlappingB, MV& OverlappingY)
const {
602 using Teuchos::rcp_dynamic_cast;
604 const size_t numVectors = OverlappingB.getNumVectors();
606 auto additiveSchwarzFilter = rcp_dynamic_cast<Details::AdditiveSchwarzFilter<MatrixType>>(innerMatrix_);
607 if (additiveSchwarzFilter) {
613 resetMultiVecIfNeeded(reduced_reordered_B_, additiveSchwarzFilter->getRowMap(), numVectors,
true);
614 resetMultiVecIfNeeded(reduced_reordered_Y_, additiveSchwarzFilter->getRowMap(), numVectors,
true);
615 additiveSchwarzFilter->CreateReducedProblem(OverlappingB, OverlappingY, *reduced_reordered_B_);
617 Inverse_->solve(*reduced_reordered_Y_, *reduced_reordered_B_);
619 additiveSchwarzFilter->UpdateLHS(*reduced_reordered_Y_, OverlappingY);
621 if (FilterSingletons_) {
623 resetMultiVecIfNeeded(reduced_B_, SingletonMatrix_->getRowMap(), numVectors,
true);
624 resetMultiVecIfNeeded(reduced_Y_, SingletonMatrix_->getRowMap(), numVectors,
true);
626 RCP<SingletonFilter<row_matrix_type>> singletonFilter =
627 rcp_dynamic_cast<SingletonFilter<row_matrix_type>>(SingletonMatrix_);
628 TEUCHOS_TEST_FOR_EXCEPTION(!SingletonMatrix_.is_null() && singletonFilter.is_null(),
630 "Ifpack2::AdditiveSchwarz::localApply: "
631 "SingletonFilter_ is nonnull but is not a SingletonFilter"
632 "<row_matrix_type>. This should never happen. Please report this bug "
633 "to the Ifpack2 developers.");
634 singletonFilter->SolveSingletons(OverlappingB, OverlappingY);
635 singletonFilter->CreateReducedRHS(OverlappingY, OverlappingB, *reduced_B_);
638 if (!UseReordering_) {
639 Inverse_->solve(*reduced_Y_, *reduced_B_);
641 RCP<ReorderFilter<row_matrix_type>> rf =
642 rcp_dynamic_cast<ReorderFilter<row_matrix_type>>(ReorderedLocalizedMatrix_);
643 TEUCHOS_TEST_FOR_EXCEPTION(!ReorderedLocalizedMatrix_.is_null() && rf.is_null(), std::logic_error,
644 "Ifpack2::AdditiveSchwarz::localApply: ReorderedLocalizedMatrix_ is "
645 "nonnull but is not a ReorderFilter<row_matrix_type>. This should "
646 "never happen. Please report this bug to the Ifpack2 developers.");
647 resetMultiVecIfNeeded(reordered_B_, reduced_B_->getMap(), numVectors,
false);
648 resetMultiVecIfNeeded(reordered_Y_, reduced_Y_->getMap(), numVectors,
false);
649 rf->permuteOriginalToReordered(*reduced_B_, *reordered_B_);
650 Inverse_->solve(*reordered_Y_, *reordered_B_);
651 rf->permuteReorderedToOriginal(*reordered_Y_, *reduced_Y_);
655 singletonFilter->UpdateLHS(*reduced_Y_, OverlappingY);
658 if (!UseReordering_) {
659 Inverse_->solve(OverlappingY, OverlappingB);
661 resetMultiVecIfNeeded(reordered_B_, OverlappingB.getMap(), numVectors,
false);
662 resetMultiVecIfNeeded(reordered_Y_, OverlappingY.getMap(), numVectors,
false);
664 RCP<ReorderFilter<row_matrix_type>> rf =
665 rcp_dynamic_cast<ReorderFilter<row_matrix_type>>(ReorderedLocalizedMatrix_);
666 TEUCHOS_TEST_FOR_EXCEPTION(!ReorderedLocalizedMatrix_.is_null() && rf.is_null(), std::logic_error,
667 "Ifpack2::AdditiveSchwarz::localApply: ReorderedLocalizedMatrix_ is "
668 "nonnull but is not a ReorderFilter<row_matrix_type>. This should "
669 "never happen. Please report this bug to the Ifpack2 developers.");
670 rf->permuteOriginalToReordered(OverlappingB, *reordered_B_);
671 Inverse_->solve(*reordered_Y_, *reordered_B_);
672 rf->permuteReorderedToOriginal(*reordered_Y_, OverlappingY);
678template <
class MatrixType,
class LocalInverseType>
685 this->setParameterList(Teuchos::rcpFromRef(List_));
688template <
class MatrixType,
class LocalInverseType>
691 using Details::getParamTryingTypes;
692 using Teuchos::ParameterEntry;
693 using Teuchos::ParameterEntryValidator;
694 using Teuchos::ParameterList;
697 using Teuchos::rcp_dynamic_cast;
698 using Teuchos::StringToIntegralParameterEntryValidator;
699 using Tpetra::CombineMode;
700 const char prefix[] =
"Ifpack2::AdditiveSchwarz: ";
702 if (plist.is_null()) {
705 this->setParameterList(rcp(
new ParameterList()));
711 TEUCHOS_TEST_FOR_EXCEPTION(
712 plist.is_null(), std::logic_error,
713 "Ifpack2::AdditiveSchwarz::"
714 "setParameterList: plist is null. This should never happen, since the "
715 "method should have replaced a null input list with a nonnull empty list "
716 "by this point. Please report this bug to the Ifpack2 developers.");
737 const std::string cmParamName(
"schwarz: combine mode");
738 const ParameterEntry* cmEnt = plist->getEntryPtr(cmParamName);
739 if (cmEnt !=
nullptr) {
740 if (cmEnt->isType<CombineMode>()) {
741 CombineMode_ = Teuchos::getValue<CombineMode>(*cmEnt);
742 }
else if (cmEnt->isType<
int>()) {
743 const int cm = Teuchos::getValue<int>(*cmEnt);
744 CombineMode_ =
static_cast<CombineMode
>(cm);
745 }
else if (cmEnt->isType<std::string>()) {
750 const ParameterEntry& validEntry =
752 RCP<const ParameterEntryValidator> v = validEntry.validator();
753 using vs2e_type = StringToIntegralParameterEntryValidator<CombineMode>;
754 RCP<const vs2e_type> vs2e = rcp_dynamic_cast<const vs2e_type>(v,
true);
756 ParameterEntry& inputEntry = plist->getEntry(cmParamName);
761 if (strncmp(Teuchos::getValue<std::string>(inputEntry).c_str(),
"AVG", 3) == 0) {
762 inputEntry.template setValue<std::string>(
"ADD");
765 CombineMode_ = vs2e->getIntegralValue(inputEntry, cmParamName);
772 if (plist->isParameter(
"subdomain solver name")) {
773 if (plist->get<std::string>(
"subdomain solver name") ==
"BLOCK_RELAXATION") {
774 if (plist->isSublist(
"subdomain solver parameters")) {
775 if (plist->sublist(
"subdomain solver parameters").isParameter(
"relaxation: type")) {
776 if (plist->sublist(
"subdomain solver parameters").get<std::string>(
"relaxation: type") ==
"Jacobi") {
777 if (plist->sublist(
"subdomain solver parameters").isParameter(
"partitioner: type")) {
778 if (plist->sublist(
"subdomain solver parameters").get<std::string>(
"partitioner: type") ==
"user") {
779 if (CombineMode_ == Tpetra::ADD) plist->sublist(
"subdomain solver parameters").set(
"partitioner: combine mode",
"ADD");
780 if (CombineMode_ == Tpetra::ZERO) plist->sublist(
"subdomain solver parameters").set(
"partitioner: combine mode",
"ZERO");
790 OverlapLevel_ = plist->get(
"schwarz: overlap level", OverlapLevel_);
796 UseReordering_ = plist->get(
"schwarz: use reordering", UseReordering_);
798#if !defined(HAVE_IFPACK2_XPETRA) || !defined(HAVE_IFPACK2_ZOLTAN2)
799 TEUCHOS_TEST_FOR_EXCEPTION(
800 UseReordering_, std::invalid_argument,
801 "Ifpack2::AdditiveSchwarz::"
802 "setParameters: You specified \"schwarz: use reordering\" = true. "
803 "This is only valid when Trilinos was built with Ifpack2, Xpetra, and "
804 "Zoltan2 enabled. Either Xpetra or Zoltan2 was not enabled in your build "
816 FilterSingletons_ = plist->get(
"schwarz: filter singletons", FilterSingletons_);
819 getParamTryingTypes<scalar_type, scalar_type, double>(UpdateDamping_, *plist,
"schwarz: update damping", prefix);
854 if (!Inverse_.is_null()) {
857 if (hasInnerPrecName() && innerPrecName() !=
"CUSTOM") {
860 Inverse_ = Teuchos::null;
864 std::pair<ParameterList, bool> result = innerPrecParams();
868 Inverse_->setParameters(rcp(
new ParameterList(result.first)));
873 NumIterations_ = plist->get(
"schwarz: num iterations", NumIterations_);
874 ZeroStartingSolution_ =
875 plist->get(
"schwarz: zero starting solution", ZeroStartingSolution_);
878template <
class MatrixType,
class LocalInverseType>
879Teuchos::RCP<const Teuchos::ParameterList>
882 using Teuchos::ParameterList;
883 using Teuchos::parameterList;
885 using Teuchos::rcp_const_cast;
887 if (validParams_.is_null()) {
888 const int overlapLevel = 0;
889 const bool useReordering =
false;
890 const bool filterSingletons =
false;
891 const int numIterations = 1;
892 const bool zeroStartingSolution =
true;
893 const scalar_type updateDamping = Teuchos::ScalarTraits<scalar_type>::one();
894 ParameterList reorderingSublist;
895 reorderingSublist.set(
"order_method", std::string(
"rcm"));
897 RCP<ParameterList> plist = parameterList(
"Ifpack2::AdditiveSchwarz");
899 Tpetra::setCombineModeParameter(*plist,
"schwarz: combine mode");
900 plist->set(
"schwarz: overlap level", overlapLevel);
901 plist->set(
"schwarz: use reordering", useReordering);
902 plist->set(
"schwarz: reordering list", reorderingSublist);
905 plist->set(
"schwarz: compute condest",
false);
906 plist->set(
"schwarz: filter singletons", filterSingletons);
907 plist->set(
"schwarz: num iterations", numIterations);
908 plist->set(
"schwarz: zero starting solution", zeroStartingSolution);
909 plist->set(
"schwarz: update damping", updateDamping);
919 validParams_ = rcp_const_cast<const ParameterList>(plist);
924template <
class MatrixType,
class LocalInverseType>
928 using Teuchos::SerialComm;
930 using Teuchos::TimeMonitor;
931 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);
938 double startTime = timer->wallTime();
941 TimeMonitor timeMon(*timer);
943 TEUCHOS_TEST_FOR_EXCEPTION(
944 Matrix_.is_null(), std::runtime_error,
945 "Ifpack2::AdditiveSchwarz::"
946 "initialize: The matrix to precondition is null. You must either pass "
947 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
948 "input, before you may call this method.");
950 IsInitialized_ =
false;
952 overlapping_B_.reset(
nullptr);
953 overlapping_Y_.reset(
nullptr);
956 reduced_reordered_B_.reset(
nullptr);
957 reduced_reordered_Y_.reset(
nullptr);
958 reduced_B_.reset(
nullptr);
959 reduced_Y_.reset(
nullptr);
960 reordered_B_.reset(
nullptr);
961 reordered_Y_.reset(
nullptr);
963 RCP<const Teuchos::Comm<int>> comm = Matrix_->getComm();
964 RCP<const map_type> rowMap = Matrix_->getRowMap();
965 const global_size_t INVALID =
966 Teuchos::OrdinalTraits<global_size_t>::invalid();
970 if (comm->getSize() == 1) {
972 IsOverlapping_ =
false;
973 }
else if (OverlapLevel_ != 0) {
974 IsOverlapping_ =
true;
977 if (OverlapLevel_ == 0) {
979 RCP<const SerialComm<int>> localComm(
new SerialComm<int>());
983 rcp(
new map_type(INVALID, rowMap->getLocalNumElements(),
984 indexBase, localComm));
988 if (IsOverlapping_) {
989 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"OverlappingRowMatrix construction"));
995 if (!Inverse_.is_null()) {
996 const std::string innerName = innerPrecName();
997 if ((innerName.compare(
"RILUK") == 0) && (Coordinates_ != Teuchos::null)) {
998 auto ifpack2_Inverse = Teuchos::rcp_dynamic_cast<Ifpack2::Details::LinearSolver<scalar_type, local_ordinal_type, global_ordinal_type, node_type>>(Inverse_);
999 if (!IsOverlapping_ && !UseReordering_) {
1000 ifpack2_Inverse->setCoord(Coordinates_);
1002 RCP<coord_type> tmp_Coordinates_;
1003 if (IsOverlapping_) {
1004 tmp_Coordinates_ = rcp(
new coord_type(OverlappingMatrix_->getRowMap(), Coordinates_->getNumVectors(),
false));
1005 Tpetra::Import<local_ordinal_type, global_ordinal_type, node_type> importer(Coordinates_->getMap(), tmp_Coordinates_->getMap());
1006 tmp_Coordinates_->doImport(*Coordinates_, importer, Tpetra::INSERT);
1008 tmp_Coordinates_ = rcp(
new coord_type(*Coordinates_, Teuchos::Copy));
1010 if (UseReordering_) {
1011 auto coorDevice = tmp_Coordinates_->getLocalViewDevice(Tpetra::Access::ReadWrite);
1012 auto permDevice = perm_coors.view_device();
1013 Kokkos::View<magnitude_type**, Kokkos::LayoutLeft> tmp_coor(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"tmp_coor"), coorDevice.extent(0), coorDevice.extent(1));
1014 Kokkos::parallel_for(
1015 Kokkos::RangePolicy<typename crs_matrix_type::execution_space>(0,
static_cast<int>(coorDevice.extent(0))), KOKKOS_LAMBDA(
const int& i) {
1016 for (
int j = 0; j < static_cast<int>(coorDevice.extent(1)); j++) {
1017 tmp_coor(permDevice(i), j) = coorDevice(i, j);
1020 Kokkos::deep_copy(coorDevice, tmp_coor);
1022 ifpack2_Inverse->setCoord(tmp_Coordinates_);
1025 Inverse_->symbolic();
1030 IsInitialized_ =
true;
1033 InitializeTime_ += (timer->wallTime() - startTime);
1036template <
class MatrixType,
class LocalInverseType>
1038 return IsInitialized_;
1041template <
class MatrixType,
class LocalInverseType>
1044 using Teuchos::Time;
1045 using Teuchos::TimeMonitor;
1047 if (!IsInitialized_) {
1051 TEUCHOS_TEST_FOR_EXCEPTION(
1052 !isInitialized(), std::logic_error,
1053 "Ifpack2::AdditiveSchwarz::compute: "
1054 "The preconditioner is not yet initialized, "
1055 "even though initialize() supposedly has been called. "
1056 "This should never happen. "
1057 "Please report this bug to the Ifpack2 developers.");
1059 TEUCHOS_TEST_FOR_EXCEPTION(
1060 Inverse_.is_null(), std::runtime_error,
1061 "Ifpack2::AdditiveSchwarz::compute: The subdomain solver is null. "
1062 "This can only happen if you called setInnerPreconditioner() with a null "
1063 "input, after calling initialize() or compute(). If you choose to call "
1064 "setInnerPreconditioner() with a null input, you must then call it with a "
1065 "nonnull input before you may call initialize() or compute().");
1067 const std::string timerName(
"Ifpack2::AdditiveSchwarz::compute");
1068 RCP<Time> timer = TimeMonitor::lookupCounter(timerName);
1069 if (timer.is_null()) {
1070 timer = TimeMonitor::getNewCounter(timerName);
1072 TimeMonitor timeMon(*timer);
1073 double startTime = timer->wallTime();
1077 if (IsOverlapping_) {
1078 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Halo Import"));
1079 OverlappingMatrix_->doExtImport();
1085 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Fill Local Matrix"));
1088 asf->updateMatrixValues();
1095 IsComputed_ =
false;
1096 Inverse_->numeric();
1102 ComputeTime_ += (timer->wallTime() - startTime);
1107template <
class MatrixType,
class LocalInverseType>
1112template <
class MatrixType,
class LocalInverseType>
1114 return NumInitialize_;
1117template <
class MatrixType,
class LocalInverseType>
1122template <
class MatrixType,
class LocalInverseType>
1127template <
class MatrixType,
class LocalInverseType>
1129 return InitializeTime_;
1132template <
class MatrixType,
class LocalInverseType>
1134 return ComputeTime_;
1137template <
class MatrixType,
class LocalInverseType>
1142template <
class MatrixType,
class LocalInverseType>
1144 std::ostringstream out;
1146 out <<
"\"Ifpack2::AdditiveSchwarz\": {";
1147 if (this->getObjectLabel() !=
"") {
1148 out <<
"Label: \"" << this->getObjectLabel() <<
"\", ";
1150 out <<
"Initialized: " << (isInitialized() ?
"true" :
"false")
1151 <<
", Computed: " << (isComputed() ?
"true" :
"false")
1152 <<
", Iterations: " << NumIterations_
1153 <<
", Overlap level: " << OverlapLevel_
1154 <<
", Subdomain reordering: \"" << ReorderingAlgorithm_ <<
"\"";
1155 out <<
", Combine mode: \"";
1156 if (CombineMode_ == Tpetra::INSERT) {
1158 }
else if (CombineMode_ == Tpetra::ADD) {
1160 }
else if (CombineMode_ == Tpetra::REPLACE) {
1162 }
else if (CombineMode_ == Tpetra::ABSMAX) {
1164 }
else if (CombineMode_ == Tpetra::ZERO) {
1168 if (Matrix_.is_null()) {
1169 out <<
", Matrix: null";
1171 out <<
", Global matrix dimensions: ["
1172 << Matrix_->getGlobalNumRows() <<
", "
1173 << Matrix_->getGlobalNumCols() <<
"]";
1175 out <<
", Inner solver: ";
1176 if (!Inverse_.is_null()) {
1177 Teuchos::RCP<Teuchos::Describable> inv =
1178 Teuchos::rcp_dynamic_cast<Teuchos::Describable>(Inverse_);
1179 if (!inv.is_null()) {
1180 out <<
"{" << inv->description() <<
"}";
1183 <<
"Some inner solver"
1194template <
class MatrixType,
class LocalInverseType>
1196 describe(Teuchos::FancyOStream& out,
1197 const Teuchos::EVerbosityLevel verbLevel)
const {
1199 using Teuchos::OSTab;
1200 using Teuchos::TypeNameTraits;
1202 const int myRank = Matrix_->getComm()->getRank();
1203 const int numProcs = Matrix_->getComm()->getSize();
1204 const Teuchos::EVerbosityLevel vl =
1205 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
1207 if (vl > Teuchos::VERB_NONE) {
1211 out <<
"\"Ifpack2::AdditiveSchwarz\":";
1215 out <<
"MatrixType: " << TypeNameTraits<MatrixType>::name() << endl;
1216 out <<
"LocalInverseType: " << TypeNameTraits<LocalInverseType>::name() << endl;
1217 if (this->getObjectLabel() !=
"") {
1218 out <<
"Label: \"" << this->getObjectLabel() <<
"\"" << endl;
1221 out <<
"Overlap level: " << OverlapLevel_ << endl
1222 <<
"Combine mode: \"";
1223 if (CombineMode_ == Tpetra::INSERT) {
1225 }
else if (CombineMode_ == Tpetra::ADD) {
1227 }
else if (CombineMode_ == Tpetra::REPLACE) {
1229 }
else if (CombineMode_ == Tpetra::ABSMAX) {
1231 }
else if (CombineMode_ == Tpetra::ZERO) {
1235 <<
"Subdomain reordering: \"" << ReorderingAlgorithm_ <<
"\"" << endl;
1238 if (Matrix_.is_null()) {
1240 out <<
"Matrix: null" << endl;
1244 out <<
"Matrix:" << endl;
1247 Matrix_->getComm()->barrier();
1248 Matrix_->describe(out, Teuchos::VERB_LOW);
1252 out <<
"Number of initialize calls: " << getNumInitialize() << endl
1253 <<
"Number of compute calls: " << getNumCompute() << endl
1254 <<
"Number of apply calls: " << getNumApply() << endl
1255 <<
"Total time in seconds for initialize: " << getInitializeTime() << endl
1256 <<
"Total time in seconds for compute: " << getComputeTime() << endl
1257 <<
"Total time in seconds for apply: " << getApplyTime() << endl;
1260 if (Inverse_.is_null()) {
1262 out <<
"Subdomain solver: null" << endl;
1265 if (vl < Teuchos::VERB_EXTREME) {
1267 auto ifpack2_inverse = Teuchos::rcp_dynamic_cast<Ifpack2::Details::LinearSolver<scalar_type, local_ordinal_type, global_ordinal_type, node_type>>(Inverse_);
1268 if (ifpack2_inverse.is_null())
1269 out <<
"Subdomain solver: not null" << endl;
1271 out <<
"Subdomain solver: ";
1272 ifpack2_inverse->describe(out, Teuchos::VERB_LOW);
1276 for (
int p = 0; p < numProcs; ++p) {
1278 out <<
"Subdomain solver on Process " << myRank <<
":";
1279 if (Inverse_.is_null()) {
1280 out <<
"null" << endl;
1282 Teuchos::RCP<Teuchos::Describable> inv =
1283 Teuchos::rcp_dynamic_cast<Teuchos::Describable>(Inverse_);
1284 if (!inv.is_null()) {
1286 inv->describe(out, vl);
1288 out <<
"null" << endl;
1292 Matrix_->getComm()->barrier();
1293 Matrix_->getComm()->barrier();
1294 Matrix_->getComm()->barrier();
1299 Matrix_->getComm()->barrier();
1303template <
class MatrixType,
class LocalInverseType>
1305 Teuchos::FancyOStream fos(Teuchos::rcp(&os,
false));
1306 fos.setOutputToRootOnly(0);
1311template <
class MatrixType,
class LocalInverseType>
1313 return OverlapLevel_;
1316template <
class MatrixType,
class LocalInverseType>
1319 using Teuchos::MpiComm;
1321 using Teuchos::ArrayRCP;
1322 using Teuchos::ParameterList;
1325 using Teuchos::rcp_dynamic_cast;
1326 using Teuchos::rcpFromRef;
1328 TEUCHOS_TEST_FOR_EXCEPTION(
1329 Matrix_.is_null(), std::runtime_error,
1330 "Ifpack2::AdditiveSchwarz::"
1331 "initialize: The matrix to precondition is null. You must either pass "
1332 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
1333 "input, before you may call this method.");
1337 auto matrixCrs = rcp_dynamic_cast<const crs_matrix_type>(Matrix_);
1338 if (!OverlappingMatrix_.is_null() || !matrixCrs.is_null()) {
1339 ArrayRCP<local_ordinal_type> perm;
1340 ArrayRCP<local_ordinal_type> revperm;
1341 if (UseReordering_) {
1342 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Reordering"));
1343#if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
1345 Teuchos::ParameterList zlist = List_.sublist(
"schwarz: reordering list");
1346 ReorderingAlgorithm_ = zlist.get<std::string>(
"order_method",
"rcm");
1348 if (ReorderingAlgorithm_ ==
"user") {
1350 perm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user ordering");
1351 revperm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user reverse ordering");
1354 typedef Tpetra::RowGraph<local_ordinal_type, global_ordinal_type, node_type> row_graph_type;
1355 typedef Zoltan2::TpetraRowGraphAdapter<row_graph_type> z2_adapter_type;
1356 auto constActiveGraph = Teuchos::rcp_const_cast<const row_graph_type>(
1357 IsOverlapping_ ? OverlappingMatrix_->getGraph() : Matrix_->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>>(Matrix_->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();
1395 TEUCHOS_TEST_FOR_EXCEPTION(
1396 true, std::logic_error,
1397 "Ifpack2::AdditiveSchwarz::setup: "
1398 "The Zoltan2 and Xpetra packages must be enabled in order "
1399 "to support reordering.");
1402 local_ordinal_type numLocalRows = OverlappingMatrix_.is_null() ? matrixCrs->getLocalNumRows() : OverlappingMatrix_->getLocalNumRows();
1406 perm = ArrayRCP<local_ordinal_type>(numLocalRows);
1407 revperm = ArrayRCP<local_ordinal_type>(numLocalRows);
1408 for (local_ordinal_type i = 0; i < numLocalRows; i++) {
1416 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Filter construction"));
1417 RCP<Details::AdditiveSchwarzFilter<MatrixType>> asf;
1418 if (OverlappingMatrix_.is_null())
1419 asf = rcp(
new Details::AdditiveSchwarzFilter<MatrixType>(matrixCrs, perm, revperm, FilterSingletons_));
1421 asf = rcp(
new Details::AdditiveSchwarzFilter<MatrixType>(OverlappingMatrix_, perm, revperm, FilterSingletons_));
1425 if (UseReordering_ && (Coordinates_ != Teuchos::null)) {
1426 perm_coors = perm_dualview_type(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"perm_coors"), perm.size());
1427 perm_coors.modify_host();
1428 auto permHost = perm_coors.view_host();
1429 for (local_ordinal_type i = 0; i < static_cast<local_ordinal_type>(perm.size()); i++) {
1430 permHost(i) = perm[i];
1432 perm_coors.sync_device();
1436 RCP<row_matrix_type> LocalizedMatrix;
1440 RCP<row_matrix_type> ActiveMatrix;
1443 if (!OverlappingMatrix_.is_null()) {
1444 LocalizedMatrix = rcp(
new LocalFilter<row_matrix_type>(OverlappingMatrix_));
1446 LocalizedMatrix = rcp(
new LocalFilter<row_matrix_type>(Matrix_));
1450 TEUCHOS_TEST_FOR_EXCEPTION(
1451 LocalizedMatrix.is_null(), std::logic_error,
1452 "Ifpack2::AdditiveSchwarz::setup: LocalizedMatrix is null, after the code "
1453 "that claimed to have created it. This should never be the case. Please "
1454 "report this bug to the Ifpack2 developers.");
1457 ActiveMatrix = LocalizedMatrix;
1460 if (FilterSingletons_) {
1461 SingletonMatrix_ = rcp(
new SingletonFilter<row_matrix_type>(LocalizedMatrix));
1462 ActiveMatrix = SingletonMatrix_;
1466 if (UseReordering_) {
1467#if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
1469 typedef ReorderFilter<row_matrix_type> reorder_filter_type;
1470 Teuchos::ParameterList zlist = List_.sublist(
"schwarz: reordering list");
1471 ReorderingAlgorithm_ = zlist.get<std::string>(
"order_method",
"rcm");
1473 ArrayRCP<local_ordinal_type> perm;
1474 ArrayRCP<local_ordinal_type> revperm;
1476 if (ReorderingAlgorithm_ ==
"user") {
1478 perm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user ordering");
1479 revperm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user reverse ordering");
1482 typedef Tpetra::RowGraph<local_ordinal_type, global_ordinal_type, node_type> row_graph_type;
1483 typedef Zoltan2::TpetraRowGraphAdapter<row_graph_type> z2_adapter_type;
1484 RCP<const row_graph_type> constActiveGraph =
1485 Teuchos::rcp_const_cast<const row_graph_type>(ActiveMatrix->getGraph());
1486 z2_adapter_type Zoltan2Graph(constActiveGraph);
1488 typedef Zoltan2::OrderingProblem<z2_adapter_type> ordering_problem_type;
1493 RCP<const MpiComm<int>> mpicomm =
1494 rcp_dynamic_cast<const MpiComm<int>>(ActiveMatrix->getComm());
1495 if (mpicomm == Teuchos::null) {
1496 myRawComm = MPI_COMM_SELF;
1498 myRawComm = *(mpicomm->getRawMpiComm());
1500 ordering_problem_type MyOrderingProblem(&Zoltan2Graph, &zlist, myRawComm);
1502 ordering_problem_type MyOrderingProblem(&Zoltan2Graph, &zlist);
1504 MyOrderingProblem.solve();
1507 typedef Zoltan2::LocalOrderingSolution<local_ordinal_type>
1508 ordering_solution_type;
1510 ordering_solution_type sol(*MyOrderingProblem.getLocalOrderingSolution());
1516 perm = sol.getPermutationRCPConst(
true);
1517 revperm = sol.getPermutationRCPConst();
1521 ReorderedLocalizedMatrix_ = rcp(
new reorder_filter_type(ActiveMatrix, perm, revperm));
1523 ActiveMatrix = ReorderedLocalizedMatrix_;
1527 TEUCHOS_TEST_FOR_EXCEPTION(
1528 true, std::logic_error,
1529 "Ifpack2::AdditiveSchwarz::setup: "
1530 "The Zoltan2 and Xpetra packages must be enabled in order "
1531 "to support reordering.");
1534 innerMatrix_ = ActiveMatrix;
1537 TEUCHOS_TEST_FOR_EXCEPTION(
1538 innerMatrix_.is_null(), std::logic_error,
1539 "Ifpack2::AdditiveSchwarz::"
1540 "setup: Inner matrix is null right before constructing inner solver. "
1541 "Please report this bug to the Ifpack2 developers.");
1544 if (Inverse_.is_null()) {
1545 const std::string innerName = innerPrecName();
1546 TEUCHOS_TEST_FOR_EXCEPTION(
1547 innerName ==
"INVALID", std::logic_error,
1548 "Ifpack2::AdditiveSchwarz::initialize: AdditiveSchwarz doesn't "
1549 "know how to create an instance of your LocalInverseType \""
1550 << Teuchos::TypeNameTraits<LocalInverseType>::name() <<
"\". "
1551 "Please talk to the Ifpack2 developers for details.");
1553 TEUCHOS_TEST_FOR_EXCEPTION(
1554 innerName ==
"CUSTOM", std::runtime_error,
1555 "Ifpack2::AdditiveSchwarz::"
1556 "initialize: If the \"inner preconditioner name\" parameter (or any "
1557 "alias thereof) has the value \"CUSTOM\", then you must first call "
1558 "setInnerPreconditioner with a nonnull inner preconditioner input before "
1559 "you may call initialize().");
1563 if (!Trilinos::Details::Impl::registeredSomeLinearSolverFactory(
"Ifpack2")) {
1569 typedef typename MV::mag_type MT;
1570 RCP<inner_solver_type> innerPrec =
1571 Trilinos::Details::getLinearSolver<MV, OP, MT>(
"Ifpack2", innerName);
1572 TEUCHOS_TEST_FOR_EXCEPTION(
1573 innerPrec.is_null(), std::logic_error,
1574 "Ifpack2::AdditiveSchwarz::setup: Failed to create inner preconditioner "
1576 << innerName <<
"\".");
1577 innerPrec->setMatrix(innerMatrix_);
1581 std::pair<Teuchos::ParameterList, bool> result = innerPrecParams();
1582 if (result.second) {
1585 innerPrec->setParameters(rcp(
new ParameterList(result.first)));
1587 Inverse_ = innerPrec;
1588 }
else if (Inverse_->getMatrix().getRawPtr() != innerMatrix_.getRawPtr()) {
1592 Inverse_->setMatrix(innerMatrix_);
1594 TEUCHOS_TEST_FOR_EXCEPTION(
1595 Inverse_.is_null(), std::logic_error,
1596 "Ifpack2::AdditiveSchwarz::"
1597 "setup: Inverse_ is null right after we were supposed to have created it."
1598 " Please report this bug to the Ifpack2 developers.");
1607template <
class MatrixType,
class LocalInverseType>
1613 if (!innerPrec.is_null()) {
1616 can_change_type* innerSolver =
dynamic_cast<can_change_type*
>(&*innerPrec);
1617 TEUCHOS_TEST_FOR_EXCEPTION(
1618 innerSolver == NULL, std::invalid_argument,
1619 "Ifpack2::AdditiveSchwarz::"
1620 "setInnerPreconditioner: The input preconditioner does not implement the "
1621 "setMatrix() feature. Only input preconditioners that inherit from "
1622 "Ifpack2::Details::CanChangeMatrix implement this feature.");
1640 innerSolver->setMatrix(asf->getFilteredMatrix());
1642 innerSolver->setMatrix(innerMatrix_);
1652 removeInnerPrecName();
1653 removeInnerPrecParams();
1654 List_.set(
"inner preconditioner name",
"CUSTOM");
1658 if (isInitialized()) {
1659 innerPrec->initialize();
1662 innerPrec->compute();
1675 inner_solver_impl_type;
1676 Inverse_ = Teuchos::rcp(
new inner_solver_impl_type(innerPrec,
"CUSTOM"));
1679template <
class MatrixType,
class LocalInverseType>
1681 setMatrix(
const Teuchos::RCP<const row_matrix_type>& A) {
1683 if (A.getRawPtr() != Matrix_.getRawPtr()) {
1684 IsInitialized_ =
false;
1685 IsComputed_ =
false;
1688 OverlappingMatrix_ = Teuchos::null;
1689 ReorderedLocalizedMatrix_ = Teuchos::null;
1690 innerMatrix_ = Teuchos::null;
1691 SingletonMatrix_ = Teuchos::null;
1692 localMap_ = Teuchos::null;
1693 overlapping_B_.reset(
nullptr);
1694 overlapping_Y_.reset(
nullptr);
1697 DistributedImporter_ = Teuchos::null;
1703template <
class MatrixType,
class LocalInverseType>
1705 setCoord(
const Teuchos::RCP<const coord_type>& Coordinates) {
1707 if (Coordinates.getRawPtr() != Coordinates_.getRawPtr()) {
1708 Coordinates_ = Coordinates;
1717#define IFPACK2_ADDITIVESCHWARZ_INSTANT(S, LO, GO, N) \
1718 template class Ifpack2::AdditiveSchwarz<Tpetra::RowMatrix<S, LO, GO, N>>;
Declaration of Ifpack2::AdditiveSchwarz, which implements additive Schwarz preconditioning with an ar...
void registerLinearSolverFactory()
Register Ifpack2's LinearSolverFactory with the central repository, for all enabled combinations of t...
Definition Ifpack2_Details_registerLinearSolverFactory.cpp:33
Declaration of interface for preconditioners that can change their matrix after construction.
Additive Schwarz domain decomposition for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:260
typename MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:283
std::string description() const
Return a simple one-line description of this object.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1143
virtual bool isInitialized() const
Returns true if the preconditioner has been successfully initialized, false otherwise.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1037
void setCoord(const Teuchos::RCP< const coord_type > &Coordinates)
Set the matrix rows' coordinates.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1705
virtual int getOverlapLevel() const
Returns the level of overlap.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1312
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Get a list of the preconditioner's default parameters.
Definition Ifpack2_AdditiveSchwarz_def.hpp:881
typename MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:286
virtual int getNumCompute() const
Returns the number of calls to compute().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1118
Teuchos::RCP< const coord_type > getCoord() const
Get the coordinates associated with the input matrix's rows.
Definition Ifpack2_AdditiveSchwarz_def.hpp:242
virtual int getNumApply() const
Returns the number of calls to apply().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1123
virtual double getComputeTime() const
Returns the time spent in compute().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1133
virtual double getApplyTime() const
Returns the time spent in apply().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1138
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1681
typename MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:289
virtual void initialize()
Computes all (graph-related) data necessary to initialize the preconditioner.
Definition Ifpack2_AdditiveSchwarz_def.hpp:925
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
Set the preconditioner's parameters.
Definition Ifpack2_AdditiveSchwarz_def.hpp:690
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:1609
virtual double getInitializeTime() const
Returns the time spent in initialize().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1128
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:226
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:214
virtual void compute()
Computes all (coefficient) data necessary to apply the preconditioner.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1042
Tpetra::MultiVector< magnitude_type, local_ordinal_type, global_ordinal_type, node_type > coord_type
The Tpetra::MultiVector specialization used for containing coordinates.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:308
virtual std::ostream & print(std::ostream &os) const
Prints basic information on iostream. This function is used by operator<<.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1304
typename MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:280
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:1196
virtual void setParameters(const Teuchos::ParameterList &plist)
Set the preconditioner's parameters.
Definition Ifpack2_AdditiveSchwarz_def.hpp:680
virtual Teuchos::RCP< const row_matrix_type > getMatrix() const
The input matrix.
Definition Ifpack2_AdditiveSchwarz_def.hpp:237
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:273
virtual bool isComputed() const
Returns true if the preconditioner has been successfully computed, false otherwise.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1108
virtual int getNumInitialize() const
Returns the number of calls to initialize().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1113
AdditiveSchwarz(const Teuchos::RCP< const row_matrix_type > &A)
Constructor that takes a matrix.
Definition Ifpack2_AdditiveSchwarz_def.hpp:194
Ifpack2's implementation of Trilinos::Details::LinearSolver interface.
Definition Ifpack2_Details_LinearSolver_decl.hpp:75
Sparse matrix (Tpetra::RowMatrix subclass) with ghost rows.
Definition Ifpack2_OverlappingRowMatrix_decl.hpp:25
Interface for all Ifpack2 preconditioners.
Definition Ifpack2_Preconditioner.hpp:74
void registerLinearSolverFactory()
Ifpack2 implementation details.
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:40
void getValidParameters(Teuchos::ParameterList ¶ms)
Fills a list which contains all the parameters possibly used by Ifpack2.
Definition Ifpack2_Parameters.cpp:18