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"
48#include "Teuchos_DefaultMpiComm.hpp"
51#include "Teuchos_StandardParameterEntryValidators.hpp"
57#include <Tpetra_BlockMultiVector.hpp>
71bool anyBad(
const MV& X) {
72 using STS = Teuchos::ScalarTraits<typename MV::scalar_type>;
73 using magnitude_type =
typename STS::magnitudeType;
74 using STM = Teuchos::ScalarTraits<magnitude_type>;
76 Teuchos::Array<magnitude_type> norms(X.getNumVectors());
79 for (
size_t j = 0; j < X.getNumVectors(); ++j) {
80 if (STM::isnaninf(norms[j])) {
88template <
class RowMatrixType>
89void writeLocalMatrixMarketPerRank(
const Teuchos::RCP<RowMatrixType>& A_local,
91 const std::string& basePath) {
92 typedef typename RowMatrixType::local_ordinal_type local_ordinal_type;
93 typedef typename RowMatrixType::scalar_type scalar_type;
94 typedef typename RowMatrixType::nonconst_local_inds_host_view_type nonconst_local_inds_host_view_type;
95 typedef typename RowMatrixType::nonconst_values_host_view_type nonconst_values_host_view_type;
96 typedef Teuchos::ScalarTraits<scalar_type> STS;
98 std::ostringstream fname;
99 fname << basePath <<
".rank_" << rank <<
".mtx";
101 std::ofstream out(fname.str().c_str());
102 TEUCHOS_TEST_FOR_EXCEPTION(
103 !out.is_open(), std::runtime_error,
104 "Ifpack2::AdditiveSchwarz: Failed to open debug MatrixMarket file \""
105 << fname.str() <<
"\".");
107 const auto numRows = A_local->getLocalNumRows();
108 const auto numCols = A_local->getLocalNumCols();
109 const auto nnz = A_local->getLocalNumEntries();
111 if (STS::isComplex) {
112 out <<
"%%MatrixMarket matrix coordinate complex general\n";
114 out <<
"%%MatrixMarket matrix coordinate real general\n";
116 out << numRows <<
" " << numCols <<
" " << nnz <<
"\n";
118 nonconst_local_inds_host_view_type indices(
"indices", A_local->getLocalMaxNumRowEntries());
119 nonconst_values_host_view_type values(
"values", A_local->getLocalMaxNumRowEntries());
121 for (local_ordinal_type i = 0; i < static_cast<local_ordinal_type>(numRows); ++i) {
122 size_t numEntries = 0;
123 A_local->getLocalRowCopy(i, indices, values, numEntries);
124 for (
size_t k = 0; k < numEntries; ++k) {
125 out << (i + 1) <<
" " << (indices[k] + 1);
126 if (STS::isComplex) {
127 out <<
" " << STS::real(values[k]) <<
" " << STS::imag(values[k]) <<
"\n";
129 out <<
" " << values[k] <<
"\n";
139template <
class MatrixType,
class LocalInverseType>
140bool AdditiveSchwarz<MatrixType, LocalInverseType>::hasInnerPrecName()
const {
141 const char* options[4] = {
142 "inner preconditioner name",
143 "subdomain solver name",
144 "schwarz: inner preconditioner name",
145 "schwarz: subdomain solver name"};
146 const int numOptions = 4;
148 for (
int k = 0; k < numOptions && !match; ++k) {
149 if (List_.isParameter(options[k])) {
156template <
class MatrixType,
class LocalInverseType>
157void AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecName() {
158 const char* options[4] = {
159 "inner preconditioner name",
160 "subdomain solver name",
161 "schwarz: inner preconditioner name",
162 "schwarz: subdomain solver name"};
163 const int numOptions = 4;
164 for (
int k = 0; k < numOptions; ++k) {
165 List_.remove(options[k],
false);
169template <
class MatrixType,
class LocalInverseType>
171AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecName()
const {
172 const char* options[4] = {
173 "inner preconditioner name",
174 "subdomain solver name",
175 "schwarz: inner preconditioner name",
176 "schwarz: subdomain solver name"};
177 const int numOptions = 4;
182 for (
int k = 0; k < numOptions && !match; ++k) {
183 const Teuchos::ParameterEntry* paramEnt =
184 List_.getEntryPtr(options[k]);
185 if (paramEnt !=
nullptr && paramEnt->isType<std::string>()) {
186 newName = Teuchos::getValue<std::string>(*paramEnt);
190 return match ? newName : defaultInnerPrecName();
193template <
class MatrixType,
class LocalInverseType>
194void AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecParams() {
195 const char* options[4] = {
196 "inner preconditioner parameters",
197 "subdomain solver parameters",
198 "schwarz: inner preconditioner parameters",
199 "schwarz: subdomain solver parameters"};
200 const int numOptions = 4;
203 for (
int k = 0; k < numOptions; ++k) {
204 List_.remove(options[k],
false);
208template <
class MatrixType,
class LocalInverseType>
209std::pair<Teuchos::ParameterList, bool>
210AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecParams()
const {
211 const char* options[4] = {
212 "inner preconditioner parameters",
213 "subdomain solver parameters",
214 "schwarz: inner preconditioner parameters",
215 "schwarz: subdomain solver parameters"};
216 const int numOptions = 4;
217 Teuchos::ParameterList params;
221 for (
int k = 0; k < numOptions && !match; ++k) {
222 if (List_.isSublist(options[k])) {
223 params = List_.sublist(options[k]);
228 return std::make_pair(params, match);
231template <
class MatrixType,
class LocalInverseType>
233AdditiveSchwarz<MatrixType, LocalInverseType>::defaultInnerPrecName() {
239template <
class MatrixType,
class LocalInverseType>
244template <
class MatrixType,
class LocalInverseType>
247 const Teuchos::RCP<const coord_type>& coordinates)
249 , Coordinates_(coordinates) {}
251template <
class MatrixType,
class LocalInverseType>
254 const int overlapLevel)
256 , OverlapLevel_(overlapLevel) {}
258template <
class MatrixType,
class LocalInverseType>
259Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type>>
262 TEUCHOS_TEST_FOR_EXCEPTION(
263 Matrix_.is_null(), std::runtime_error,
264 "Ifpack2::AdditiveSchwarz::"
265 "getDomainMap: The matrix to precondition is null. You must either pass "
266 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
267 "input, before you may call this method.");
268 return Matrix_->getDomainMap();
271template <
class MatrixType,
class LocalInverseType>
272Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type>>
274 TEUCHOS_TEST_FOR_EXCEPTION(
275 Matrix_.is_null(), std::runtime_error,
276 "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();
283template <
class MatrixType,
class LocalInverseType>
288template <
class MatrixType,
class LocalInverseType>
289Teuchos::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 {
295template <
class MatrixType,
class map_type>
296Teuchos::RCP<const map_type>
297pointMapFromMeshMap(
const Teuchos::RCP<const map_type>& meshMap,
const typename MatrixType::local_ordinal_type blockSize) {
298 using BMV = Tpetra::BlockMultiVector<
299 typename MatrixType::scalar_type,
300 typename MatrixType::local_ordinal_type,
301 typename MatrixType::global_ordinal_type,
302 typename MatrixType::node_type>;
304 if (blockSize == 1)
return meshMap;
306 return Teuchos::RCP<const map_type>(
new map_type(BMV::makePointMap(*meshMap, blockSize)));
309template <
typename MV,
typename Map>
310void resetMultiVecIfNeeded(std::unique_ptr<MV>& mv_ptr,
const Map& map,
const size_t numVectors,
bool initialize) {
311 if (!mv_ptr || mv_ptr->getNumVectors() != numVectors) {
312 mv_ptr.reset(
new MV(map, numVectors, initialize));
318template <
class MatrixType,
class LocalInverseType>
320 apply(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& B,
321 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
322 Teuchos::ETransp mode,
327 using Teuchos::rcp_dynamic_cast;
329 using Teuchos::TimeMonitor;
330 typedef Teuchos::ScalarTraits<scalar_type> STS;
331 const char prefix[] =
"Ifpack2::AdditiveSchwarz::apply: ";
333 TEUCHOS_TEST_FOR_EXCEPTION(!IsComputed_, std::runtime_error,
334 prefix <<
"isComputed() must be true before you may call apply().");
335 TEUCHOS_TEST_FOR_EXCEPTION(Matrix_.is_null(), std::logic_error, prefix <<
"The input matrix A is null, but the preconditioner says that it has "
336 "been computed (isComputed() is true). This should never happen, since "
337 "setMatrix() should always mark the preconditioner as not computed if "
338 "its argument is null. "
339 "Please report this bug to the Ifpack2 developers.");
340 TEUCHOS_TEST_FOR_EXCEPTION(Inverse_.is_null(), std::runtime_error,
341 prefix <<
"The subdomain solver is null. "
342 "This can only happen if you called setInnerPreconditioner() with a null "
343 "input, after calling initialize() or compute(). If you choose to call "
344 "setInnerPreconditioner() with a null input, you must then call it with "
345 "a nonnull input before you may call initialize() or compute().");
346 TEUCHOS_TEST_FOR_EXCEPTION(B.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
347 prefix <<
"B and Y must have the same number of columns. B has " << B.getNumVectors() <<
" columns, but Y has " << Y.getNumVectors() <<
".");
348 TEUCHOS_TEST_FOR_EXCEPTION(IsOverlapping_ && OverlappingMatrix_.is_null(), std::logic_error,
349 prefix <<
"The overlapping matrix is null. "
350 "This should never happen if IsOverlapping_ is true. "
351 "Please report this bug to the Ifpack2 developers.");
352 TEUCHOS_TEST_FOR_EXCEPTION(!IsOverlapping_ && localMap_.is_null(), std::logic_error,
353 prefix <<
"localMap_ is null. "
354 "This should never happen if IsOverlapping_ is false. "
355 "Please report this bug to the Ifpack2 developers.");
356 TEUCHOS_TEST_FOR_EXCEPTION(alpha != STS::one(), std::logic_error,
357 prefix <<
"Not implemented for alpha != 1.");
358 TEUCHOS_TEST_FOR_EXCEPTION(beta != STS::zero(), std::logic_error,
359 prefix <<
"Not implemented for beta != 0.");
362 const bool bad = anyBad(B);
363 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
364 "Ifpack2::AdditiveSchwarz::apply: "
365 "The 2-norm of the input B is NaN or Inf.");
369 if (!ZeroStartingSolution_) {
370 const bool bad = anyBad(Y);
371 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
372 "Ifpack2::AdditiveSchwarz::apply: "
373 "On input, the initial guess Y has 2-norm NaN or Inf "
374 "(ZeroStartingSolution_ is false).");
378 const std::string timerName(
"Ifpack2::AdditiveSchwarz::apply");
379 RCP<Time> timer = TimeMonitor::lookupCounter(timerName);
380 if (timer.is_null()) {
381 timer = TimeMonitor::getNewCounter(timerName);
383 double startTime = timer->wallTime();
386 TimeMonitor timeMon(*timer);
388 const scalar_type ZERO = Teuchos::ScalarTraits<scalar_type>::zero();
389 const size_t numVectors = B.getNumVectors();
393 if (ZeroStartingSolution_) {
398 MV* OverlappingB =
nullptr;
399 MV* OverlappingY =
nullptr;
401 RCP<const map_type> B_and_Y_map = pointMapFromMeshMap<MatrixType>(IsOverlapping_ ? OverlappingMatrix_->getRowMap() : localMap_, Matrix_->getBlockSize());
402 resetMultiVecIfNeeded(overlapping_B_, B_and_Y_map, numVectors,
false);
403 resetMultiVecIfNeeded(overlapping_Y_, B_and_Y_map, numVectors,
false);
404 OverlappingB = overlapping_B_.get();
405 OverlappingY = overlapping_Y_.get();
408 OverlappingB->putScalar(ZERO);
409 OverlappingY->putScalar(ZERO);
412 RCP<MV> globalOverlappingB;
413 if (!IsOverlapping_) {
414 auto matrixPointRowMap = pointMapFromMeshMap<MatrixType>(Matrix_->getRowMap(), Matrix_->getBlockSize());
417 OverlappingB->offsetViewNonConst(matrixPointRowMap, 0);
420 if (DistributedImporter_.is_null()) {
424 DistributedImporter_ =
425 rcp(
new import_type(matrixPointRowMap,
426 Matrix_->getDomainMap()));
430 resetMultiVecIfNeeded(R_, B.getMap(), numVectors,
false);
431 resetMultiVecIfNeeded(C_, Y.getMap(), numVectors,
false);
434 Teuchos::ArrayRCP<scalar_type> dataNumOverlapCopies;
435 if (IsOverlapping_ && AvgOverlap_) {
436 if (num_overlap_copies_.get() ==
nullptr) {
437 num_overlap_copies_.reset(
new MV(Y.getMap(), 1,
false));
438 RCP<MV> onesVec(
new MV(OverlappingMatrix_->getRowMap(), 1,
false));
439 onesVec->putScalar(Teuchos::ScalarTraits<scalar_type>::one());
440 rcp_dynamic_cast<OverlappingRowMatrix<row_matrix_type>>(OverlappingMatrix_)->exportMultiVector(*onesVec, *(num_overlap_copies_.get()), CombineMode_);
442 dataNumOverlapCopies = num_overlap_copies_.get()->getDataNonConst(0);
452 for (
int ni = 0; ni < NumIterations_; ++ni) {
454 const bool bad = anyBad(Y);
455 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
456 "Ifpack2::AdditiveSchwarz::apply: "
457 "At top of iteration "
458 << ni <<
", the 2-norm of Y is NaN or Inf.");
461 Tpetra::deep_copy(*R, B);
466 if (!ZeroStartingSolution_ || ni > 0) {
468 Matrix_->apply(Y, *R, mode, -STS::one(), STS::one());
471 const bool bad = anyBad(*R);
472 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
473 "Ifpack2::AdditiveSchwarz::apply: "
475 << ni <<
", the 2-norm of R (result of computing "
476 "residual with Y) is NaN or Inf.");
481 if (IsOverlapping_) {
482 TEUCHOS_TEST_FOR_EXCEPTION(OverlappingMatrix_.is_null(), std::logic_error, prefix <<
"IsOverlapping_ is true, but OverlappingMatrix_, while nonnull, is "
483 "not an OverlappingRowMatrix<row_matrix_type>. Please report this "
484 "bug to the Ifpack2 developers.");
485 OverlappingMatrix_->importMultiVector(*R, *OverlappingB, Tpetra::INSERT);
503 const bool bad = anyBad(*OverlappingB);
504 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
505 "Ifpack2::AdditiveSchwarz::apply: "
507 << ni <<
", result of importMultiVector from R "
508 "to OverlappingB, has 2-norm NaN or Inf.");
511 globalOverlappingB->doImport(*R, *DistributedImporter_, Tpetra::INSERT);
514 const bool bad = anyBad(*globalOverlappingB);
515 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
516 "Ifpack2::AdditiveSchwarz::apply: "
518 << ni <<
", result of doImport from R, has 2-norm "
524 const bool bad = anyBad(*OverlappingB);
525 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
526 "Ifpack2::AdditiveSchwarz::apply: "
528 << ni <<
", right before localApply, the 2-norm of "
529 "OverlappingB is NaN or Inf.");
533 localApply(*OverlappingB, *OverlappingY);
536 const bool bad = anyBad(*OverlappingY);
537 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
538 "Ifpack2::AdditiveSchwarz::apply: "
540 << ni <<
", after localApply and before export / "
541 "copy, the 2-norm of OverlappingY is NaN or Inf.");
545 const bool bad = anyBad(*C);
546 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
547 "Ifpack2::AdditiveSchwarz::apply: "
549 << ni <<
", before export / copy, the 2-norm of C "
554 if (IsOverlapping_) {
555 TEUCHOS_TEST_FOR_EXCEPTION(OverlappingMatrix_.is_null(), std::logic_error, prefix <<
"OverlappingMatrix_ is null when it shouldn't be. "
556 "Please report this bug to the Ifpack2 developers.");
557 OverlappingMatrix_->exportMultiVector(*OverlappingY, *C, CombineMode_);
561 Teuchos::ArrayRCP<scalar_type> dataC = C->getDataNonConst(0);
562 for (
int i = 0; i < (int)C->getMap()->getLocalNumElements(); i++) {
563 dataC[i] = dataC[i] / dataNumOverlapCopies[i];
573 RCP<MV> C_view = C->offsetViewNonConst(OverlappingY->getMap(), 0);
574 Tpetra::deep_copy(*C_view, *OverlappingY);
578 const bool bad = anyBad(*C);
579 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
580 "Ifpack2::AdditiveSchwarz::apply: "
582 << ni <<
", before Y := C + Y, the 2-norm of C "
587 const bool bad = anyBad(Y);
588 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
589 "Ifpack2::AdditiveSchwarz::apply: "
590 "Before Y := C + Y, at iteration "
591 << ni <<
", the 2-norm of Y "
595 Y.update(UpdateDamping_, *C, STS::one());
598 const bool bad = anyBad(Y);
599 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
600 "Ifpack2::AdditiveSchwarz::apply: "
602 << ni <<
", after Y := C + Y, the 2-norm of Y "
610 const bool bad = anyBad(Y);
611 TEUCHOS_TEST_FOR_EXCEPTION(bad, std::runtime_error,
612 "Ifpack2::AdditiveSchwarz::apply: "
613 "The 2-norm of the output Y is NaN or Inf.");
618 ApplyTime_ += (timer->wallTime() - startTime);
621template <
class MatrixType,
class LocalInverseType>
623 localApply(MV& OverlappingB, MV& OverlappingY)
const {
625 using Teuchos::rcp_dynamic_cast;
627 const size_t numVectors = OverlappingB.getNumVectors();
629 auto additiveSchwarzFilter = rcp_dynamic_cast<Details::AdditiveSchwarzFilter<MatrixType>>(innerMatrix_);
630 if (additiveSchwarzFilter) {
636 resetMultiVecIfNeeded(reduced_reordered_B_, additiveSchwarzFilter->getRowMap(), numVectors,
true);
637 resetMultiVecIfNeeded(reduced_reordered_Y_, additiveSchwarzFilter->getRowMap(), numVectors,
true);
638 additiveSchwarzFilter->CreateReducedProblem(OverlappingB, OverlappingY, *reduced_reordered_B_);
640 Inverse_->solve(*reduced_reordered_Y_, *reduced_reordered_B_);
642 additiveSchwarzFilter->UpdateLHS(*reduced_reordered_Y_, OverlappingY);
644 if (FilterSingletons_) {
646 resetMultiVecIfNeeded(reduced_B_, SingletonMatrix_->getRowMap(), numVectors,
true);
647 resetMultiVecIfNeeded(reduced_Y_, SingletonMatrix_->getRowMap(), numVectors,
true);
649 RCP<SingletonFilter<row_matrix_type>> singletonFilter =
650 rcp_dynamic_cast<SingletonFilter<row_matrix_type>>(SingletonMatrix_);
651 TEUCHOS_TEST_FOR_EXCEPTION(!SingletonMatrix_.is_null() && singletonFilter.is_null(),
653 "Ifpack2::AdditiveSchwarz::localApply: "
654 "SingletonFilter_ is nonnull but is not a SingletonFilter"
655 "<row_matrix_type>. This should never happen. Please report this bug "
656 "to the Ifpack2 developers.");
657 singletonFilter->SolveSingletons(OverlappingB, OverlappingY);
658 singletonFilter->CreateReducedRHS(OverlappingY, OverlappingB, *reduced_B_);
661 if (!UseReordering_) {
662 Inverse_->solve(*reduced_Y_, *reduced_B_);
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 resetMultiVecIfNeeded(reordered_B_, reduced_B_->getMap(), numVectors,
false);
671 resetMultiVecIfNeeded(reordered_Y_, reduced_Y_->getMap(), numVectors,
false);
672 rf->permuteOriginalToReordered(*reduced_B_, *reordered_B_);
673 Inverse_->solve(*reordered_Y_, *reordered_B_);
674 rf->permuteReorderedToOriginal(*reordered_Y_, *reduced_Y_);
678 singletonFilter->UpdateLHS(*reduced_Y_, OverlappingY);
681 if (!UseReordering_) {
682 Inverse_->solve(OverlappingY, OverlappingB);
684 resetMultiVecIfNeeded(reordered_B_, OverlappingB.getMap(), numVectors,
false);
685 resetMultiVecIfNeeded(reordered_Y_, OverlappingY.getMap(), numVectors,
false);
687 RCP<ReorderFilter<row_matrix_type>> rf =
688 rcp_dynamic_cast<ReorderFilter<row_matrix_type>>(ReorderedLocalizedMatrix_);
689 TEUCHOS_TEST_FOR_EXCEPTION(!ReorderedLocalizedMatrix_.is_null() && rf.is_null(), std::logic_error,
690 "Ifpack2::AdditiveSchwarz::localApply: ReorderedLocalizedMatrix_ is "
691 "nonnull but is not a ReorderFilter<row_matrix_type>. This should "
692 "never happen. Please report this bug to the Ifpack2 developers.");
693 rf->permuteOriginalToReordered(OverlappingB, *reordered_B_);
694 Inverse_->solve(*reordered_Y_, *reordered_B_);
695 rf->permuteReorderedToOriginal(*reordered_Y_, OverlappingY);
701template <
class MatrixType,
class LocalInverseType>
708 this->setParameterList(Teuchos::rcpFromRef(List_));
711template <
class MatrixType,
class LocalInverseType>
714 using Details::getParamTryingTypes;
715 using Teuchos::ParameterEntry;
716 using Teuchos::ParameterEntryValidator;
717 using Teuchos::ParameterList;
720 using Teuchos::rcp_dynamic_cast;
721 using Teuchos::StringToIntegralParameterEntryValidator;
722 using Tpetra::CombineMode;
723 const char prefix[] =
"Ifpack2::AdditiveSchwarz: ";
725 if (plist.is_null()) {
728 this->setParameterList(rcp(
new ParameterList()));
734 TEUCHOS_TEST_FOR_EXCEPTION(
735 plist.is_null(), std::logic_error,
736 "Ifpack2::AdditiveSchwarz::"
737 "setParameterList: plist is null. This should never happen, since the "
738 "method should have replaced a null input list with a nonnull empty list "
739 "by this point. Please report this bug to the Ifpack2 developers.");
760 const std::string cmParamName(
"schwarz: combine mode");
761 const ParameterEntry* cmEnt = plist->getEntryPtr(cmParamName);
762 if (cmEnt !=
nullptr) {
763 if (cmEnt->isType<CombineMode>()) {
764 CombineMode_ = Teuchos::getValue<CombineMode>(*cmEnt);
765 }
else if (cmEnt->isType<
int>()) {
766 const int cm = Teuchos::getValue<int>(*cmEnt);
767 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 ParameterEntry& inputEntry = plist->getEntry(cmParamName);
784 if (strncmp(Teuchos::getValue<std::string>(inputEntry).c_str(),
"AVG", 3) == 0) {
785 inputEntry.template setValue<std::string>(
"ADD");
788 CombineMode_ = vs2e->getIntegralValue(inputEntry, cmParamName);
795 if (plist->isParameter(
"subdomain solver name")) {
796 if (plist->get<std::string>(
"subdomain solver name") ==
"BLOCK_RELAXATION") {
797 if (plist->isSublist(
"subdomain solver parameters")) {
798 if (plist->sublist(
"subdomain solver parameters").isParameter(
"relaxation: type")) {
799 if (plist->sublist(
"subdomain solver parameters").get<std::string>(
"relaxation: type") ==
"Jacobi") {
800 if (plist->sublist(
"subdomain solver parameters").isParameter(
"partitioner: type")) {
801 if (plist->sublist(
"subdomain solver parameters").get<std::string>(
"partitioner: type") ==
"user") {
802 if (CombineMode_ == Tpetra::ADD) plist->sublist(
"subdomain solver parameters").set(
"partitioner: combine mode",
"ADD");
803 if (CombineMode_ == Tpetra::ZERO) plist->sublist(
"subdomain solver parameters").set(
"partitioner: combine mode",
"ZERO");
813 OverlapLevel_ = plist->get(
"schwarz: overlap level", OverlapLevel_);
819 UseReordering_ = plist->get(
"schwarz: use reordering", UseReordering_);
821#if !defined(HAVE_IFPACK2_XPETRA) || !defined(HAVE_IFPACK2_ZOLTAN2)
822 TEUCHOS_TEST_FOR_EXCEPTION(
823 UseReordering_, std::invalid_argument,
824 "Ifpack2::AdditiveSchwarz::"
825 "setParameters: You specified \"schwarz: use reordering\" = true. "
826 "This is only valid when Trilinos was built with Ifpack2, Xpetra, and "
827 "Zoltan2 enabled. Either Xpetra or Zoltan2 was not enabled in your build "
839 FilterSingletons_ = plist->get(
"schwarz: filter singletons", FilterSingletons_);
842 getParamTryingTypes<scalar_type, scalar_type, double>(UpdateDamping_, *plist,
"schwarz: update damping", prefix);
877 if (!Inverse_.is_null()) {
880 if (hasInnerPrecName() && innerPrecName() !=
"CUSTOM") {
883 Inverse_ = Teuchos::null;
887 std::pair<ParameterList, bool> result = innerPrecParams();
891 Inverse_->setParameters(rcp(
new ParameterList(result.first)));
896 NumIterations_ = plist->get(
"schwarz: num iterations", NumIterations_);
897 ZeroStartingSolution_ =
898 plist->get(
"schwarz: zero starting solution", ZeroStartingSolution_);
901template <
class MatrixType,
class LocalInverseType>
902Teuchos::RCP<const Teuchos::ParameterList>
905 using Teuchos::ParameterList;
906 using Teuchos::parameterList;
908 using Teuchos::rcp_const_cast;
910 if (validParams_.is_null()) {
911 const int overlapLevel = 0;
912 const bool useReordering =
false;
913 const bool filterSingletons =
false;
914 const int numIterations = 1;
915 const bool zeroStartingSolution =
true;
916 const scalar_type updateDamping = Teuchos::ScalarTraits<scalar_type>::one();
917 ParameterList reorderingSublist;
918 reorderingSublist.set(
"order_method", std::string(
"rcm"));
920 RCP<ParameterList> plist = parameterList(
"Ifpack2::AdditiveSchwarz");
922 Tpetra::setCombineModeParameter(*plist,
"schwarz: combine mode");
923 plist->set(
"schwarz: overlap level", overlapLevel);
924 plist->set(
"schwarz: use reordering", useReordering);
925 plist->set(
"schwarz: reordering list", reorderingSublist);
928 plist->set(
"schwarz: compute condest",
false);
929 plist->set(
"schwarz: filter singletons", filterSingletons);
930 plist->set(
"schwarz: num iterations", numIterations);
931 plist->set(
"schwarz: zero starting solution", zeroStartingSolution);
932 plist->set(
"schwarz: update damping", updateDamping);
942 validParams_ = rcp_const_cast<const ParameterList>(plist);
947template <
class MatrixType,
class LocalInverseType>
951 using Teuchos::SerialComm;
953 using Teuchos::TimeMonitor;
954 using Tpetra::global_size_t;
956 const std::string timerName(
"Ifpack2::AdditiveSchwarz::initialize");
957 RCP<Time> timer = TimeMonitor::lookupCounter(timerName);
958 if (timer.is_null()) {
959 timer = TimeMonitor::getNewCounter(timerName);
961 double startTime = timer->wallTime();
964 TimeMonitor timeMon(*timer);
966 TEUCHOS_TEST_FOR_EXCEPTION(
967 Matrix_.is_null(), std::runtime_error,
968 "Ifpack2::AdditiveSchwarz::"
969 "initialize: The matrix to precondition is null. You must either pass "
970 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
971 "input, before you may call this method.");
973 IsInitialized_ =
false;
975 overlapping_B_.reset(
nullptr);
976 overlapping_Y_.reset(
nullptr);
979 reduced_reordered_B_.reset(
nullptr);
980 reduced_reordered_Y_.reset(
nullptr);
981 reduced_B_.reset(
nullptr);
982 reduced_Y_.reset(
nullptr);
983 reordered_B_.reset(
nullptr);
984 reordered_Y_.reset(
nullptr);
986 RCP<const Teuchos::Comm<int>> comm = Matrix_->getComm();
987 RCP<const map_type> rowMap = Matrix_->getRowMap();
988 const global_size_t INVALID =
989 Teuchos::OrdinalTraits<global_size_t>::invalid();
993 if (comm->getSize() == 1) {
995 IsOverlapping_ =
false;
996 }
else if (OverlapLevel_ != 0) {
997 IsOverlapping_ =
true;
1000 if (OverlapLevel_ == 0) {
1002 RCP<const SerialComm<int>> localComm(
new SerialComm<int>());
1006 rcp(
new map_type(INVALID, rowMap->getLocalNumElements(),
1007 indexBase, localComm));
1011 if (IsOverlapping_) {
1012 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"OverlappingRowMatrix construction"));
1019 if (Inverse_.is_null())
return;
1020 const std::string innerName = innerPrecName();
1021 if (innerName.compare(
"RILUK") != 0)
return;
1022 if (Coordinates_ == Teuchos::null)
return;
1025 if (rowMap->getGlobalNumElements() != Coordinates_->getMap()->getGlobalNumElements())
return;
1027 auto ifpack2_Inverse = Teuchos::rcp_dynamic_cast<Ifpack2::Details::LinearSolver<scalar_type, local_ordinal_type, global_ordinal_type, node_type>>(Inverse_);
1028 if (!IsOverlapping_ && !UseReordering_) {
1029 ifpack2_Inverse->setCoord(Coordinates_);
1033 RCP<coord_type> tmp_Coordinates_;
1034 if (IsOverlapping_) {
1035 tmp_Coordinates_ = rcp(
new coord_type(OverlappingMatrix_->getRowMap(), Coordinates_->getNumVectors(),
false));
1036 Tpetra::Import<local_ordinal_type, global_ordinal_type, node_type> importer(Coordinates_->getMap(), tmp_Coordinates_->getMap());
1037 tmp_Coordinates_->doImport(*Coordinates_, importer, Tpetra::INSERT);
1039 tmp_Coordinates_ = rcp(
new coord_type(*Coordinates_, Teuchos::Copy));
1041 if (UseReordering_) {
1042 auto coorDevice = tmp_Coordinates_->getLocalViewDevice(Tpetra::Access::ReadWrite);
1043 auto permDevice = perm_coors.view_device();
1044 Kokkos::View<magnitude_type**, Kokkos::LayoutLeft> tmp_coor(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"tmp_coor"), coorDevice.extent(0), coorDevice.extent(1));
1045 Kokkos::parallel_for(
1046 Kokkos::RangePolicy<typename crs_matrix_type::execution_space>(0,
static_cast<int>(coorDevice.extent(0))), KOKKOS_LAMBDA(
const int& i) {
1047 for (
int j = 0; j < static_cast<int>(coorDevice.extent(1)); j++) {
1048 tmp_coor(permDevice(i), j) = coorDevice(i, j);
1051 Kokkos::deep_copy(coorDevice, tmp_coor);
1053 ifpack2_Inverse->setCoord(tmp_Coordinates_);
1056 if (!Inverse_.is_null()) {
1057 Inverse_->symbolic();
1062 IsInitialized_ =
true;
1065 InitializeTime_ += (timer->wallTime() - startTime);
1068template <
class MatrixType,
class LocalInverseType>
1070 return IsInitialized_;
1073template <
class MatrixType,
class LocalInverseType>
1076 using Teuchos::Time;
1077 using Teuchos::TimeMonitor;
1079 if (!IsInitialized_) {
1083 TEUCHOS_TEST_FOR_EXCEPTION(
1084 !isInitialized(), std::logic_error,
1085 "Ifpack2::AdditiveSchwarz::compute: "
1086 "The preconditioner is not yet initialized, "
1087 "even though initialize() supposedly has been called. "
1088 "This should never happen. "
1089 "Please report this bug to the Ifpack2 developers.");
1091 TEUCHOS_TEST_FOR_EXCEPTION(
1092 Inverse_.is_null(), std::runtime_error,
1093 "Ifpack2::AdditiveSchwarz::compute: The subdomain solver is null. "
1094 "This can only happen if you called setInnerPreconditioner() with a null "
1095 "input, after calling initialize() or compute(). If you choose to call "
1096 "setInnerPreconditioner() with a null input, you must then call it with a "
1097 "nonnull input before you may call initialize() or compute().");
1099 const std::string timerName(
"Ifpack2::AdditiveSchwarz::compute");
1100 RCP<Time> timer = TimeMonitor::lookupCounter(timerName);
1101 if (timer.is_null()) {
1102 timer = TimeMonitor::getNewCounter(timerName);
1104 TimeMonitor timeMon(*timer);
1105 double startTime = timer->wallTime();
1109 if (IsOverlapping_) {
1110 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Halo Import"));
1111 OverlappingMatrix_->doExtImport();
1117 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Fill Local Matrix"));
1120 asf->updateMatrixValues();
1126 const int rank = Matrix_->getComm()->getRank();
1127 writeLocalMatrixMarketPerRank(innerMatrix_, rank,
"Ifpack2_AdditiveSchwarz_innerMatrix");
1132 IsComputed_ =
false;
1133 Inverse_->numeric();
1139 ComputeTime_ += (timer->wallTime() - startTime);
1144template <
class MatrixType,
class LocalInverseType>
1149template <
class MatrixType,
class LocalInverseType>
1151 return NumInitialize_;
1154template <
class MatrixType,
class LocalInverseType>
1159template <
class MatrixType,
class LocalInverseType>
1164template <
class MatrixType,
class LocalInverseType>
1166 return InitializeTime_;
1169template <
class MatrixType,
class LocalInverseType>
1171 return ComputeTime_;
1174template <
class MatrixType,
class LocalInverseType>
1179template <
class MatrixType,
class LocalInverseType>
1181 std::ostringstream out;
1183 out <<
"\"Ifpack2::AdditiveSchwarz\": {";
1184 if (this->getObjectLabel() !=
"") {
1185 out <<
"Label: \"" << this->getObjectLabel() <<
"\", ";
1187 out <<
"Initialized: " << (isInitialized() ?
"true" :
"false")
1188 <<
", Computed: " << (isComputed() ?
"true" :
"false")
1189 <<
", Iterations: " << NumIterations_
1190 <<
", Overlap level: " << OverlapLevel_
1191 <<
", Subdomain reordering: \"" << ReorderingAlgorithm_ <<
"\"";
1192 out <<
", Combine mode: \"";
1193 if (CombineMode_ == Tpetra::INSERT) {
1195 }
else if (CombineMode_ == Tpetra::ADD) {
1197 }
else if (CombineMode_ == Tpetra::REPLACE) {
1199 }
else if (CombineMode_ == Tpetra::ABSMAX) {
1201 }
else if (CombineMode_ == Tpetra::ZERO) {
1205 if (Matrix_.is_null()) {
1206 out <<
", Matrix: null";
1208 out <<
", Global matrix dimensions: ["
1209 << Matrix_->getGlobalNumRows() <<
", "
1210 << Matrix_->getGlobalNumCols() <<
"]";
1212 out <<
", Inner solver: ";
1213 if (!Inverse_.is_null()) {
1214 Teuchos::RCP<Teuchos::Describable> inv =
1215 Teuchos::rcp_dynamic_cast<Teuchos::Describable>(Inverse_);
1216 if (!inv.is_null()) {
1217 out <<
"{" << inv->description() <<
"}";
1220 <<
"Some inner solver"
1231template <
class MatrixType,
class LocalInverseType>
1233 describe(Teuchos::FancyOStream& out,
1234 const Teuchos::EVerbosityLevel verbLevel)
const {
1236 using Teuchos::OSTab;
1237 using Teuchos::TypeNameTraits;
1239 const int myRank = Matrix_->getComm()->getRank();
1240 const int numProcs = Matrix_->getComm()->getSize();
1241 const Teuchos::EVerbosityLevel vl =
1242 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
1244 if (vl > Teuchos::VERB_NONE) {
1248 out <<
"\"Ifpack2::AdditiveSchwarz\":";
1252 out <<
"MatrixType: " << TypeNameTraits<MatrixType>::name() << endl;
1253 out <<
"LocalInverseType: " << TypeNameTraits<LocalInverseType>::name() << endl;
1254 if (this->getObjectLabel() !=
"") {
1255 out <<
"Label: \"" << this->getObjectLabel() <<
"\"" << endl;
1258 out <<
"Overlap level: " << OverlapLevel_ << endl
1259 <<
"Combine mode: \"";
1260 if (CombineMode_ == Tpetra::INSERT) {
1262 }
else if (CombineMode_ == Tpetra::ADD) {
1264 }
else if (CombineMode_ == Tpetra::REPLACE) {
1266 }
else if (CombineMode_ == Tpetra::ABSMAX) {
1268 }
else if (CombineMode_ == Tpetra::ZERO) {
1272 <<
"Subdomain reordering: \"" << ReorderingAlgorithm_ <<
"\"" << endl;
1275 if (Matrix_.is_null()) {
1277 out <<
"Matrix: null" << endl;
1281 out <<
"Matrix:" << endl;
1284 Matrix_->getComm()->barrier();
1285 Matrix_->describe(out, Teuchos::VERB_LOW);
1289 out <<
"Number of initialize calls: " << getNumInitialize() << endl
1290 <<
"Number of compute calls: " << getNumCompute() << endl
1291 <<
"Number of apply calls: " << getNumApply() << endl
1292 <<
"Total time in seconds for initialize: " << getInitializeTime() << endl
1293 <<
"Total time in seconds for compute: " << getComputeTime() << endl
1294 <<
"Total time in seconds for apply: " << getApplyTime() << endl;
1297 if (Inverse_.is_null()) {
1299 out <<
"Subdomain solver: null" << endl;
1302 if (vl < Teuchos::VERB_EXTREME) {
1304 auto ifpack2_inverse = Teuchos::rcp_dynamic_cast<Ifpack2::Details::LinearSolver<scalar_type, local_ordinal_type, global_ordinal_type, node_type>>(Inverse_);
1305 if (ifpack2_inverse.is_null())
1306 out <<
"Subdomain solver: not null" << endl;
1308 out <<
"Subdomain solver: ";
1309 ifpack2_inverse->describe(out, Teuchos::VERB_LOW);
1313 for (
int p = 0; p < numProcs; ++p) {
1315 out <<
"Subdomain solver on Process " << myRank <<
":";
1316 if (Inverse_.is_null()) {
1317 out <<
"null" << endl;
1319 Teuchos::RCP<Teuchos::Describable> inv =
1320 Teuchos::rcp_dynamic_cast<Teuchos::Describable>(Inverse_);
1321 if (!inv.is_null()) {
1323 inv->describe(out, vl);
1325 out <<
"null" << endl;
1329 Matrix_->getComm()->barrier();
1330 Matrix_->getComm()->barrier();
1331 Matrix_->getComm()->barrier();
1336 Matrix_->getComm()->barrier();
1340template <
class MatrixType,
class LocalInverseType>
1342 Teuchos::FancyOStream fos(Teuchos::rcp(&os,
false));
1343 fos.setOutputToRootOnly(0);
1348template <
class MatrixType,
class LocalInverseType>
1350 return OverlapLevel_;
1353template <
class MatrixType,
class LocalInverseType>
1356 using Teuchos::MpiComm;
1358 using Teuchos::ArrayRCP;
1359 using Teuchos::ParameterList;
1362 using Teuchos::rcp_dynamic_cast;
1363 using Teuchos::rcpFromRef;
1365 TEUCHOS_TEST_FOR_EXCEPTION(
1366 Matrix_.is_null(), std::runtime_error,
1367 "Ifpack2::AdditiveSchwarz::"
1368 "initialize: The matrix to precondition is null. You must either pass "
1369 "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
1370 "input, before you may call this method.");
1374 auto matrixCrs = rcp_dynamic_cast<const crs_matrix_type>(Matrix_);
1375 if (!OverlappingMatrix_.is_null() || !matrixCrs.is_null()) {
1376 ArrayRCP<local_ordinal_type> perm;
1377 ArrayRCP<local_ordinal_type> revperm;
1378 if (UseReordering_) {
1379 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Reordering"));
1380#if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
1382 Teuchos::ParameterList zlist = List_.sublist(
"schwarz: reordering list");
1383 ReorderingAlgorithm_ = zlist.get<std::string>(
"order_method",
"rcm");
1385 if (ReorderingAlgorithm_ ==
"user") {
1387 perm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user ordering");
1388 revperm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user reverse ordering");
1391 typedef Tpetra::RowGraph<local_ordinal_type, global_ordinal_type, node_type> row_graph_type;
1392 typedef Zoltan2::TpetraRowGraphAdapter<row_graph_type> z2_adapter_type;
1393 auto constActiveGraph = Teuchos::rcp_const_cast<const row_graph_type>(
1394 IsOverlapping_ ? OverlappingMatrix_->getGraph() : Matrix_->getGraph());
1395 z2_adapter_type Zoltan2Graph(constActiveGraph);
1397 typedef Zoltan2::OrderingProblem<z2_adapter_type> ordering_problem_type;
1402 RCP<const MpiComm<int>> mpicomm =
1403 rcp_dynamic_cast<const MpiComm<int>>(Matrix_->getComm());
1404 if (mpicomm == Teuchos::null) {
1405 myRawComm = MPI_COMM_SELF;
1407 myRawComm = *(mpicomm->getRawMpiComm());
1409 ordering_problem_type MyOrderingProblem(&Zoltan2Graph, &zlist, myRawComm);
1411 ordering_problem_type MyOrderingProblem(&Zoltan2Graph, &zlist);
1413 MyOrderingProblem.solve();
1416 typedef Zoltan2::LocalOrderingSolution<local_ordinal_type>
1417 ordering_solution_type;
1419 ordering_solution_type sol(*MyOrderingProblem.getLocalOrderingSolution());
1425 perm = sol.getPermutationRCPConst(
true);
1426 revperm = sol.getPermutationRCPConst();
1432 TEUCHOS_TEST_FOR_EXCEPTION(
1433 true, std::logic_error,
1434 "Ifpack2::AdditiveSchwarz::setup: "
1435 "The Zoltan2 and Xpetra packages must be enabled in order "
1436 "to support reordering.");
1439 local_ordinal_type numLocalRows = OverlappingMatrix_.is_null() ? matrixCrs->getLocalNumRows() : OverlappingMatrix_->getLocalNumRows();
1443 perm = ArrayRCP<local_ordinal_type>(numLocalRows);
1444 revperm = ArrayRCP<local_ordinal_type>(numLocalRows);
1445 for (local_ordinal_type i = 0; i < numLocalRows; i++) {
1453 Teuchos::TimeMonitor t(*Teuchos::TimeMonitor::getNewTimer(
"Filter construction"));
1454 RCP<Details::AdditiveSchwarzFilter<MatrixType>> asf;
1455 if (OverlappingMatrix_.is_null())
1456 asf = rcp(
new Details::AdditiveSchwarzFilter<MatrixType>(matrixCrs, perm, revperm, FilterSingletons_));
1458 asf = rcp(
new Details::AdditiveSchwarzFilter<MatrixType>(OverlappingMatrix_, perm, revperm, FilterSingletons_));
1462 if (UseReordering_ && (Coordinates_ != Teuchos::null)) {
1463 perm_coors = perm_dualview_type(Kokkos::view_alloc(Kokkos::WithoutInitializing,
"perm_coors"), perm.size());
1464 perm_coors.modify_host();
1465 auto permHost = perm_coors.view_host();
1466 for (local_ordinal_type i = 0; i < static_cast<local_ordinal_type>(perm.size()); i++) {
1467 permHost(i) = perm[i];
1469 perm_coors.sync_device();
1473 RCP<row_matrix_type> LocalizedMatrix;
1477 RCP<row_matrix_type> ActiveMatrix;
1480 if (!OverlappingMatrix_.is_null()) {
1481 LocalizedMatrix = rcp(
new LocalFilter<row_matrix_type>(OverlappingMatrix_));
1483 LocalizedMatrix = rcp(
new LocalFilter<row_matrix_type>(Matrix_));
1487 TEUCHOS_TEST_FOR_EXCEPTION(
1488 LocalizedMatrix.is_null(), std::logic_error,
1489 "Ifpack2::AdditiveSchwarz::setup: LocalizedMatrix is null, after the code "
1490 "that claimed to have created it. This should never be the case. Please "
1491 "report this bug to the Ifpack2 developers.");
1494 ActiveMatrix = LocalizedMatrix;
1497 if (FilterSingletons_) {
1498 SingletonMatrix_ = rcp(
new SingletonFilter<row_matrix_type>(LocalizedMatrix));
1499 ActiveMatrix = SingletonMatrix_;
1503 if (UseReordering_) {
1504#if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
1506 typedef ReorderFilter<row_matrix_type> reorder_filter_type;
1507 Teuchos::ParameterList zlist = List_.sublist(
"schwarz: reordering list");
1508 ReorderingAlgorithm_ = zlist.get<std::string>(
"order_method",
"rcm");
1510 ArrayRCP<local_ordinal_type> perm;
1511 ArrayRCP<local_ordinal_type> revperm;
1513 if (ReorderingAlgorithm_ ==
"user") {
1515 perm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user ordering");
1516 revperm = zlist.get<Teuchos::ArrayRCP<local_ordinal_type>>(
"user reverse ordering");
1519 typedef Tpetra::RowGraph<local_ordinal_type, global_ordinal_type, node_type> row_graph_type;
1520 typedef Zoltan2::TpetraRowGraphAdapter<row_graph_type> z2_adapter_type;
1521 RCP<const row_graph_type> constActiveGraph =
1522 Teuchos::rcp_const_cast<const row_graph_type>(ActiveMatrix->getGraph());
1523 z2_adapter_type Zoltan2Graph(constActiveGraph);
1525 typedef Zoltan2::OrderingProblem<z2_adapter_type> ordering_problem_type;
1530 RCP<const MpiComm<int>> mpicomm =
1531 rcp_dynamic_cast<const MpiComm<int>>(ActiveMatrix->getComm());
1532 if (mpicomm == Teuchos::null) {
1533 myRawComm = MPI_COMM_SELF;
1535 myRawComm = *(mpicomm->getRawMpiComm());
1537 ordering_problem_type MyOrderingProblem(&Zoltan2Graph, &zlist, myRawComm);
1539 ordering_problem_type MyOrderingProblem(&Zoltan2Graph, &zlist);
1541 MyOrderingProblem.solve();
1544 typedef Zoltan2::LocalOrderingSolution<local_ordinal_type>
1545 ordering_solution_type;
1547 ordering_solution_type sol(*MyOrderingProblem.getLocalOrderingSolution());
1553 perm = sol.getPermutationRCPConst(
true);
1554 revperm = sol.getPermutationRCPConst();
1558 ReorderedLocalizedMatrix_ = rcp(
new reorder_filter_type(ActiveMatrix, perm, revperm));
1560 ActiveMatrix = ReorderedLocalizedMatrix_;
1564 TEUCHOS_TEST_FOR_EXCEPTION(
1565 true, std::logic_error,
1566 "Ifpack2::AdditiveSchwarz::setup: "
1567 "The Zoltan2 and Xpetra packages must be enabled in order "
1568 "to support reordering.");
1571 innerMatrix_ = ActiveMatrix;
1574 TEUCHOS_TEST_FOR_EXCEPTION(
1575 innerMatrix_.is_null(), std::logic_error,
1576 "Ifpack2::AdditiveSchwarz::"
1577 "setup: Inner matrix is null right before constructing inner solver. "
1578 "Please report this bug to the Ifpack2 developers.");
1581 if (Inverse_.is_null()) {
1582 const std::string innerName = innerPrecName();
1583 TEUCHOS_TEST_FOR_EXCEPTION(
1584 innerName ==
"INVALID", std::logic_error,
1585 "Ifpack2::AdditiveSchwarz::initialize: AdditiveSchwarz doesn't "
1586 "know how to create an instance of your LocalInverseType \""
1587 << Teuchos::TypeNameTraits<LocalInverseType>::name() <<
"\". "
1588 "Please talk to the Ifpack2 developers for details.");
1590 TEUCHOS_TEST_FOR_EXCEPTION(
1591 innerName ==
"CUSTOM", std::runtime_error,
1592 "Ifpack2::AdditiveSchwarz::"
1593 "initialize: If the \"inner preconditioner name\" parameter (or any "
1594 "alias thereof) has the value \"CUSTOM\", then you must first call "
1595 "setInnerPreconditioner with a nonnull inner preconditioner input before "
1596 "you may call initialize().");
1600 if (!Trilinos::Details::Impl::registeredSomeLinearSolverFactory(
"Ifpack2")) {
1606 typedef typename MV::mag_type MT;
1607 RCP<inner_solver_type> innerPrec =
1608 Trilinos::Details::getLinearSolver<MV, OP, MT>(
"Ifpack2", innerName);
1609 TEUCHOS_TEST_FOR_EXCEPTION(
1610 innerPrec.is_null(), std::logic_error,
1611 "Ifpack2::AdditiveSchwarz::setup: Failed to create inner preconditioner "
1613 << innerName <<
"\".");
1614 innerPrec->setMatrix(innerMatrix_);
1618 std::pair<Teuchos::ParameterList, bool> result = innerPrecParams();
1619 if (result.second) {
1622 innerPrec->setParameters(rcp(
new ParameterList(result.first)));
1624 Inverse_ = innerPrec;
1625 }
else if (Inverse_->getMatrix().getRawPtr() != innerMatrix_.getRawPtr()) {
1629 Inverse_->setMatrix(innerMatrix_);
1631 TEUCHOS_TEST_FOR_EXCEPTION(
1632 Inverse_.is_null(), std::logic_error,
1633 "Ifpack2::AdditiveSchwarz::"
1634 "setup: Inverse_ is null right after we were supposed to have created it."
1635 " Please report this bug to the Ifpack2 developers.");
1644template <
class MatrixType,
class LocalInverseType>
1650 if (!innerPrec.is_null()) {
1653 can_change_type* innerSolver =
dynamic_cast<can_change_type*
>(&*innerPrec);
1654 TEUCHOS_TEST_FOR_EXCEPTION(
1655 innerSolver == NULL, std::invalid_argument,
1656 "Ifpack2::AdditiveSchwarz::"
1657 "setInnerPreconditioner: The input preconditioner does not implement the "
1658 "setMatrix() feature. Only input preconditioners that inherit from "
1659 "Ifpack2::Details::CanChangeMatrix implement this feature.");
1677 innerSolver->setMatrix(asf->getFilteredMatrix());
1679 innerSolver->setMatrix(innerMatrix_);
1689 removeInnerPrecName();
1690 removeInnerPrecParams();
1691 List_.set(
"inner preconditioner name",
"CUSTOM");
1695 if (isInitialized()) {
1696 innerPrec->initialize();
1699 innerPrec->compute();
1712 inner_solver_impl_type;
1713 Inverse_ = Teuchos::rcp(
new inner_solver_impl_type(innerPrec,
"CUSTOM"));
1716template <
class MatrixType,
class LocalInverseType>
1718 setMatrix(
const Teuchos::RCP<const row_matrix_type>& A) {
1720 if (A.getRawPtr() != Matrix_.getRawPtr()) {
1721 IsInitialized_ =
false;
1722 IsComputed_ =
false;
1725 OverlappingMatrix_ = Teuchos::null;
1726 ReorderedLocalizedMatrix_ = Teuchos::null;
1727 innerMatrix_ = Teuchos::null;
1728 SingletonMatrix_ = Teuchos::null;
1729 localMap_ = Teuchos::null;
1730 overlapping_B_.reset(
nullptr);
1731 overlapping_Y_.reset(
nullptr);
1734 DistributedImporter_ = Teuchos::null;
1740template <
class MatrixType,
class LocalInverseType>
1742 setCoord(
const Teuchos::RCP<const coord_type>& Coordinates) {
1744 if (Coordinates.getRawPtr() != Coordinates_.getRawPtr()) {
1745 Coordinates_ = Coordinates;
1754#define IFPACK2_ADDITIVESCHWARZ_INSTANT(S, LO, GO, N) \
1755 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 Ifpack2::Details::Behavior, a class that describes Ifpack2's run-time behavior.
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:1180
virtual bool isInitialized() const
Returns true if the preconditioner has been successfully initialized, false otherwise.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1069
void setCoord(const Teuchos::RCP< const coord_type > &Coordinates)
Set the matrix rows' coordinates.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1742
virtual int getOverlapLevel() const
Returns the level of overlap.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1349
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Get a list of the preconditioner's default parameters.
Definition Ifpack2_AdditiveSchwarz_def.hpp:904
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:1155
Teuchos::RCP< const coord_type > getCoord() const
Get the coordinates associated with the input matrix's rows.
Definition Ifpack2_AdditiveSchwarz_def.hpp:289
virtual int getNumApply() const
Returns the number of calls to apply().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1160
virtual double getComputeTime() const
Returns the time spent in compute().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1170
virtual double getApplyTime() const
Returns the time spent in apply().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1175
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1718
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:948
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
Set the preconditioner's parameters.
Definition Ifpack2_AdditiveSchwarz_def.hpp:713
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:1646
virtual double getInitializeTime() const
Returns the time spent in initialize().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1165
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 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:261
virtual void compute()
Computes all (coefficient) data necessary to apply the preconditioner.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1074
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:1341
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:1233
virtual void setParameters(const Teuchos::ParameterList &plist)
Set the preconditioner's parameters.
Definition Ifpack2_AdditiveSchwarz_def.hpp:703
virtual Teuchos::RCP< const row_matrix_type > getMatrix() const
The input matrix.
Definition Ifpack2_AdditiveSchwarz_def.hpp:284
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:320
virtual bool isComputed() const
Returns true if the preconditioner has been successfully computed, false otherwise.
Definition Ifpack2_AdditiveSchwarz_def.hpp:1145
virtual int getNumInitialize() const
Returns the number of calls to initialize().
Definition Ifpack2_AdditiveSchwarz_def.hpp:1150
AdditiveSchwarz(const Teuchos::RCP< const row_matrix_type > &A)
Constructor that takes a matrix.
Definition Ifpack2_AdditiveSchwarz_def.hpp:241
static bool writeAdditiveSchwarzLocalMatrix()
Whether to write the AdditiveSchwarz local matrix.
Definition Ifpack2_Details_Behavior.cpp:40
static bool debug()
Whether Ifpack2 is in debug mode.
Definition Ifpack2_Details_Behavior.cpp:31
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