Ifpack2 Templated Preconditioning Package  Version 1.0
Ifpack2_AdditiveSchwarz_def.hpp
Go to the documentation of this file.
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack2: Tempated Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2009) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
54 
55 #ifndef IFPACK2_ADDITIVESCHWARZ_DEF_HPP
56 #define IFPACK2_ADDITIVESCHWARZ_DEF_HPP
57 
58 #include "Trilinos_Details_LinearSolverFactory.hpp"
59 // We need Ifpack2's implementation of LinearSolver, because we use it
60 // to wrap the user-provided Ifpack2::Preconditioner in
61 // Ifpack2::AdditiveSchwarz::setInnerPreconditioner.
62 #include "Ifpack2_Details_LinearSolver.hpp"
63 
64 #if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
65 #include "Xpetra_RowMatrix.hpp"
66 #include "Xpetra_TpetraRowMatrix.hpp"
67 #include "Zoltan2_XpetraRowMatrixAdapter.hpp"
68 #include "Zoltan2_OrderingProblem.hpp"
69 #include "Zoltan2_OrderingSolution.hpp"
70 #endif
71 
73 #include "Ifpack2_LocalFilter.hpp"
74 #include "Ifpack2_OverlappingRowMatrix.hpp"
75 #include "Ifpack2_Parameters.hpp"
76 #include "Ifpack2_ReorderFilter.hpp"
77 #include "Ifpack2_SingletonFilter.hpp"
78 
79 #ifdef HAVE_MPI
80 #include "Teuchos_DefaultMpiComm.hpp"
81 #endif
82 
83 #include "Teuchos_StandardParameterEntryValidators.hpp"
84 #include <locale> // std::toupper
85 
86 
87 // FIXME (mfh 25 Aug 2015) Work-around for Bug 6392. This doesn't
88 // need to be a weak symbol because it only refers to a function in
89 // the Ifpack2 package.
90 namespace Ifpack2 {
91 namespace Details {
92  extern void registerLinearSolverFactory ();
93 } // namespace Details
94 } // namespace Ifpack2
95 
96 
97 namespace Ifpack2 {
98 
99 
100 template<class MatrixType, class LocalInverseType>
101 bool
102 AdditiveSchwarz<MatrixType, LocalInverseType>::hasInnerPrecName () const
103 {
104  const char* options[4] = {
105  "inner preconditioner name",
106  "subdomain solver name",
107  "schwarz: inner preconditioner name",
108  "schwarz: subdomain solver name"
109  };
110  const int numOptions = 4;
111  bool match = false;
112  for (int k = 0; k < numOptions && ! match; ++k) {
113  if (List_.isParameter (options[k])) {
114  return true;
115  }
116  }
117  return false;
118 }
119 
120 
121 template<class MatrixType, class LocalInverseType>
122 void
123 AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecName ()
124 {
125  const char* options[4] = {
126  "inner preconditioner name",
127  "subdomain solver name",
128  "schwarz: inner preconditioner name",
129  "schwarz: subdomain solver name"
130  };
131  const int numOptions = 4;
132  for (int k = 0; k < numOptions; ++k) {
133  List_.remove (options[k], false);
134  }
135 }
136 
137 
138 template<class MatrixType, class LocalInverseType>
139 std::string
140 AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecName () const
141 {
142  const char* options[4] = {
143  "inner preconditioner name",
144  "subdomain solver name",
145  "schwarz: inner preconditioner name",
146  "schwarz: subdomain solver name"
147  };
148  const int numOptions = 4;
149  std::string newName;
150  bool match = false;
151 
152  // As soon as one parameter option matches, ignore all others.
153  for (int k = 0; k < numOptions && ! match; ++k) {
154  if (List_.isParameter (options[k])) {
155  // try-catch block protects against incorrect type errors.
156  //
157  // FIXME (mfh 04 Jan 2013) We should instead catch and report
158  // type errors.
159  try {
160  newName = List_.get<std::string> (options[k]);
161  match = true;
162  } catch (...) {}
163  }
164  }
165  return match ? newName : defaultInnerPrecName ();
166 }
167 
168 
169 template<class MatrixType, class LocalInverseType>
170 void
171 AdditiveSchwarz<MatrixType, LocalInverseType>::removeInnerPrecParams ()
172 {
173  const char* options[4] = {
174  "inner preconditioner parameters",
175  "subdomain solver parameters",
176  "schwarz: inner preconditioner parameters",
177  "schwarz: subdomain solver parameters"
178  };
179  const int numOptions = 4;
180 
181  // As soon as one parameter option matches, ignore all others.
182  for (int k = 0; k < numOptions; ++k) {
183  List_.remove (options[k], false);
184  }
185 }
186 
187 
188 template<class MatrixType, class LocalInverseType>
189 std::pair<Teuchos::ParameterList, bool>
190 AdditiveSchwarz<MatrixType, LocalInverseType>::innerPrecParams () const
191 {
192  const char* options[4] = {
193  "inner preconditioner parameters",
194  "subdomain solver parameters",
195  "schwarz: inner preconditioner parameters",
196  "schwarz: subdomain solver parameters"
197  };
198  const int numOptions = 4;
199  Teuchos::ParameterList params;
200 
201  // As soon as one parameter option matches, ignore all others.
202  bool match = false;
203  for (int k = 0; k < numOptions && ! match; ++k) {
204  if (List_.isSublist (options[k])) {
205  params = List_.sublist (options[k]);
206  match = true;
207  }
208  }
209  // Default is an empty list of parameters.
210  return std::make_pair (params, match);
211 }
212 
213 
214 template<class MatrixType, class LocalInverseType>
215 std::string
216 AdditiveSchwarz<MatrixType, LocalInverseType>::defaultInnerPrecName ()
217 {
218  // The default inner preconditioner is "ILUT", for backwards
219  // compatibility with the original AdditiveSchwarz implementation.
220  return "ILUT";
221 }
222 
223 
224 template<class MatrixType, class LocalInverseType>
226 AdditiveSchwarz (const Teuchos::RCP<const row_matrix_type>& A) :
227  Matrix_ (A),
228  IsInitialized_ (false),
229  IsComputed_ (false),
230  IsOverlapping_ (false),
231  OverlapLevel_ (0),
232  CombineMode_ (Tpetra::ZERO),
233  UseReordering_ (false),
234  ReorderingAlgorithm_ ("none"),
235  FilterSingletons_ (false),
236  NumIterations_(1),
237  ZeroStartingSolution_(true),
238  NumInitialize_ (0),
239  NumCompute_ (0),
240  NumApply_ (0),
241  InitializeTime_ (0.0),
242  ComputeTime_ (0.0),
243  ApplyTime_ (0.0)
244 {
245  Teuchos::ParameterList plist;
246  setParameters (plist); // Set parameters to default values
247 }
248 
249 template<class MatrixType, class LocalInverseType>
251 AdditiveSchwarz (const Teuchos::RCP<const row_matrix_type>& A,
252  const int overlapLevel) :
253  Matrix_ (A),
254  IsInitialized_ (false),
255  IsComputed_ (false),
256  IsOverlapping_ (false),
257  OverlapLevel_ (overlapLevel),
258  CombineMode_ (Tpetra::ZERO),
259  UseReordering_ (false),
260  ReorderingAlgorithm_ ("none"),
261  FilterSingletons_ (false),
262  NumIterations_(1),
263  ZeroStartingSolution_(true),
264  NumInitialize_ (0),
265  NumCompute_ (0),
266  NumApply_ (0),
267  InitializeTime_ (0.0),
268  ComputeTime_ (0.0),
269  ApplyTime_ (0.0)
270 {
271  Teuchos::ParameterList plist;
272  setParameters (plist); // Set parameters to default values
273 }
274 
275 
276 template<class MatrixType,class LocalInverseType>
278 
279 
280 template<class MatrixType,class LocalInverseType>
281 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type > >
283 {
284  TEUCHOS_TEST_FOR_EXCEPTION(
285  Matrix_.is_null (), std::runtime_error, "Ifpack2::AdditiveSchwarz::"
286  "getDomainMap: The matrix to precondition is null. You must either pass "
287  "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
288  "input, before you may call this method.");
289  return Matrix_->getDomainMap ();
290 }
291 
292 
293 template<class MatrixType,class LocalInverseType>
294 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> >
296 {
297  TEUCHOS_TEST_FOR_EXCEPTION(
298  Matrix_.is_null (), std::runtime_error, "Ifpack2::AdditiveSchwarz::"
299  "getRangeMap: The matrix to precondition is null. You must either pass "
300  "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
301  "input, before you may call this method.");
302  return Matrix_->getRangeMap ();
303 }
304 
305 
306 template<class MatrixType,class LocalInverseType>
307 Teuchos::RCP<const Tpetra::RowMatrix<typename MatrixType::scalar_type, typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> > AdditiveSchwarz<MatrixType,LocalInverseType>::getMatrix() const
308 {
309  return Matrix_;
310 }
311 
312 
313 template<class MatrixType,class LocalInverseType>
314 void
316 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &B,
317  Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &Y,
318  Teuchos::ETransp mode,
319  scalar_type alpha,
320  scalar_type beta) const
321 {
322  using Teuchos::Time;
323  using Teuchos::TimeMonitor;
324  using Teuchos::RCP;
325  using Teuchos::rcp;
326  using Teuchos::rcp_dynamic_cast;
327  typedef Teuchos::ScalarTraits<scalar_type> STS;
328  const char prefix[] = "Ifpack2::AdditiveSchwarz::apply: ";
329 
330  TEUCHOS_TEST_FOR_EXCEPTION
331  (! IsComputed_, std::runtime_error,
332  prefix << "isComputed() must be true before you may call apply().");
333  TEUCHOS_TEST_FOR_EXCEPTION
334  (Matrix_.is_null (), std::logic_error, prefix <<
335  "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
341  (Inverse_.is_null (), std::runtime_error,
342  prefix << "The subdomain solver is null. "
343  "This can only happen if you called setInnerPreconditioner() with a null "
344  "input, after calling initialize() or compute(). If you choose to call "
345  "setInnerPreconditioner() with a null input, you must then call it with "
346  "a nonnull input before you may call initialize() or compute().");
347  TEUCHOS_TEST_FOR_EXCEPTION
348  (B.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
349  prefix << "B and Y must have the same number of columns. B has " <<
350  B.getNumVectors () << " columns, but Y has " << Y.getNumVectors() << ".");
351  TEUCHOS_TEST_FOR_EXCEPTION
352  (IsOverlapping_ && OverlappingMatrix_.is_null (), std::logic_error,
353  prefix << "The overlapping matrix is null. "
354  "This should never happen if IsOverlapping_ is true. "
355  "Please report this bug to the Ifpack2 developers.");
356  TEUCHOS_TEST_FOR_EXCEPTION
357  (! IsOverlapping_ && localMap_.is_null (), std::logic_error,
358  prefix << "localMap_ is null. "
359  "This should never happen if IsOverlapping_ is false. "
360  "Please report this bug to the Ifpack2 developers.");
361  TEUCHOS_TEST_FOR_EXCEPTION
362  (alpha != STS::one (), std::logic_error,
363  prefix << "Not implemented for alpha != 1.");
364  TEUCHOS_TEST_FOR_EXCEPTION
365  (beta != STS::zero (), std::logic_error,
366  prefix << "Not implemented for beta != 0.");
367 
368 #ifdef HAVE_IFPACK2_DEBUG
369  {
370  typedef typename STS::magnitudeType magnitude_type;
371  typedef Teuchos::ScalarTraits<magnitude_type> STM;
372  Teuchos::Array<magnitude_type> norms (B.getNumVectors ());
373  B.norm2 (norms ());
374  bool good = true;
375  for (size_t j = 0; j < B.getNumVectors (); ++j) {
376  if (STM::isnaninf (norms[j])) {
377  good = false;
378  break;
379  }
380  }
381  TEUCHOS_TEST_FOR_EXCEPTION
382  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
383  "The 2-norm of the input B is NaN or Inf.");
384  }
385 #endif // HAVE_IFPACK2_DEBUG
386 
387 #ifdef HAVE_IFPACK2_DEBUG
388  if (! ZeroStartingSolution_) {
389  typedef typename STS::magnitudeType magnitude_type;
390  typedef Teuchos::ScalarTraits<magnitude_type> STM;
391  Teuchos::Array<magnitude_type> norms (Y.getNumVectors ());
392  Y.norm2 (norms ());
393  bool good = true;
394  for (size_t j = 0; j < Y.getNumVectors (); ++j) {
395  if (STM::isnaninf (norms[j])) {
396  good = false;
397  break;
398  }
399  }
400  TEUCHOS_TEST_FOR_EXCEPTION
401  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
402  "On input, the initial guess Y has 2-norm NaN or Inf "
403  "(ZeroStartingSolution_ is false).");
404  }
405 #endif // HAVE_IFPACK2_DEBUG
406 
407  const std::string timerName ("Ifpack2::AdditiveSchwarz::apply");
408  RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
409  if (timer.is_null ()) {
410  timer = TimeMonitor::getNewCounter (timerName);
411  }
412 
413  { // Start timing here.
414  TimeMonitor timeMon (*timer);
415 
416  const scalar_type ZERO = Teuchos::ScalarTraits<scalar_type>::zero ();
417  //const scalar_type ONE = Teuchos::ScalarTraits<scalar_type>::one (); // unused
418  const size_t numVectors = B.getNumVectors ();
419 
420  // mfh 25 Apr 2015: Fix for currently failing
421  // Ifpack2_AdditiveSchwarz_RILUK test.
422  if (ZeroStartingSolution_) {
423  Y.putScalar (ZERO);
424  }
425 
426  // set up for overlap communication
427  RCP<MV> OverlappingB,OverlappingY;
428  RCP<MV> globalOverlappingB;
429  if (IsOverlapping_) {
430  // MV's constructor fills with zeros.
431  OverlappingB = rcp (new MV (OverlappingMatrix_->getRowMap (), numVectors));
432  OverlappingY = rcp (new MV (OverlappingMatrix_->getRowMap (), numVectors));
433  }
434  else {
435  // MV's constructor fills with zeros.
436  //
437  // localMap_ has the same number of indices on each process that
438  // Matrix_->getRowMap() does on that process. Thus, we can do
439  // the Import step without creating a new MV, just by viewing
440  // OverlappingB using Matrix_->getRowMap ().
441  OverlappingB = rcp (new MV (localMap_, numVectors));
442  OverlappingY = rcp (new MV (localMap_, numVectors));
443 
444  globalOverlappingB =
445  OverlappingB->offsetViewNonConst (Matrix_->getRowMap (), 0);
446 
447  // Create Import object on demand, if necessary.
448  if (DistributedImporter_.is_null ()) {
449  // FIXME (mfh 15 Apr 2014) Why can't we just ask the Matrix
450  // for its Import object? Of course a general RowMatrix might
451  // not necessarily have one.
452  DistributedImporter_ =
453  rcp (new import_type (Matrix_->getRowMap (),
454  Matrix_->getDomainMap ()));
455  }
456  }
457 
458  RCP<MV> R = rcp(new MV(B.getMap(),numVectors));
459  RCP<MV> C = rcp(new MV(Y.getMap(),numVectors)); //TODO no need to initialize to zero?
460 
461  for (int ni=0; ni<NumIterations_; ++ni)
462  {
463 #ifdef HAVE_IFPACK2_DEBUG
464  {
465  typedef typename STS::magnitudeType magnitude_type;
466  typedef Teuchos::ScalarTraits<magnitude_type> STM;
467  Teuchos::Array<magnitude_type> norms (Y.getNumVectors ());
468  Y.norm2 (norms ());
469  bool good = true;
470  for (size_t j = 0;
471  j < Y.getNumVectors (); ++j) {
472  if (STM::isnaninf (norms[j])) {
473  good = false;
474  break;
475  }
476  }
477  TEUCHOS_TEST_FOR_EXCEPTION
478  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
479  "At top of iteration " << ni << ", the 2-norm of Y is NaN or Inf.");
480  }
481 #endif // HAVE_IFPACK2_DEBUG
482 
483  Tpetra::deep_copy(*R, B);
484 
485  // if (ZeroStartingSolution_ && ni == 0) {
486  // Y.putScalar (STS::zero ());
487  // }
488  if (!ZeroStartingSolution_ || ni > 0) {
489  //calculate residual
490  Matrix_->apply (Y, *R, mode, -STS::one(), STS::one());
491 
492 #ifdef HAVE_IFPACK2_DEBUG
493  {
494  typedef typename STS::magnitudeType magnitude_type;
495  typedef Teuchos::ScalarTraits<magnitude_type> STM;
496  Teuchos::Array<magnitude_type> norms (R->getNumVectors ());
497  R->norm2 (norms ());
498  bool good = true;
499  for (size_t j = 0; j < R->getNumVectors (); ++j) {
500  if (STM::isnaninf (norms[j])) {
501  good = false;
502  break;
503  }
504  }
505  TEUCHOS_TEST_FOR_EXCEPTION
506  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
507  "At iteration " << ni << ", the 2-norm of R (result of computing "
508  "residual with Y) is NaN or Inf.");
509  }
510 #endif // HAVE_IFPACK2_DEBUG
511  }
512 
513  typedef OverlappingRowMatrix<row_matrix_type> overlap_mat_type;
514  RCP<overlap_mat_type> overlapMatrix;
515  if (IsOverlapping_) {
516  overlapMatrix = rcp_dynamic_cast<overlap_mat_type> (OverlappingMatrix_);
517  TEUCHOS_TEST_FOR_EXCEPTION
518  (overlapMatrix.is_null (), std::logic_error, prefix <<
519  "IsOverlapping_ is true, but OverlappingMatrix_, while nonnull, is "
520  "not an OverlappingRowMatrix<row_matrix_type>. Please report this "
521  "bug to the Ifpack2 developers.");
522  }
523 
524  // do communication if necessary
525  if (IsOverlapping_) {
526  TEUCHOS_TEST_FOR_EXCEPTION
527  (overlapMatrix.is_null (), std::logic_error, prefix
528  << "overlapMatrix is null when it shouldn't be. "
529  "Please report this bug to the Ifpack2 developers.");
530  overlapMatrix->importMultiVector (*R, *OverlappingB, Tpetra::INSERT);
531 
532  //JJH We don't need to import the solution Y we are always solving AY=R with initial guess zero
533  //if (ZeroStartingSolution_ == false)
534  // overlapMatrix->importMultiVector (Y, *OverlappingY, Tpetra::INSERT);
535  /*
536  FIXME from Ifpack1: Will not work with non-zero starting solutions.
537  TODO JJH 3/20/15 I don't know whether this comment is still valid.
538 
539  Here is the log for the associated commit 720b2fa4 to Ifpack1:
540 
541  "Added a note to recall that the nonzero starting solution will not
542  work properly if reordering, filtering or wider overlaps are used. This only
543  applied to methods like Jacobi, Gauss-Seidel, and SGS (in both point and block
544  version), and not to ILU-type preconditioners."
545  */
546 
547 #ifdef HAVE_IFPACK2_DEBUG
548  {
549  typedef typename STS::magnitudeType magnitude_type;
550  typedef Teuchos::ScalarTraits<magnitude_type> STM;
551  Teuchos::Array<magnitude_type> norms (OverlappingB->getNumVectors ());
552  OverlappingB->norm2 (norms ());
553  bool good = true;
554  for (size_t j = 0;
555  j < OverlappingB->getNumVectors (); ++j) {
556  if (STM::isnaninf (norms[j])) {
557  good = false;
558  break;
559  }
560  }
561  TEUCHOS_TEST_FOR_EXCEPTION
562  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
563  "At iteration " << ni << ", result of importMultiVector from R "
564  "to OverlappingB, has 2-norm NaN or Inf.");
565  }
566 #endif // HAVE_IFPACK2_DEBUG
567  } else {
568  globalOverlappingB->doImport (*R, *DistributedImporter_, Tpetra::INSERT);
569 
570 #ifdef HAVE_IFPACK2_DEBUG
571  {
572  typedef typename STS::magnitudeType magnitude_type;
573  typedef Teuchos::ScalarTraits<magnitude_type> STM;
574  Teuchos::Array<magnitude_type> norms (globalOverlappingB->getNumVectors ());
575  globalOverlappingB->norm2 (norms ());
576  bool good = true;
577  for (size_t j = 0;
578  j < globalOverlappingB->getNumVectors (); ++j) {
579  if (STM::isnaninf (norms[j])) {
580  good = false;
581  break;
582  }
583  }
584  TEUCHOS_TEST_FOR_EXCEPTION
585  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
586  "At iteration " << ni << ", result of doImport from R, has 2-norm "
587  "NaN or Inf.");
588  }
589 #endif // HAVE_IFPACK2_DEBUG
590  }
591 
592 #ifdef HAVE_IFPACK2_DEBUG
593  {
594  typedef typename STS::magnitudeType magnitude_type;
595  typedef Teuchos::ScalarTraits<magnitude_type> STM;
596  Teuchos::Array<magnitude_type> norms (OverlappingB->getNumVectors ());
597  OverlappingB->norm2 (norms ());
598  bool good = true;
599  for (size_t j = 0;
600  j < OverlappingB->getNumVectors (); ++j) {
601  if (STM::isnaninf (norms[j])) {
602  good = false;
603  break;
604  }
605  }
606  TEUCHOS_TEST_FOR_EXCEPTION
607  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
608  "At iteration " << ni << ", right before localApply, the 2-norm of "
609  "OverlappingB is NaN or Inf.");
610  }
611 #endif // HAVE_IFPACK2_DEBUG
612 
613  // local solve
614  localApply(*OverlappingB, *OverlappingY);
615 
616 #ifdef HAVE_IFPACK2_DEBUG
617  {
618  typedef typename STS::magnitudeType magnitude_type;
619  typedef Teuchos::ScalarTraits<magnitude_type> STM;
620  Teuchos::Array<magnitude_type> norms (OverlappingY->getNumVectors ());
621  OverlappingY->norm2 (norms ());
622  bool good = true;
623  for (size_t j = 0;
624  j < OverlappingY->getNumVectors (); ++j) {
625  if (STM::isnaninf (norms[j])) {
626  good = false;
627  break;
628  }
629  }
630  TEUCHOS_TEST_FOR_EXCEPTION
631  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
632  "At iteration " << ni << ", after localApply and before export / "
633  "copy, the 2-norm of OverlappingY is NaN or Inf.");
634  }
635 #endif // HAVE_IFPACK2_DEBUG
636 
637 #ifdef HAVE_IFPACK2_DEBUG
638  {
639  typedef typename STS::magnitudeType magnitude_type;
640  typedef Teuchos::ScalarTraits<magnitude_type> STM;
641  Teuchos::Array<magnitude_type> norms (C->getNumVectors ());
642  C->norm2 (norms ());
643  bool good = true;
644  for (size_t j = 0;
645  j < C->getNumVectors (); ++j) {
646  if (STM::isnaninf (norms[j])) {
647  good = false;
648  break;
649  }
650  }
651  TEUCHOS_TEST_FOR_EXCEPTION
652  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
653  "At iteration " << ni << ", before export / copy, the 2-norm of C "
654  "is NaN or Inf.");
655  }
656 #endif // HAVE_IFPACK2_DEBUG
657 
658  // do communication if necessary
659  if (IsOverlapping_) {
660  TEUCHOS_TEST_FOR_EXCEPTION
661  (overlapMatrix.is_null (), std::logic_error, prefix
662  << "overlapMatrix is null when it shouldn't be. "
663  "Please report this bug to the Ifpack2 developers.");
664  overlapMatrix->exportMultiVector (*OverlappingY, *C, CombineMode_);
665  }
666  else {
667  // mfh 16 Apr 2014: Make a view of Y with the same Map as
668  // OverlappingY, so that we can copy OverlappingY into Y. This
669  // replaces code that iterates over all entries of OverlappingY,
670  // copying them one at a time into Y. That code assumed that
671  // the rows of Y and the rows of OverlappingY have the same
672  // global indices in the same order; see Bug 5992.
673  RCP<MV> C_view = C->offsetViewNonConst (OverlappingY->getMap (), 0);
674  Tpetra::deep_copy (*C_view, *OverlappingY);
675  }
676 
677 #ifdef HAVE_IFPACK2_DEBUG
678  {
679  typedef typename STS::magnitudeType magnitude_type;
680  typedef Teuchos::ScalarTraits<magnitude_type> STM;
681  Teuchos::Array<magnitude_type> norms (C->getNumVectors ());
682  C->norm2 (norms ());
683  bool good = true;
684  for (size_t j = 0;
685  j < C->getNumVectors (); ++j) {
686  if (STM::isnaninf (norms[j])) {
687  good = false;
688  break;
689  }
690  }
691  TEUCHOS_TEST_FOR_EXCEPTION
692  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
693  "At iteration " << ni << ", before Y := C + Y, the 2-norm of C "
694  "is NaN or Inf.");
695  }
696 #endif // HAVE_IFPACK2_DEBUG
697 
698 #ifdef HAVE_IFPACK2_DEBUG
699  {
700  typedef typename STS::magnitudeType magnitude_type;
701  typedef Teuchos::ScalarTraits<magnitude_type> STM;
702  Teuchos::Array<magnitude_type> norms (Y.getNumVectors ());
703  Y.norm2 (norms ());
704  bool good = true;
705  for (size_t j = 0;
706  j < Y.getNumVectors (); ++j) {
707  if (STM::isnaninf (norms[j])) {
708  good = false;
709  break;
710  }
711  }
712  TEUCHOS_TEST_FOR_EXCEPTION
713  (! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
714  "Before Y := C + Y, at iteration " << ni << ", the 2-norm of Y "
715  "is NaN or Inf.");
716  }
717 #endif // HAVE_IFPACK2_DEBUG
718 
719  Y.update(STS::one(), *C, STS::one());
720 
721 #ifdef HAVE_IFPACK2_DEBUG
722  {
723  typedef typename STS::magnitudeType magnitude_type;
724  typedef Teuchos::ScalarTraits<magnitude_type> STM;
725  Teuchos::Array<magnitude_type> norms (Y.getNumVectors ());
726  Y.norm2 (norms ());
727  bool good = true;
728  for (size_t j = 0; j < Y.getNumVectors (); ++j) {
729  if (STM::isnaninf (norms[j])) {
730  good = false;
731  break;
732  }
733  }
734  TEUCHOS_TEST_FOR_EXCEPTION
735  ( ! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
736  "At iteration " << ni << ", after Y := C + Y, the 2-norm of Y "
737  "is NaN or Inf.");
738  }
739 #endif // HAVE_IFPACK2_DEBUG
740  }
741 
742  } // Stop timing here.
743 
744 #ifdef HAVE_IFPACK2_DEBUG
745  {
746  typedef typename STS::magnitudeType magnitude_type;
747  typedef Teuchos::ScalarTraits<magnitude_type> STM;
748  Teuchos::Array<magnitude_type> norms (Y.getNumVectors ());
749  Y.norm2 (norms ());
750  bool good = true;
751  for (size_t j = 0; j < Y.getNumVectors (); ++j) {
752  if (STM::isnaninf (norms[j])) {
753  good = false;
754  break;
755  }
756  }
757  TEUCHOS_TEST_FOR_EXCEPTION
758  ( ! good, std::runtime_error, "Ifpack2::AdditiveSchwarz::apply: "
759  "The 2-norm of the output Y is NaN or Inf.");
760  }
761 #endif // HAVE_IFPACK2_DEBUG
762 
763  ++NumApply_;
764 
765  // timer->totalElapsedTime() returns the total time over all timer
766  // calls. Thus, we use = instead of +=.
767  ApplyTime_ = timer->totalElapsedTime ();
768 }
769 
770 template<class MatrixType,class LocalInverseType>
771 void
773 localApply(MV &OverlappingB, MV &OverlappingY) const
774 {
775  using Teuchos::RCP;
776  using Teuchos::rcp_dynamic_cast;
777 
778  const size_t numVectors = OverlappingB.getNumVectors ();
779  if (FilterSingletons_) {
780  // process singleton filter
781  MV ReducedB (SingletonMatrix_->getRowMap (), numVectors);
782  MV ReducedY (SingletonMatrix_->getRowMap (), numVectors);
783 
784  RCP<SingletonFilter<row_matrix_type> > singletonFilter =
785  rcp_dynamic_cast<SingletonFilter<row_matrix_type> > (SingletonMatrix_);
786  TEUCHOS_TEST_FOR_EXCEPTION
787  (! SingletonMatrix_.is_null () && singletonFilter.is_null (),
788  std::logic_error, "Ifpack2::AdditiveSchwarz::localApply: "
789  "SingletonFilter_ is nonnull but is not a SingletonFilter"
790  "<row_matrix_type>. This should never happen. Please report this bug "
791  "to the Ifpack2 developers.");
792  singletonFilter->SolveSingletons (OverlappingB, OverlappingY);
793  singletonFilter->CreateReducedRHS (OverlappingY, OverlappingB, ReducedB);
794 
795  // process reordering
796  if (! UseReordering_) {
797  Inverse_->solve (ReducedY, ReducedB);
798  }
799  else {
800  RCP<ReorderFilter<row_matrix_type> > rf =
801  rcp_dynamic_cast<ReorderFilter<row_matrix_type> > (ReorderedLocalizedMatrix_);
802  TEUCHOS_TEST_FOR_EXCEPTION
803  (! ReorderedLocalizedMatrix_.is_null () && rf.is_null (), std::logic_error,
804  "Ifpack2::AdditiveSchwarz::localApply: ReorderedLocalizedMatrix_ is "
805  "nonnull but is not a ReorderFilter<row_matrix_type>. This should "
806  "never happen. Please report this bug to the Ifpack2 developers.");
807  MV ReorderedB (ReducedB, Teuchos::Copy);
808  MV ReorderedY (ReducedY, Teuchos::Copy);
809  rf->permuteOriginalToReordered (ReducedB, ReorderedB);
810  Inverse_->solve (ReorderedY, ReorderedB);
811  rf->permuteReorderedToOriginal (ReorderedY, ReducedY);
812  }
813 
814  // finish up with singletons
815  singletonFilter->UpdateLHS (ReducedY, OverlappingY);
816  }
817  else {
818 
819  // process reordering
820  if (! UseReordering_) {
821  Inverse_->solve (OverlappingY, OverlappingB);
822  }
823  else {
824  MV ReorderedB (OverlappingB, Teuchos::Copy);
825  MV ReorderedY (OverlappingY, Teuchos::Copy);
826 
827  RCP<ReorderFilter<row_matrix_type> > rf =
828  rcp_dynamic_cast<ReorderFilter<row_matrix_type> > (ReorderedLocalizedMatrix_);
829  TEUCHOS_TEST_FOR_EXCEPTION
830  (! ReorderedLocalizedMatrix_.is_null () && rf.is_null (), std::logic_error,
831  "Ifpack2::AdditiveSchwarz::localApply: ReorderedLocalizedMatrix_ is "
832  "nonnull but is not a ReorderFilter<row_matrix_type>. This should "
833  "never happen. Please report this bug to the Ifpack2 developers.");
834  rf->permuteOriginalToReordered (OverlappingB, ReorderedB);
835  Inverse_->solve (ReorderedY, ReorderedB);
836  rf->permuteReorderedToOriginal (ReorderedY, OverlappingY);
837  }
838  }
839 }
840 
841 
842 template<class MatrixType,class LocalInverseType>
844 setParameters (const Teuchos::ParameterList& plist)
845 {
846  // mfh 18 Nov 2013: Ifpack2's setParameters() method passes in the
847  // input list as const. This means that we have to copy it before
848  // validation or passing into setParameterList().
849  List_ = plist;
850  this->setParameterList (Teuchos::rcpFromRef (List_));
851 }
852 
853 
854 
855 template<class MatrixType,class LocalInverseType>
857 setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist)
858 {
859  using Tpetra::CombineMode;
860  using Teuchos::getIntegralValue;
861  using Teuchos::ParameterEntry;
862  using Teuchos::ParameterEntryValidator;
863  using Teuchos::ParameterList;
864  using Teuchos::RCP;
865  using Teuchos::rcp;
866  using Teuchos::rcp_dynamic_cast;
867  using Teuchos::StringToIntegralParameterEntryValidator;
868 
869  if (plist.is_null ()) {
870  // Assume that the user meant to set default parameters by passing
871  // in an empty list.
872  this->setParameterList (rcp (new ParameterList ()));
873  }
874  // FIXME (mfh 26 Aug 2015) It's not necessarily true that plist is
875  // nonnull at this point.
876 
877  // At this point, plist should be nonnull.
878  TEUCHOS_TEST_FOR_EXCEPTION(
879  plist.is_null (), std::logic_error, "Ifpack2::AdditiveSchwarz::"
880  "setParameterList: plist is null. This should never happen, since the "
881  "method should have replaced a null input list with a nonnull empty list "
882  "by this point. Please report this bug to the Ifpack2 developers.");
883 
884  // TODO JJH 24March2015 The list needs to be validated. Not sure why this is commented out.
885  // try {
886  // List_.validateParameters (* getValidParameters ());
887  // }
888  // catch (std::exception& e) {
889  // std::cerr << "Ifpack2::AdditiveSchwarz::setParameterList: Validation failed with the following error message: " << e.what () << std::endl;
890  // throw e;
891  // }
892 
893  // mfh 18 Nov 2013: Supplying the current value as the default value
894  // when calling ParameterList::get() ensures "delta" behavior when
895  // users pass in new parameters: any unspecified parameters in the
896  // new list retain their values in the old list. This preserves
897  // backwards compatiblity with this class' previous behavior. Note
898  // that validateParametersAndSetDefaults() would have different
899  // behavior: any parameters not in the new list would get default
900  // values, which could be different than their values in the
901  // original list.
902 
903  bool gotCombineMode = false;
904  try {
905  CombineMode_ = getIntegralValue<Tpetra::CombineMode> (List_, "schwarz: combine mode");
906  gotCombineMode = true;
907  }
908  catch (Teuchos::Exceptions::InvalidParameterName&) {
909  // The caller didn't provide that parameter. Just keep the
910  // existing value of CombineMode_.
911  gotCombineMode = true;
912  }
913  catch (Teuchos::Exceptions::InvalidParameterType&) {
914  // The user perhaps supplied it as an Tpetra::CombineMode enum
915  // value. Let's try again (below). If it doesn't succeed, we
916  // know that the type is wrong, so we can let it throw whatever
917  // exception it would throw.
918  }
919  // Try to get the combine mode as an integer.
920  if (! gotCombineMode) {
921  try {
922  CombineMode_ = plist->get ("schwarz: combine mode", CombineMode_);
923  gotCombineMode = true;
924  }
925  catch (Teuchos::Exceptions::InvalidParameterType&) {}
926  }
927  // Try to get the combine mode as a string. If this works, use the
928  // validator to convert to int. This is painful, but necessary in
929  // order to do validation, since the input list doesn't come with a
930  // validator.
931  if (! gotCombineMode) {
932  const ParameterEntry& validEntry =
933  getValidParameters ()->getEntry ("schwarz: combine mode");
934  RCP<const ParameterEntryValidator> v = validEntry.validator ();
935  typedef StringToIntegralParameterEntryValidator<CombineMode> vs2e_type;
936  RCP<const vs2e_type> vs2e = rcp_dynamic_cast<const vs2e_type> (v, true);
937 
938  const ParameterEntry& inputEntry = plist->getEntry ("schwarz: combine mode");
939  CombineMode_ = vs2e->getIntegralValue (inputEntry, "schwarz: combine mode");
940  gotCombineMode = true;
941  }
942  (void) gotCombineMode; // forestall "set but not used" compiler warning
943 
944  OverlapLevel_ = plist->get ("schwarz: overlap level", OverlapLevel_);
945 
946  // We set IsOverlapping_ in initialize(), once we know that Matrix_ is nonnull.
947 
948  // Will we be doing reordering? Unlike Ifpack, we'll use a
949  // "schwarz: reordering list" to give to Zoltan2.
950  UseReordering_ = plist->get ("schwarz: use reordering", UseReordering_);
951 
952 #if !defined(HAVE_IFPACK2_XPETRA) || !defined(HAVE_IFPACK2_ZOLTAN2)
953  TEUCHOS_TEST_FOR_EXCEPTION(
954  UseReordering_, std::invalid_argument, "Ifpack2::AdditiveSchwarz::"
955  "setParameters: You specified \"schwarz: use reordering\" = true. "
956  "This is only valid when Trilinos was built with Ifpack2, Xpetra, and "
957  "Zoltan2 enabled. Either Xpetra or Zoltan2 was not enabled in your build "
958  "of Trilinos.");
959 #endif
960 
961  // FIXME (mfh 18 Nov 2013) Now would be a good time to validate the
962  // "schwarz: reordering list" parameter list. Currently, that list
963  // gets extracted in setup().
964 
965  // if true, filter singletons. NOTE: the filtered matrix can still have
966  // singletons! A simple example: upper triangular matrix, if I remove
967  // the lower node, I still get a matrix with a singleton! However, filter
968  // singletons should help for PDE problems with Dirichlet BCs.
969  FilterSingletons_ = plist->get ("schwarz: filter singletons", FilterSingletons_);
970 
971  // If the inner solver doesn't exist yet, don't create it.
972  // initialize() creates it.
973  //
974  // If the inner solver _does_ exist, there are three cases,
975  // depending on what the user put in the input ParameterList.
976  //
977  // 1. The user did /not/ provide a parameter specifying the inner
978  // solver's type, nor did the user specify a sublist of
979  // parameters for the inner solver
980  // 2. The user did /not/ provide a parameter specifying the inner
981  // solver's type, but /did/ specify a sublist of parameters for
982  // the inner solver
983  // 3. The user provided a parameter specifying the inner solver's
984  // type (it does not matter in this case whether the user gave
985  // a sublist of parameters for the inner solver)
986  //
987  // AdditiveSchwarz has "delta" (relative) semantics for setting
988  // parameters. This means that if the user did not specify the
989  // inner solver's type, we presume that the type has not changed.
990  // Thus, if the inner solver exists, we don't need to recreate it.
991  //
992  // In Case 3, if the user bothered to specify the inner solver's
993  // type, then we must assume it may differ than the current inner
994  // solver's type. Thus, we have to recreate the inner solver. We
995  // achieve this here by assigning null to Inverse_; initialize()
996  // will recreate the solver when it is needed. Our assumption here
997  // is necessary because Ifpack2::Preconditioner does not have a
998  // method for querying a preconditioner's "type" (i.e., name) as a
999  // string. Remember that the user may have previously set an
1000  // arbitrary inner solver by calling setInnerPreconditioner().
1001  //
1002  // See note at the end of setInnerPreconditioner().
1003 
1004  if (! Inverse_.is_null ()) {
1005  // "CUSTOM" explicitly indicates that the user called or plans to
1006  // call setInnerPreconditioner.
1007  if (hasInnerPrecName () && innerPrecName () != "CUSTOM") {
1008  // Wipe out the current inner solver. initialize() will
1009  // recreate it with the correct type.
1010  Inverse_ = Teuchos::null;
1011  }
1012  else {
1013  // Extract and apply the sublist of parameters to give to the
1014  // inner solver, if there is such a sublist of parameters.
1015  std::pair<Teuchos::ParameterList, bool> result = innerPrecParams ();
1016  if (result.second) {
1017  // FIXME (mfh 26 Aug 2015) Rewrite innerPrecParams() so this
1018  // isn't another deep copy.
1019  Inverse_->setParameters (rcp (new ParameterList (result.first)));
1020  }
1021  }
1022  }
1023 
1024  NumIterations_ = plist->get<int>("schwarz: num iterations", NumIterations_);
1025  ZeroStartingSolution_ = plist->get<bool>("schwarz: zero starting solution", ZeroStartingSolution_);
1026 }
1027 
1028 
1029 
1030 template<class MatrixType,class LocalInverseType>
1031 Teuchos::RCP<const Teuchos::ParameterList>
1034 {
1035  using Teuchos::ParameterList;
1036  using Teuchos::parameterList;
1037  using Teuchos::RCP;
1038  using Teuchos::rcp_const_cast;
1039 
1040  if (validParams_.is_null ()) {
1041  const int overlapLevel = 0;
1042  const bool useReordering = false;
1043  const bool filterSingletons = false;
1044  const int numIterations = 1;
1045  const bool zeroStartingSolution = true;
1046  ParameterList reorderingSublist;
1047  reorderingSublist.set ("order_method", std::string ("rcm"));
1048 
1049  RCP<ParameterList> plist = parameterList ("Ifpack2::AdditiveSchwarz");
1050 
1051  Tpetra::setCombineModeParameter (*plist, "schwarz: combine mode");
1052  plist->set ("schwarz: overlap level", overlapLevel);
1053  plist->set ("schwarz: use reordering", useReordering);
1054  plist->set ("schwarz: reordering list", reorderingSublist);
1055  // mfh 24 Mar 2015: We accept this for backwards compatibility
1056  // ONLY. It is IGNORED.
1057  plist->set ("schwarz: compute condest", false);
1058  plist->set ("schwarz: filter singletons", filterSingletons);
1059  plist->set ("schwarz: num iterations", numIterations);
1060  plist->set ("schwarz: zero starting solution", zeroStartingSolution);
1061 
1062  // FIXME (mfh 18 Nov 2013) Get valid parameters from inner solver.
1063  // JJH The inner solver should handle its own validation.
1064  //
1065  // FIXME (mfh 18 Nov 2013) Get valid parameters from Zoltan2, if
1066  // Zoltan2 was enabled in the build.
1067  // JJH Zoltan2 should handle its own validation.
1068  //
1069 
1070  validParams_ = rcp_const_cast<const ParameterList> (plist);
1071  }
1072  return validParams_;
1073 }
1074 
1075 
1076 template<class MatrixType,class LocalInverseType>
1078 {
1079  using Tpetra::global_size_t;
1080  using Teuchos::RCP;
1081  using Teuchos::rcp;
1082  using Teuchos::SerialComm;
1083  using Teuchos::Time;
1084  using Teuchos::TimeMonitor;
1085 
1086  const std::string timerName ("Ifpack2::AdditiveSchwarz::initialize");
1087  RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
1088  if (timer.is_null ()) {
1089  timer = TimeMonitor::getNewCounter (timerName);
1090  }
1091 
1092  { // Start timing here.
1093  TimeMonitor timeMon (*timer);
1094 
1095  TEUCHOS_TEST_FOR_EXCEPTION(
1096  Matrix_.is_null (), std::runtime_error, "Ifpack2::AdditiveSchwarz::"
1097  "initialize: The matrix to precondition is null. You must either pass "
1098  "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
1099  "input, before you may call this method.");
1100 
1101  IsInitialized_ = false;
1102  IsComputed_ = false;
1103 
1104  RCP<const Teuchos::Comm<int> > comm = Matrix_->getComm ();
1105  RCP<const map_type> rowMap = Matrix_->getRowMap ();
1106  RCP<node_type> node = Matrix_->getNode ();
1107  const global_size_t INVALID =
1108  Teuchos::OrdinalTraits<global_size_t>::invalid ();
1109 
1110  // If there's only one process in the matrix's communicator,
1111  // then there's no need to compute overlap.
1112  if (comm->getSize () == 1) {
1113  OverlapLevel_ = 0;
1114  IsOverlapping_ = false;
1115  } else if (OverlapLevel_ != 0) {
1116  IsOverlapping_ = true;
1117  }
1118 
1119  if (OverlapLevel_ == 0) {
1120  const global_ordinal_type indexBase = rowMap->getIndexBase ();
1121  RCP<const SerialComm<int> > localComm (new SerialComm<int> ());
1122  // FIXME (mfh 15 Apr 2014) What if indexBase isn't the least
1123  // global index in the list of GIDs on this process?
1124  localMap_ =
1125  rcp (new map_type (INVALID, rowMap->getNodeNumElements (),
1126  indexBase, localComm, node));
1127  }
1128 
1129  // compute the overlapping matrix if necessary
1130  if (IsOverlapping_) {
1131  OverlappingMatrix_ = rcp (new OverlappingRowMatrix<row_matrix_type> (Matrix_, OverlapLevel_));
1132  }
1133 
1134  setup (); // This does a lot of the initialization work.
1135 
1136  if (! Inverse_.is_null ()) {
1137  Inverse_->symbolic (); // Initialize subdomain solver.
1138  }
1139 
1140  } // Stop timing here.
1141 
1142  IsInitialized_ = true;
1143  ++NumInitialize_;
1144 
1145  // timer->totalElapsedTime() returns the total time over all timer
1146  // calls. Thus, we use = instead of +=.
1147  InitializeTime_ = timer->totalElapsedTime ();
1148 }
1149 
1150 
1151 template<class MatrixType,class LocalInverseType>
1153 {
1154  return IsInitialized_;
1155 }
1156 
1157 
1158 template<class MatrixType,class LocalInverseType>
1160 {
1161  using Teuchos::RCP;
1162  using Teuchos::Time;
1163  using Teuchos::TimeMonitor;
1164 
1165  if (! IsInitialized_) {
1166  initialize ();
1167  }
1168 
1169  TEUCHOS_TEST_FOR_EXCEPTION(
1170  ! isInitialized (), std::logic_error, "Ifpack2::AdditiveSchwarz::compute: "
1171  "The preconditioner is not yet initialized, "
1172  "even though initialize() supposedly has been called. "
1173  "This should never happen. "
1174  "Please report this bug to the Ifpack2 developers.");
1175 
1176  TEUCHOS_TEST_FOR_EXCEPTION(
1177  Inverse_.is_null (), std::runtime_error,
1178  "Ifpack2::AdditiveSchwarz::compute: The subdomain solver is null. "
1179  "This can only happen if you called setInnerPreconditioner() with a null "
1180  "input, after calling initialize() or compute(). If you choose to call "
1181  "setInnerPreconditioner() with a null input, you must then call it with a "
1182  "nonnull input before you may call initialize() or compute().");
1183 
1184  const std::string timerName ("Ifpack2::AdditiveSchwarz::compute");
1185  RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
1186  if (timer.is_null ()) {
1187  timer = TimeMonitor::getNewCounter (timerName);
1188  }
1189 
1190  { // Start timing here.
1191  TimeMonitor timeMon (*timer);
1192 
1193  IsComputed_ = false;
1194  Inverse_->numeric ();
1195  } // Stop timing here.
1196 
1197  IsComputed_ = true;
1198  ++NumCompute_;
1199 
1200  // timer->totalElapsedTime() returns the total time over all timer
1201  // calls. Thus, we use = instead of +=.
1202  ComputeTime_ = timer->totalElapsedTime ();
1203 }
1204 
1205 //==============================================================================
1206 // Returns true if the preconditioner has been successfully computed, false otherwise.
1207 template<class MatrixType,class LocalInverseType>
1209 {
1210  return IsComputed_;
1211 }
1212 
1213 
1214 template<class MatrixType,class LocalInverseType>
1216 {
1217  return NumInitialize_;
1218 }
1219 
1220 
1221 template<class MatrixType,class LocalInverseType>
1223 {
1224  return NumCompute_;
1225 }
1226 
1227 
1228 template<class MatrixType,class LocalInverseType>
1230 {
1231  return NumApply_;
1232 }
1233 
1234 
1235 template<class MatrixType,class LocalInverseType>
1237 {
1238  return InitializeTime_;
1239 }
1240 
1241 
1242 template<class MatrixType,class LocalInverseType>
1244 {
1245  return ComputeTime_;
1246 }
1247 
1248 
1249 template<class MatrixType,class LocalInverseType>
1251 {
1252  return ApplyTime_;
1253 }
1254 
1255 
1256 template<class MatrixType,class LocalInverseType>
1258 {
1259  std::ostringstream out;
1260 
1261  out << "\"Ifpack2::AdditiveSchwarz\": {";
1262  if (this->getObjectLabel () != "") {
1263  out << "Label: \"" << this->getObjectLabel () << "\", ";
1264  }
1265  out << "Initialized: " << (isInitialized () ? "true" : "false")
1266  << ", Computed: " << (isComputed () ? "true" : "false")
1267  << ", Iterations: " << NumIterations_
1268  << ", Overlap level: " << OverlapLevel_
1269  << ", Subdomain reordering: \"" << ReorderingAlgorithm_ << "\"";
1270  out << ", Combine mode: \"";
1271  if (CombineMode_ == Tpetra::INSERT) {
1272  out << "INSERT";
1273  } else if (CombineMode_ == Tpetra::ADD) {
1274  out << "ADD";
1275  } else if (CombineMode_ == Tpetra::REPLACE) {
1276  out << "REPLACE";
1277  } else if (CombineMode_ == Tpetra::ABSMAX) {
1278  out << "ABSMAX";
1279  } else if (CombineMode_ == Tpetra::ZERO) {
1280  out << "ZERO";
1281  }
1282  out << "\"";
1283  if (Matrix_.is_null ()) {
1284  out << ", Matrix: null";
1285  }
1286  else {
1287  out << ", Global matrix dimensions: ["
1288  << Matrix_->getGlobalNumRows () << ", "
1289  << Matrix_->getGlobalNumCols () << "]";
1290  }
1291  out << ", Inner solver: ";
1292  if (! Inverse_.is_null ()) {
1293  Teuchos::RCP<Teuchos::Describable> inv =
1294  Teuchos::rcp_dynamic_cast<Teuchos::Describable> (Inverse_);
1295  if (! inv.is_null ()) {
1296  out << "{" << inv->description () << "}";
1297  } else {
1298  out << "{" << "Some inner solver" << "}";
1299  }
1300  } else {
1301  out << "null";
1302  }
1303 
1304  out << "}";
1305  return out.str ();
1306 }
1307 
1308 
1309 template<class MatrixType,class LocalInverseType>
1310 void
1312 describe (Teuchos::FancyOStream& out,
1313  const Teuchos::EVerbosityLevel verbLevel) const
1314 {
1315  using Teuchos::OSTab;
1316  using Teuchos::TypeNameTraits;
1317  using std::endl;
1318 
1319  const int myRank = Matrix_->getComm ()->getRank ();
1320  const int numProcs = Matrix_->getComm ()->getSize ();
1321  const Teuchos::EVerbosityLevel vl =
1322  (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
1323 
1324  if (vl > Teuchos::VERB_NONE) {
1325  // describe() starts with a tab, by convention.
1326  OSTab tab0 (out);
1327  if (myRank == 0) {
1328  out << "\"Ifpack2::AdditiveSchwarz\":";
1329  }
1330  OSTab tab1 (out);
1331  if (myRank == 0) {
1332  out << "MatrixType: " << TypeNameTraits<MatrixType>::name () << endl;
1333  out << "LocalInverseType: " << TypeNameTraits<LocalInverseType>::name () << endl;
1334  if (this->getObjectLabel () != "") {
1335  out << "Label: \"" << this->getObjectLabel () << "\"" << endl;
1336  }
1337 
1338  out << "Overlap level: " << OverlapLevel_ << endl
1339  << "Combine mode: \"";
1340  if (CombineMode_ == Tpetra::INSERT) {
1341  out << "INSERT";
1342  } else if (CombineMode_ == Tpetra::ADD) {
1343  out << "ADD";
1344  } else if (CombineMode_ == Tpetra::REPLACE) {
1345  out << "REPLACE";
1346  } else if (CombineMode_ == Tpetra::ABSMAX) {
1347  out << "ABSMAX";
1348  } else if (CombineMode_ == Tpetra::ZERO) {
1349  out << "ZERO";
1350  }
1351  out << "\"" << endl
1352  << "Subdomain reordering: \"" << ReorderingAlgorithm_ << "\"" << endl;
1353  }
1354 
1355  if (Matrix_.is_null ()) {
1356  if (myRank == 0) {
1357  out << "Matrix: null" << endl;
1358  }
1359  }
1360  else {
1361  if (myRank == 0) {
1362  out << "Matrix:" << endl;
1363  std::flush (out);
1364  }
1365  Matrix_->getComm ()->barrier (); // wait for output to finish
1366  Matrix_->describe (out, Teuchos::VERB_LOW);
1367  }
1368 
1369  if (myRank == 0) {
1370  out << "Number of initialize calls: " << getNumInitialize () << endl
1371  << "Number of compute calls: " << getNumCompute () << endl
1372  << "Number of apply calls: " << getNumApply () << endl
1373  << "Total time in seconds for initialize: " << getInitializeTime () << endl
1374  << "Total time in seconds for compute: " << getComputeTime () << endl
1375  << "Total time in seconds for apply: " << getApplyTime () << endl;
1376  }
1377 
1378  if (Inverse_.is_null ()) {
1379  if (myRank == 0) {
1380  out << "Subdomain solver: null" << endl;
1381  }
1382  }
1383  else {
1384  if (vl < Teuchos::VERB_EXTREME) {
1385  if (myRank == 0) {
1386  out << "Subdomain solver: not null" << endl;
1387  }
1388  }
1389  else { // vl >= Teuchos::VERB_EXTREME
1390  for (int p = 0; p < numProcs; ++p) {
1391  if (p == myRank) {
1392  out << "Subdomain solver on Process " << myRank << ":";
1393  if (Inverse_.is_null ()) {
1394  out << "null" << endl;
1395  } else {
1396  Teuchos::RCP<Teuchos::Describable> inv =
1397  Teuchos::rcp_dynamic_cast<Teuchos::Describable> (Inverse_);
1398  if (! inv.is_null ()) {
1399  out << endl;
1400  inv->describe (out, vl);
1401  } else {
1402  out << "null" << endl;
1403  }
1404  }
1405  }
1406  Matrix_->getComm ()->barrier ();
1407  Matrix_->getComm ()->barrier ();
1408  Matrix_->getComm ()->barrier (); // wait for output to finish
1409  }
1410  }
1411  }
1412 
1413  Matrix_->getComm ()->barrier (); // wait for output to finish
1414  }
1415 }
1416 
1417 
1418 template<class MatrixType,class LocalInverseType>
1419 std::ostream& AdditiveSchwarz<MatrixType,LocalInverseType>::print(std::ostream& os) const
1420 {
1421  Teuchos::FancyOStream fos(Teuchos::rcp(&os,false));
1422  fos.setOutputToRootOnly(0);
1423  describe(fos);
1424  return(os);
1425 }
1426 
1427 
1428 template<class MatrixType,class LocalInverseType>
1430 {
1431  return OverlapLevel_;
1432 }
1433 
1434 
1435 template<class MatrixType,class LocalInverseType>
1437 {
1438 #ifdef HAVE_MPI
1439  using Teuchos::MpiComm;
1440 #endif // HAVE_MPI
1441  using Teuchos::ArrayRCP;
1442  using Teuchos::ParameterList;
1443  using Teuchos::RCP;
1444  using Teuchos::rcp;
1445  using Teuchos::rcp_dynamic_cast;
1446  using Teuchos::rcpFromRef;
1447 
1448 #if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
1449  typedef Xpetra::RowMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> XpetraMatrixType;
1450  typedef Xpetra::TpetraRowMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> XpetraTpetraMatrixType;
1451 #endif
1452 
1453  TEUCHOS_TEST_FOR_EXCEPTION(
1454  Matrix_.is_null (), std::runtime_error, "Ifpack2::AdditiveSchwarz::"
1455  "initialize: The matrix to precondition is null. You must either pass "
1456  "a nonnull matrix to the constructor, or call setMatrix() with a nonnull "
1457  "input, before you may call this method.");
1458 
1459  // Localized version of Matrix_ or OverlappingMatrix_.
1460  RCP<row_matrix_type> LocalizedMatrix;
1461 
1462  // The "most current local matrix." At the end of this method, this
1463  // will be handed off to the inner solver.
1464  RCP<row_matrix_type> ActiveMatrix;
1465 
1466  // Create localized matrix.
1467  if (! OverlappingMatrix_.is_null ()) {
1468  LocalizedMatrix = rcp (new LocalFilter<row_matrix_type> (OverlappingMatrix_));
1469  }
1470  else {
1471  LocalizedMatrix = rcp (new LocalFilter<row_matrix_type> (Matrix_));
1472  }
1473 
1474  // Sanity check; I don't trust the logic above to have created LocalizedMatrix.
1475  TEUCHOS_TEST_FOR_EXCEPTION(
1476  LocalizedMatrix.is_null (), std::logic_error,
1477  "Ifpack2::AdditiveSchwarz::setup: LocalizedMatrix is null, after the code "
1478  "that claimed to have created it. This should never be the case. Please "
1479  "report this bug to the Ifpack2 developers.");
1480 
1481  // Mark localized matrix as active
1482  ActiveMatrix = LocalizedMatrix;
1483 
1484  // Singleton Filtering
1485  if (FilterSingletons_) {
1486  SingletonMatrix_ = rcp (new SingletonFilter<row_matrix_type> (LocalizedMatrix));
1487  ActiveMatrix = SingletonMatrix_;
1488  }
1489 
1490  // Do reordering
1491  if (UseReordering_) {
1492 #if defined(HAVE_IFPACK2_XPETRA) && defined(HAVE_IFPACK2_ZOLTAN2)
1493  // Unlike Ifpack, Zoltan2 does all the dirty work here.
1494  Teuchos::ParameterList zlist = List_.sublist ("schwarz: reordering list");
1495 
1496  // FIXME (mfh 18 Nov 2013) Shouldn't this come from the Zoltan2 sublist?
1497  ReorderingAlgorithm_ = List_.get<std::string> ("order_method", "rcm");
1498  XpetraTpetraMatrixType XpetraMatrix (ActiveMatrix);
1499  typedef Zoltan2::XpetraRowMatrixAdapter<XpetraMatrixType> z2_adapter_type;
1500  z2_adapter_type Zoltan2Matrix (rcpFromRef (XpetraMatrix));
1501  typedef Zoltan2::OrderingProblem<z2_adapter_type> ordering_problem_type;
1502 #ifdef HAVE_MPI
1503  // Grab the MPI Communicator and build the ordering problem with that
1504  MPI_Comm myRawComm;
1505 
1506  RCP<const MpiComm<int> > mpicomm =
1507  rcp_dynamic_cast<const MpiComm<int> > (ActiveMatrix->getComm ());
1508  if (mpicomm == Teuchos::null) {
1509  myRawComm = MPI_COMM_SELF;
1510  } else {
1511  myRawComm = * (mpicomm->getRawMpiComm ());
1512  }
1513  ordering_problem_type MyOrderingProblem (&Zoltan2Matrix, &zlist, myRawComm);
1514 #else
1515  ordering_problem_type MyOrderingProblem (&Zoltan2Matrix, &zlist);
1516 #endif
1517  MyOrderingProblem.solve ();
1518 
1519  // Now create the reordered matrix & mark it as active
1520  {
1521  typedef ReorderFilter<row_matrix_type> reorder_filter_type;
1522  typedef Zoltan2::OrderingSolution<local_ordinal_type,
1523  global_ordinal_type> ordering_solution_type;
1524 
1525  ordering_solution_type sol (*MyOrderingProblem.getSolution ());
1526 
1527  // perm[i] gives the where OLD index i shows up in the NEW
1528  // ordering. revperm[i] gives the where NEW index i shows
1529  // up in the OLD ordering. Note that perm is actually the
1530  // "inverse permutation," in Zoltan2 terms.
1531  ArrayRCP<local_ordinal_type> perm = sol.getPermutationRCPConst (true);
1532  ArrayRCP<local_ordinal_type> revperm = sol.getPermutationRCPConst ();
1533 
1534  ReorderedLocalizedMatrix_ =
1535  rcp (new reorder_filter_type (ActiveMatrix, perm, revperm));
1536 
1537  ActiveMatrix = ReorderedLocalizedMatrix_;
1538  }
1539 #else
1540  // This is a logic_error, not a runtime_error, because
1541  // setParameters() should have excluded this case already.
1542  TEUCHOS_TEST_FOR_EXCEPTION(
1543  true, std::logic_error, "Ifpack2::AdditiveSchwarz::setup: "
1544  "The Zoltan2 and Xpetra packages must be enabled in order "
1545  "to support reordering.");
1546 #endif
1547  }
1548 
1549  innerMatrix_ = ActiveMatrix;
1550 
1551  TEUCHOS_TEST_FOR_EXCEPTION(
1552  innerMatrix_.is_null (), std::logic_error, "Ifpack2::AdditiveSchwarz::"
1553  "setup: Inner matrix is null right before constructing inner solver. "
1554  "Please report this bug to the Ifpack2 developers.");
1555 
1556  // Construct the inner solver if necessary.
1557  if (Inverse_.is_null ()) {
1558  const std::string innerName = innerPrecName ();
1559  TEUCHOS_TEST_FOR_EXCEPTION(
1560  innerName == "INVALID", std::logic_error,
1561  "Ifpack2::AdditiveSchwarz::initialize: AdditiveSchwarz doesn't "
1562  "know how to create an instance of your LocalInverseType \""
1563  << Teuchos::TypeNameTraits<LocalInverseType>::name () << "\". "
1564  "Please talk to the Ifpack2 developers for details.");
1565 
1566  TEUCHOS_TEST_FOR_EXCEPTION(
1567  innerName == "CUSTOM", std::runtime_error, "Ifpack2::AdditiveSchwarz::"
1568  "initialize: If the \"inner preconditioner name\" parameter (or any "
1569  "alias thereof) has the value \"CUSTOM\", then you must first call "
1570  "setInnerPreconditioner with a nonnull inner preconditioner input before "
1571  "you may call initialize().");
1572 
1573  // FIXME (mfh 26 Aug 2015) Once we fix Bug 6392, the following
1574  // three lines of code can and SHOULD go away.
1575  if (! Trilinos::Details::Impl::registeredSomeLinearSolverFactory ("Ifpack2")) {
1576  Ifpack2::Details::registerLinearSolverFactory ();
1577  }
1578 
1579  // FIXME (mfh 26 Aug 2015) Provide the capability to get inner
1580  // solvers from packages other than Ifpack2.
1581  typedef typename MV::mag_type MT;
1582  RCP<inner_solver_type> innerPrec =
1583  Trilinos::Details::getLinearSolver<MV, OP, MT> ("Ifpack2", innerName);
1584  TEUCHOS_TEST_FOR_EXCEPTION(
1585  innerPrec.is_null (), std::logic_error,
1586  "Ifpack2::AdditiveSchwarz::setup: Failed to create inner preconditioner "
1587  "with name \"" << innerName << "\".");
1588  innerPrec->setMatrix (innerMatrix_);
1589 
1590  // Extract and apply the sublist of parameters to give to the
1591  // inner solver, if there is such a sublist of parameters.
1592  std::pair<Teuchos::ParameterList, bool> result = innerPrecParams ();
1593  if (result.second) {
1594  // FIXME (mfh 26 Aug 2015) We don't really want to use yet
1595  // another deep copy of the ParameterList here.
1596  innerPrec->setParameters (rcp (new ParameterList (result.first)));
1597  }
1598  Inverse_ = innerPrec; // "Commit" the inner solver.
1599  }
1600  else if (Inverse_->getMatrix ().getRawPtr () != innerMatrix_.getRawPtr ()) {
1601  // The new inner matrix is different from the inner
1602  // preconditioner's current matrix, so give the inner
1603  // preconditioner the new inner matrix.
1604  Inverse_->setMatrix (innerMatrix_);
1605  }
1606  TEUCHOS_TEST_FOR_EXCEPTION(
1607  Inverse_.is_null (), std::logic_error, "Ifpack2::AdditiveSchwarz::"
1608  "setup: Inverse_ is null right after we were supposed to have created it."
1609  " Please report this bug to the Ifpack2 developers.");
1610 
1611  // We don't have to call setInnerPreconditioner() here, because we
1612  // had the inner matrix (innerMatrix_) before creation of the inner
1613  // preconditioner. Calling setInnerPreconditioner here would be
1614  // legal, but it would require an unnecessary reset of the inner
1615  // preconditioner (i.e., calling initialize() and compute() again).
1616 }
1617 
1618 
1619 template<class MatrixType, class LocalInverseType>
1624  node_type> >& innerPrec)
1625 {
1626  if (! innerPrec.is_null ()) {
1627  // Make sure that the new inner solver knows how to have its matrix changed.
1628  typedef Details::CanChangeMatrix<row_matrix_type> can_change_type;
1629  can_change_type* innerSolver = dynamic_cast<can_change_type*> (&*innerPrec);
1630  TEUCHOS_TEST_FOR_EXCEPTION(
1631  innerSolver == NULL, std::invalid_argument, "Ifpack2::AdditiveSchwarz::"
1632  "setInnerPreconditioner: The input preconditioner does not implement the "
1633  "setMatrix() feature. Only input preconditioners that inherit from "
1634  "Ifpack2::Details::CanChangeMatrix implement this feature.");
1635 
1636  // If users provide an inner solver, we assume that
1637  // AdditiveSchwarz's current inner solver parameters no longer
1638  // apply. (In fact, we will remove those parameters from
1639  // AdditiveSchwarz's current list below.) Thus, we do /not/ apply
1640  // the current sublist of inner solver parameters to the input
1641  // inner solver.
1642 
1643  // mfh 03 Jan 2014: Thanks to Paul Tsuji for pointing out that
1644  // it's perfectly legal for innerMatrix_ to be null here. This
1645  // can happen if initialize() has not been called yet. For
1646  // example, when Ifpack2::Factory creates an AdditiveSchwarz
1647  // instance, it calls setInnerPreconditioner() without first
1648  // calling initialize().
1649 
1650  // Give the local matrix to the new inner solver.
1651  innerSolver->setMatrix (innerMatrix_);
1652 
1653  // If the user previously specified a parameter for the inner
1654  // preconditioner's type, then clear out that parameter and its
1655  // associated sublist. Replace the inner preconditioner's type with
1656  // "CUSTOM", to make it obvious that AdditiveSchwarz's ParameterList
1657  // does not necessarily describe the current inner preconditioner.
1658  // We have to remove all allowed aliases of "inner preconditioner
1659  // name" before we may set it to "CUSTOM". Users may also set this
1660  // parameter to "CUSTOM" themselves, but this is not required.
1661  removeInnerPrecName ();
1662  removeInnerPrecParams ();
1663  List_.set ("inner preconditioner name", "CUSTOM");
1664 
1665  // Bring the new inner solver's current status (initialized or
1666  // computed) in line with AdditiveSchwarz's current status.
1667  if (isInitialized ()) {
1668  innerPrec->initialize ();
1669  }
1670  if (isComputed ()) {
1671  innerPrec->compute ();
1672  }
1673  }
1674 
1675  // If the new inner solver is null, we don't change the initialized
1676  // or computed status of AdditiveSchwarz. That way, AdditiveSchwarz
1677  // won't have to recompute innerMatrix_ if the inner solver changes.
1678  // This does introduce a new error condition in compute() and
1679  // apply(), but that's OK.
1680 
1681  // Set the new inner solver.
1683  global_ordinal_type, node_type> inner_solver_impl_type;
1684  Inverse_ = Teuchos::rcp (new inner_solver_impl_type (innerPrec, "CUSTOM"));
1685 }
1686 
1687 template<class MatrixType, class LocalInverseType>
1689 setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
1690 {
1691  // Don't set the matrix unless it is different from the current one.
1692  if (A.getRawPtr () != Matrix_.getRawPtr ()) {
1693  IsInitialized_ = false;
1694  IsComputed_ = false;
1695 
1696  // Reset all the state computed in initialize() and compute().
1697  OverlappingMatrix_ = Teuchos::null;
1698  ReorderedLocalizedMatrix_ = Teuchos::null;
1699  innerMatrix_ = Teuchos::null;
1700  SingletonMatrix_ = Teuchos::null;
1701  localMap_ = Teuchos::null;
1702  DistributedImporter_ = Teuchos::null;
1703 
1704  Matrix_ = A;
1705  }
1706 }
1707 
1708 } // namespace Ifpack2
1709 
1710 // NOTE (mfh 26 Aug 2015) There's no need to instantiate for CrsMatrix
1711 // too. All Ifpack2 preconditioners can and should do dynamic casts
1712 // internally, if they need a type more specific than RowMatrix.
1713 #define IFPACK2_ADDITIVESCHWARZ_INSTANT(S,LO,GO,N) \
1714  template class Ifpack2::AdditiveSchwarz< Tpetra::RowMatrix<S, LO, GO, N> >;
1715 
1716 #endif // IFPACK2_ADDITIVESCHWARZ_DECL_HPP
Mix-in interface for preconditioners that can change their matrix after construction.
Definition: Ifpack2_Details_CanChangeMatrix.hpp:93
Wraps a Tpetra::RowMatrix in a filter that reorders local rows and columns.
Definition: Ifpack2_ReorderFilter_decl.hpp:69
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
Set the preconditioner&#39;s parameters.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:857
virtual void compute()
Computes all (coefficient) data necessary to apply the preconditioner.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1159
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:316
virtual int getNumApply() const
Returns the number of calls to apply().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1229
virtual bool isInitialized() const
Returns true if the preconditioner has been successfully initialized, false otherwise.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1152
virtual double getInitializeTime() const
Returns the time spent in initialize().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1236
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:1312
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:282
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:321
virtual double getComputeTime() const
Returns the time spent in compute().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1243
virtual ~AdditiveSchwarz()
Destructor.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:277
Teuchos::ScalarTraits< scalar_type >::magnitudeType magnitude_type
The type of the magnitude (absolute value) of a matrix entry.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:324
std::string description() const
Return a simple one-line description of this object.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1257
virtual std::ostream & print(std::ostream &os) const
Prints basic information on iostream. This function is used by operator<<.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1419
AdditiveSchwarz(const Teuchos::RCP< const row_matrix_type > &A)
Constructor that takes a matrix.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:226
virtual double getApplyTime() const
Returns the time spent in apply().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1250
virtual void initialize()
Computes all (graph-related) data necessary to initialize the preconditioner.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1077
Ifpack2 implementation details.
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:318
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:312
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:1621
Ifpack2&#39;s implementation of Trilinos::Details::LinearSolver interface.
Definition: Ifpack2_Details_LinearSolver_decl.hpp:105
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Get a list of the preconditioner&#39;s default parameters.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1033
Interface for all Ifpack2 preconditioners.
Definition: Ifpack2_Preconditioner.hpp:107
virtual Teuchos::RCP< const row_matrix_type > getMatrix() const
The input matrix.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:307
Declaration of interface for preconditioners that can change their matrix after construction.
virtual Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRangeMap() const
The range Map of this operator.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:295
virtual void setParameters(const Teuchos::ParameterList &plist)
Set the preconditioner&#39;s parameters.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:844
virtual int getNumCompute() const
Returns the number of calls to compute().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1222
Sparse matrix (Tpetra::RowMatrix subclass) with ghost rows.
Definition: Ifpack2_OverlappingRowMatrix_decl.hpp:59
Additive Schwarz domain decomposition for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:281
virtual bool isComputed() const
Returns true if the preconditioner has been successfully computed, false otherwise.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1208
Access only local rows and columns of a sparse matrix.
Definition: Ifpack2_LocalFilter_decl.hpp:160
virtual void SolveSingletons(const Tpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS, Tpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &LHS)
Solve the singleton components of the linear system.
Definition: Ifpack2_SingletonFilter_def.hpp:486
Preconditioners and smoothers for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:72
void registerLinearSolverFactory()
virtual void permuteOriginalToReordered(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &originalX, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &reorderedY) const
Permute multivector: original-to-reordered.
Definition: Ifpack2_ReorderFilter_def.hpp:532
Filter based on matrix entries.
Definition: Ifpack2_SingletonFilter_decl.hpp:64
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1689
virtual int getOverlapLevel() const
Returns the level of overlap.
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1429
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:315
virtual int getNumInitialize() const
Returns the number of calls to initialize().
Definition: Ifpack2_AdditiveSchwarz_def.hpp:1215