22 #ifndef IFPACK2_ADDITIVESCHWARZ_DEF_HPP 
   23 #define IFPACK2_ADDITIVESCHWARZ_DEF_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" 
   50 #include "Teuchos_StandardParameterEntryValidators.hpp" 
   53 #include <Tpetra_BlockMultiVector.hpp> 
   64 #ifdef HAVE_IFPACK2_DEBUG 
   69 bool anyBad(
const MV& X) {
 
   71   using magnitude_type = 
typename STS::magnitudeType;
 
   77   for (
size_t j = 0; j < X.getNumVectors(); ++j) {
 
   78     if (STM::isnaninf(norms[j])) {
 
   88 #endif  // HAVE_IFPACK2_DEBUG 
   92 template <
class MatrixType, 
class LocalInverseType>
 
   93 bool 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])) {
 
  109 template <
class MatrixType, 
class LocalInverseType>
 
  110 void 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);
 
  122 template <
class MatrixType, 
class LocalInverseType>
 
  124 AdditiveSchwarz<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) {
 
  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();
 
  146 template <
class MatrixType, 
class LocalInverseType>
 
  147 void 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);
 
  161 template <
class MatrixType, 
class LocalInverseType>
 
  162 std::pair<Teuchos::ParameterList, bool>
 
  163 AdditiveSchwarz<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;
 
  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);
 
  184 template <
class MatrixType, 
class LocalInverseType>
 
  186 AdditiveSchwarz<MatrixType, LocalInverseType>::defaultInnerPrecName() {
 
  192 template <
class MatrixType, 
class LocalInverseType>
 
  197 template <
class MatrixType, 
class LocalInverseType>
 
  202   , Coordinates_(coordinates) {}
 
  204 template <
class MatrixType, 
class LocalInverseType>
 
  207                     const int overlapLevel)
 
  209   , OverlapLevel_(overlapLevel) {}
 
  211 template <
class MatrixType, 
class LocalInverseType>
 
  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();
 
  224 template <
class MatrixType, 
class LocalInverseType>
 
  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();
 
  236 template <
class MatrixType, 
class LocalInverseType>
 
  241 template <
class MatrixType, 
class LocalInverseType>
 
  248 template <
class MatrixType, 
class map_type>
 
  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;
 
  262 template <
typename MV, 
typename Map>
 
  263 void 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));
 
  271 template <
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,
 
  280   using Teuchos::rcp_dynamic_cast;
 
  284   const char prefix[] = 
"Ifpack2::AdditiveSchwarz::apply: ";
 
  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.");
 
  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().");
 
  300                              prefix << 
"B and Y must have the same number of columns.  B has " << B.getNumVectors() << 
" columns, but Y has " << Y.getNumVectors() << 
".");
 
  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.");
 
  306                              prefix << 
"localMap_ is null.  " 
  307                                        "This should never happen if IsOverlapping_ is false.  " 
  308                                        "Please report this bug to the Ifpack2 developers.");
 
  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.");
 
  321 #endif  // HAVE_IFPACK2_DEBUG 
  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).");
 
  331 #endif  // HAVE_IFPACK2_DEBUG 
  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);
 
  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);
 
  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));
 
  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.");
 
  416 #endif  // HAVE_IFPACK2_DEBUG 
  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.");
 
  436 #endif  // HAVE_IFPACK2_DEBUG 
  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.");
 
  470 #endif  // HAVE_IFPACK2_DEBUG 
  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 " 
  483 #endif  // HAVE_IFPACK2_DEBUG 
  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.");
 
  495 #endif  // HAVE_IFPACK2_DEBUG 
  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.");
 
  509 #endif  // HAVE_IFPACK2_DEBUG 
  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 " 
  520 #endif  // HAVE_IFPACK2_DEBUG 
  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_);
 
  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 " 
  555 #endif  // HAVE_IFPACK2_DEBUG 
  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 " 
  566 #endif  // HAVE_IFPACK2_DEBUG 
  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 " 
  579 #endif  // HAVE_IFPACK2_DEBUG 
  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.");
 
  591 #endif  // HAVE_IFPACK2_DEBUG 
  595   ApplyTime_ += (timer->wallTime() - startTime);
 
  598 template <
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_);
 
  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_);
 
  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_);
 
  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);
 
  678 template <
class MatrixType, 
class LocalInverseType>
 
  685   this->setParameterList(Teuchos::rcpFromRef(List_));
 
  688 template <
class MatrixType, 
class LocalInverseType>
 
  691   using Details::getParamTryingTypes;
 
  697   using Teuchos::rcp_dynamic_cast;
 
  699   using Tpetra::CombineMode;
 
  700   const char prefix[] = 
"Ifpack2::AdditiveSchwarz: ";
 
  705     this->setParameterList(
rcp(
new ParameterList()));
 
  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);
 
  773     if (plist->
get<std::string>(
"subdomain solver name") == 
"BLOCK_RELAXATION") {
 
  774       if (plist->
isSublist(
"subdomain solver parameters")) {
 
  776           if (plist->
sublist(
"subdomain solver parameters").
get<std::string>(
"relaxation: type") == 
"Jacobi") {
 
  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) 
  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_);
 
  878 template <
class MatrixType, 
class LocalInverseType>
 
  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;
 
  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);
 
  924 template <
class MatrixType, 
class LocalInverseType>
 
  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);
 
  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 =
 
  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_) {
 
  995     if (!Inverse_.is_null()) {
 
  996       const std::string innerName = innerPrecName();
 
  997       if ((innerName.compare(
"RILUK") == 0) && (Coordinates_ != Teuchos::null)) {
 
  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);
 
 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);
 
 1036 template <
class MatrixType, 
class LocalInverseType>
 
 1038   return IsInitialized_;
 
 1041 template <
class MatrixType, 
class LocalInverseType>
 
 1047   if (!IsInitialized_) {
 
 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.");
 
 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_) {
 
 1079     OverlappingMatrix_->doExtImport();
 
 1084   if (
auto asf = Teuchos::rcp_dynamic_cast<Details::AdditiveSchwarzFilter<MatrixType>>(innerMatrix_)) {
 
 1088     asf->updateMatrixValues();
 
 1095     IsComputed_ = 
false;
 
 1096     Inverse_->numeric();
 
 1102   ComputeTime_ += (timer->wallTime() - startTime);
 
 1107 template <
class MatrixType, 
class LocalInverseType>
 
 1112 template <
class MatrixType, 
class LocalInverseType>
 
 1114   return NumInitialize_;
 
 1117 template <
class MatrixType, 
class LocalInverseType>
 
 1122 template <
class MatrixType, 
class LocalInverseType>
 
 1127 template <
class MatrixType, 
class LocalInverseType>
 
 1129   return InitializeTime_;
 
 1132 template <
class MatrixType, 
class LocalInverseType>
 
 1134   return ComputeTime_;
 
 1137 template <
class MatrixType, 
class LocalInverseType>
 
 1142 template <
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()) {
 
 1183           << 
"Some inner solver" 
 1194 template <
class MatrixType, 
class LocalInverseType>
 
 1202   const int myRank   = Matrix_->getComm()->getRank();
 
 1203   const int numProcs = Matrix_->getComm()->getSize();
 
 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();  
 
 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;
 
 1268           if (ifpack2_inverse.is_null())
 
 1269             out << 
"Subdomain solver: not null" << endl;
 
 1271             out << 
"Subdomain solver: ";
 
 1276         for (
int p = 0; p < numProcs; ++p) {
 
 1278             out << 
"Subdomain solver on Process " << myRank << 
":";
 
 1279             if (Inverse_.is_null()) {
 
 1280               out << 
"null" << endl;
 
 1288                 out << 
"null" << endl;
 
 1292           Matrix_->getComm()->barrier();
 
 1293           Matrix_->getComm()->barrier();
 
 1294           Matrix_->getComm()->barrier();  
 
 1299     Matrix_->getComm()->barrier();  
 
 1303 template <
class MatrixType, 
class LocalInverseType>
 
 1311 template <
class MatrixType, 
class LocalInverseType>
 
 1313   return OverlapLevel_;
 
 1316 template <
class MatrixType, 
class LocalInverseType>
 
 1319   using Teuchos::MpiComm;
 
 1325   using Teuchos::rcp_dynamic_cast;
 
 1326   using Teuchos::rcpFromRef;
 
 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_) {
 
 1343 #if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2) 
 1346       ReorderingAlgorithm_         = zlist.
get<std::string>(
"order_method", 
"rcm");
 
 1348       if (ReorderingAlgorithm_ == 
"user") {
 
 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();
 
 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++) {
 
 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_));
 
 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;
 
 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") {
 
 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_;
 
 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;
 
 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();
 
 1547         innerName == 
"INVALID", std::logic_error,
 
 1548         "Ifpack2::AdditiveSchwarz::initialize: AdditiveSchwarz doesn't " 
 1549         "know how to create an instance of your LocalInverseType \"" 
 1551                                                                     "Please talk to the Ifpack2 developers for details.");
 
 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().");
 
 1564       Ifpack2::Details::registerLinearSolverFactory();
 
 1569     typedef typename MV::mag_type MT;
 
 1570     RCP<inner_solver_type> innerPrec =
 
 1571         Trilinos::Details::getLinearSolver<MV, OP, MT>(
"Ifpack2", innerName);
 
 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_);
 
 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.");
 
 1607 template <
class MatrixType, 
class LocalInverseType>
 
 1613   if (!innerPrec.is_null()) {
 
 1616     can_change_type* innerSolver = 
dynamic_cast<can_change_type*
>(&*innerPrec);
 
 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.");
 
 1639     if (
auto asf = Teuchos::rcp_dynamic_cast<Details::AdditiveSchwarzFilter<MatrixType>>(innerMatrix_))
 
 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"));
 
 1679 template <
class MatrixType, 
class LocalInverseType>
 
 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;
 
 1703 template <
class MatrixType, 
class LocalInverseType>
 
 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>>; 
 1720 #endif  // IFPACK2_ADDITIVESCHWARZ_DECL_HPP 
Mix-in interface for preconditioners that can change their matrix after construction. 
Definition: Ifpack2_Details_CanChangeMatrix.hpp:60
 
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
Set the preconditioner's parameters. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:690
 
virtual void compute()
Computes all (coefficient) data necessary to apply the preconditioner. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1042
 
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
 
basic_OSTab< char > OSTab
 
virtual int getNumApply() const 
Returns the number of calls to apply(). 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1123
 
T & get(const std::string &name, T def_value)
 
virtual bool isInitialized() const 
Returns true if the preconditioner has been successfully initialized, false otherwise. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1037
 
virtual double getInitializeTime() const 
Returns the time spent in initialize(). 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1128
 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
 
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const 
Print the object with some verbosity level to an FancyOStream object. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1196
 
void setCoord(const Teuchos::RCP< const coord_type > &C)
Set the matrix rows' coordinates. 
Definition: Ifpack2_Details_LinearSolver_def.hpp:87
 
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 double getComputeTime() const 
Returns the time spent in compute(). 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1133
 
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
 
std::string description() const 
Return a simple one-line description of this object. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1143
 
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
 
AdditiveSchwarz(const Teuchos::RCP< const row_matrix_type > &A)
Constructor that takes a matrix. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:194
 
virtual double getApplyTime() const 
Returns the time spent in apply(). 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1138
 
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
 
static RCP< Time > getNewTimer(const std::string &name)
 
ParameterEntry * getEntryPtr(const std::string &name)
 
bool registeredSomeLinearSolverFactory(const std::string &packageName)
 
bool isParameter(const std::string &name) const 
 
typename MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType. 
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:286
 
Teuchos::RCP< const coord_type > getCoord() const 
Get the coordinates associated with the input matrix's rows. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:242
 
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
 
bool isSublist(const std::string &name) const 
 
Ifpack2's implementation of Trilinos::Details::LinearSolver interface. 
Definition: Ifpack2_Details_LinearSolver_decl.hpp:72
 
virtual std::string description() const 
 
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const 
Get a list of the preconditioner's default parameters. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:881
 
Interface for all Ifpack2 preconditioners. 
Definition: Ifpack2_Preconditioner.hpp:74
 
virtual Teuchos::RCP< const row_matrix_type > getMatrix() const 
The input matrix. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:237
 
typename MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType. 
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:283
 
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
 
Declaration of interface for preconditioners that can change their matrix after construction. 
 
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 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 void setParameters(const Teuchos::ParameterList &plist)
Set the preconditioner's parameters. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:680
 
virtual int getNumCompute() const 
Returns the number of calls to compute(). 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1118
 
Sparse matrix (Tpetra::RowMatrix subclass) with ghost rows. 
Definition: Ifpack2_OverlappingRowMatrix_decl.hpp:25
 
Additive Schwarz domain decomposition for Tpetra sparse matrices. 
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:249
 
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
 
virtual bool isComputed() const 
Returns true if the preconditioner has been successfully computed, false otherwise. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1108
 
Declaration of Ifpack2::AdditiveSchwarz, which implements additive Schwarz preconditioning with an ar...
 
ParameterEntry & getEntry(const std::string &name)
 
void registerLinearSolverFactory()
 
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1681
 
void getValidParameters(Teuchos::ParameterList ¶ms)
Fills a list which contains all the parameters possibly used by Ifpack2. 
Definition: Ifpack2_Parameters.cpp:18
 
virtual int getOverlapLevel() const 
Returns the level of overlap. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1312
 
void setCoord(const Teuchos::RCP< const coord_type > &Coordinates)
Set the matrix rows' coordinates. 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1705
 
typename MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType. 
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:280
 
virtual void describe(FancyOStream &out, const EVerbosityLevel verbLevel=verbLevel_default) const 
 
virtual int getNumInitialize() const 
Returns the number of calls to initialize(). 
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1113