Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_Chebyshev_def.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
4 //
5 // Copyright 2009 NTESS and the Ifpack2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef IFPACK2_CHEBYSHEV_DEF_HPP
11 #define IFPACK2_CHEBYSHEV_DEF_HPP
12 
13 #include "Ifpack2_Parameters.hpp"
14 #include "Teuchos_TimeMonitor.hpp"
15 #include "Tpetra_CrsMatrix.hpp"
17 #include <iostream>
18 #include <sstream>
19 
20 namespace Ifpack2 {
21 
22 template <class MatrixType>
25  : impl_(A)
26  , IsInitialized_(false)
27  , IsComputed_(false)
28  , NumInitialize_(0)
29  , NumCompute_(0)
30  , TimerForApply_(true)
31  , NumApply_(0)
32  , InitializeTime_(0.0)
33  , ComputeTime_(0.0)
34  , ApplyTime_(0.0)
35  , ComputeFlops_(0.0)
36  , ApplyFlops_(0.0) {
37  this->setObjectLabel("Ifpack2::Chebyshev");
38 }
39 
40 template <class MatrixType>
42 }
43 
44 template <class MatrixType>
46  if (A.getRawPtr() != impl_.getMatrix().getRawPtr()) {
47  IsInitialized_ = false;
48  IsComputed_ = false;
49  impl_.setMatrix(A);
50  }
51 }
52 
53 template <class MatrixType>
55  // FIXME (mfh 25 Jan 2013) Casting away const is bad here.
56  impl_.setParameters(const_cast<Teuchos::ParameterList&>(List));
57  if (List.isType<bool>("timer for apply"))
58  TimerForApply_ = List.get<bool>("timer for apply");
59 }
60 
61 template <class MatrixType>
62 void Chebyshev<MatrixType>::setZeroStartingSolution(bool zeroStartingSolution) {
63  impl_.setZeroStartingSolution(zeroStartingSolution);
64 }
65 
66 template <class MatrixType>
69  Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
71  A.is_null(), std::runtime_error,
72  "Ifpack2::Chebyshev::getComm: The input "
73  "matrix A is null. Please call setMatrix() with a nonnull input matrix "
74  "before calling this method.");
75  return A->getRowMap()->getComm();
76 }
77 
78 template <class MatrixType>
81  getMatrix() const {
82  return impl_.getMatrix();
83 }
84 
85 template <class MatrixType>
86 Teuchos::RCP<const Tpetra::CrsMatrix<typename MatrixType::scalar_type,
87  typename MatrixType::local_ordinal_type,
88  typename MatrixType::global_ordinal_type,
89  typename MatrixType::node_type> >
91  getCrsMatrix() const {
92  typedef Tpetra::CrsMatrix<scalar_type, local_ordinal_type,
94  crs_matrix_type;
95  return Teuchos::rcp_dynamic_cast<const crs_matrix_type>(impl_.getMatrix());
96 }
97 
98 template <class MatrixType>
101  getDomainMap() const {
102  Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
104  A.is_null(), std::runtime_error,
105  "Ifpack2::Chebyshev::getDomainMap: The "
106  "input matrix A is null. Please call setMatrix() with a nonnull input "
107  "matrix before calling this method.");
108  return A->getDomainMap();
109 }
110 
111 template <class MatrixType>
114  getRangeMap() const {
115  Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
117  A.is_null(), std::runtime_error,
118  "Ifpack2::Chebyshev::getRangeMap: The "
119  "input matrix A is null. Please call setMatrix() with a nonnull input "
120  "matrix before calling this method.");
121  return A->getRangeMap();
122 }
123 
124 template <class MatrixType>
126  return impl_.hasTransposeApply();
127 }
128 
129 template <class MatrixType>
131  return NumInitialize_;
132 }
133 
134 template <class MatrixType>
136  return NumCompute_;
137 }
138 
139 template <class MatrixType>
141  return NumApply_;
142 }
143 
144 template <class MatrixType>
146  return InitializeTime_;
147 }
148 
149 template <class MatrixType>
151  return ComputeTime_;
152 }
153 
154 template <class MatrixType>
156  return ApplyTime_;
157 }
158 
159 template <class MatrixType>
161  return ComputeFlops_;
162 }
163 
164 template <class MatrixType>
166  return ApplyFlops_;
167 }
168 
169 template <class MatrixType>
171  Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
173  A.is_null(), std::runtime_error,
174  "Ifpack2::Chevyshev::getNodeSmootherComplexity: "
175  "The input matrix A is null. Please call setMatrix() with a nonnull "
176  "input matrix, then call compute(), before calling this method.");
177  // Chevyshev costs roughly one apply + one diagonal inverse per iteration
178  return A->getLocalNumRows() + A->getLocalNumEntries();
179 }
180 
181 template <class MatrixType>
183  apply(const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
184  Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
185  Teuchos::ETransp mode,
186  scalar_type alpha,
187  scalar_type beta) const {
189  const std::string timerName("Ifpack2::Chebyshev::apply");
190  if (TimerForApply_) {
191  timer = Teuchos::TimeMonitor::lookupCounter(timerName);
192  if (timer.is_null()) {
193  timer = Teuchos::TimeMonitor::getNewCounter(timerName);
194  }
195  }
196 
197  Teuchos::Time time = Teuchos::Time(timerName);
198  double startTime = time.wallTime();
199 
200  // Start timing here.
201  {
203  if (TimerForApply_)
204  timeMon = Teuchos::rcp(new Teuchos::TimeMonitor(*timer));
205 
206  // compute() calls initialize() if it hasn't already been called.
207  // Thus, we only need to check isComputed().
209  !isComputed(), std::runtime_error,
210  "Ifpack2::Chebyshev::apply(): You must call the compute() method before "
211  "you may call apply().");
213  X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
214  "Ifpack2::Chebyshev::apply(): X and Y must have the same number of "
215  "columns. X.getNumVectors() = "
216  << X.getNumVectors() << " != "
217  << "Y.getNumVectors() = " << Y.getNumVectors() << ".");
218  applyImpl(X, Y, mode, alpha, beta);
219  }
220  ++NumApply_;
221  ApplyTime_ += (time.wallTime() - startTime);
222 }
223 
224 template <class MatrixType>
226  applyMat(const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
227  Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
228  Teuchos::ETransp mode) const {
230  X.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
231  "Ifpack2::Chebyshev::applyMat: X.getNumVectors() != Y.getNumVectors().");
232 
233  Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
235  A.is_null(), std::runtime_error,
236  "Ifpack2::Chebyshev::applyMat: The input "
237  "matrix A is null. Please call setMatrix() with a nonnull input matrix "
238  "before calling this method.");
239 
240  A->apply(X, Y, mode);
241 }
242 
243 template <class MatrixType>
245  // We create the timer, but this method doesn't do anything, so
246  // there is no need to start the timer. The resulting total time
247  // will always be zero.
248  const std::string timerName("Ifpack2::Chebyshev::initialize");
250  if (timer.is_null()) {
251  timer = Teuchos::TimeMonitor::getNewCounter(timerName);
252  }
253  IsInitialized_ = true;
254  ++NumInitialize_;
255 }
256 
257 template <class MatrixType>
259  const std::string timerName("Ifpack2::Chebyshev::compute");
261  if (timer.is_null()) {
262  timer = Teuchos::TimeMonitor::getNewCounter(timerName);
263  }
264 
265  double startTime = timer->wallTime();
266 
267  // Start timing here.
268  {
269  Teuchos::TimeMonitor timeMon(*timer);
270  if (!isInitialized()) {
271  initialize();
272  }
273  IsComputed_ = false;
274  impl_.compute();
275  }
276  IsComputed_ = true;
277  ++NumCompute_;
278 
279  ComputeTime_ += (timer->wallTime() - startTime);
280 }
281 
282 template <class MatrixType>
284  std::ostringstream out;
285 
286  // Output is a valid YAML dictionary in flow style. If you don't
287  // like everything on a single line, you should call describe()
288  // instead.
289  out << "\"Ifpack2::Chebyshev\": {";
290  out << "Initialized: " << (isInitialized() ? "true" : "false") << ", "
291  << "Computed: " << (isComputed() ? "true" : "false") << ", ";
292 
293  out << impl_.description() << ", ";
294 
295  if (impl_.getMatrix().is_null()) {
296  out << "Matrix: null";
297  } else {
298  out << "Global matrix dimensions: ["
299  << impl_.getMatrix()->getGlobalNumRows() << ", "
300  << impl_.getMatrix()->getGlobalNumCols() << "]"
301  << ", Global nnz: " << impl_.getMatrix()->getGlobalNumEntries();
302  }
303 
304  out << "}";
305  return out.str();
306 }
307 
308 template <class MatrixType>
311  const Teuchos::EVerbosityLevel verbLevel) const {
312  using std::endl;
314 
315  // Default verbosity level is VERB_LOW
316  const Teuchos::EVerbosityLevel vl =
317  (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
318 
319  if (vl == Teuchos::VERB_NONE) {
320  return; // print NOTHING, not even the class name
321  }
322 
323  // By convention, describe() starts with a tab.
324  //
325  // This does affect all processes on which it's valid to print to
326  // 'out'. However, it does not actually print spaces to 'out'
327  // unless operator<< gets called, so it's safe to use on all
328  // processes.
329  Teuchos::OSTab tab0(out);
330  const int myRank = this->getComm()->getRank();
331  if (myRank == 0) {
332  // Output is a valid YAML dictionary.
333  // In particular, we quote keys with colons in them.
334  out << "\"Ifpack2::Chebyshev\":" << endl;
335  }
336 
337  Teuchos::OSTab tab1(out);
338  if (vl >= Teuchos::VERB_LOW && myRank == 0) {
339  out << "Template parameters:" << endl;
340  {
341  Teuchos::OSTab tab2(out);
342  out << "Scalar: " << TypeNameTraits<scalar_type>::name() << endl
343  << "LocalOrdinal: " << TypeNameTraits<local_ordinal_type>::name() << endl
344  << "GlobalOrdinal: " << TypeNameTraits<global_ordinal_type>::name() << endl
345  << "Device: " << TypeNameTraits<device_type>::name() << endl;
346  }
347  out << "Initialized: " << (isInitialized() ? "true" : "false") << endl
348  << "Computed: " << (isComputed() ? "true" : "false") << endl;
349  impl_.describe(out, vl);
350 
351  if (impl_.getMatrix().is_null()) {
352  out << "Matrix: null" << endl;
353  } else {
354  out << "Global matrix dimensions: ["
355  << impl_.getMatrix()->getGlobalNumRows() << ", "
356  << impl_.getMatrix()->getGlobalNumCols() << "]" << endl
357  << "Global nnz: " << impl_.getMatrix()->getGlobalNumEntries() << endl;
358  }
359  }
360 }
361 
362 template <class MatrixType>
364  applyImpl(const MV& X,
365  MV& Y,
366  Teuchos::ETransp /* mode */,
367  scalar_type alpha,
368  scalar_type beta) const {
369  using Teuchos::ArrayRCP;
370  using Teuchos::as;
371  using Teuchos::RCP;
372  using Teuchos::rcp;
373  using Teuchos::rcp_const_cast;
374  using Teuchos::rcpFromRef;
375 
376  const scalar_type zero = STS::zero();
377  const scalar_type one = STS::one();
378 
379  // Y = beta*Y + alpha*M*X.
380 
381  // If alpha == 0, then we don't need to do Chebyshev at all.
382  if (alpha == zero) {
383  if (beta == zero) { // Obey Sparse BLAS rules; avoid 0*NaN.
384  Y.putScalar(zero);
385  } else {
386  Y.scale(beta);
387  }
388  return;
389  }
390 
391  // If beta != 0, then we need to keep a (deep) copy of the initial
392  // value of Y, so that we can add beta*it to the Chebyshev result at
393  // the end. Usually this method is called with beta == 0, so we
394  // don't have to worry about caching Y_org.
395  RCP<MV> Y_orig;
396  if (beta != zero) {
397  Y_orig = rcp(new MV(Y, Teuchos::Copy));
398  }
399 
400  // If X and Y point to the same memory location, we need to use a
401  // (deep) copy of X (X_copy) as the input MV. Otherwise, just let
402  // X_copy point to X.
403  //
404  // This is hopefully an uncommon use case, so we don't bother to
405  // optimize for it by caching X_copy.
406  RCP<const MV> X_copy;
407  bool copiedInput = false;
408  if (X.aliases(Y)) {
409  X_copy = rcp(new MV(X, Teuchos::Copy));
410  copiedInput = true;
411  } else {
412  X_copy = rcpFromRef(X);
413  }
414 
415  // If alpha != 1, fold alpha into (a deep copy of) X.
416  //
417  // This is an uncommon use case, so we don't bother to optimize for
418  // it by caching X_copy. However, we do check whether we've already
419  // copied X above, to avoid a second copy.
420  if (alpha != one) {
421  RCP<MV> X_copy_nonConst = rcp_const_cast<MV>(X_copy);
422  if (!copiedInput) {
423  X_copy_nonConst = rcp(new MV(X, Teuchos::Copy));
424  copiedInput = true;
425  }
426  X_copy_nonConst->scale(alpha);
427  X_copy = rcp_const_cast<const MV>(X_copy_nonConst);
428  }
429 
430  impl_.apply(*X_copy, Y);
431 
432  if (beta != zero) {
433  Y.update(beta, *Y_orig, one); // Y = beta * Y_orig + 1 * Y
434  }
435 }
436 
437 template <class MatrixType>
438 typename MatrixType::scalar_type Chebyshev<MatrixType>::getLambdaMaxForApply() const {
439  return impl_.getLambdaMaxForApply();
440 }
441 
442 } // namespace Ifpack2
443 
444 #define IFPACK2_CHEBYSHEV_INSTANT(S, LO, GO, N) \
445  template class Ifpack2::Chebyshev<Tpetra::RowMatrix<S, LO, GO, N> >;
446 
447 #endif // IFPACK2_CHEBYSHEV_DEF_HPP
double getApplyFlops() const
The total number of floating-point operations taken by all calls to apply().
Definition: Ifpack2_Chebyshev_def.hpp:165
Teuchos::RCP< const Tpetra::CrsMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > > getCrsMatrix() const
Attempt to return the matrix A as a Tpetra::CrsMatrix.
Definition: Ifpack2_Chebyshev_def.hpp:91
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_Chebyshev_decl.hpp:187
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_Chebyshev_decl.hpp:181
double getApplyTime() const
The total time spent in all calls to apply().
Definition: Ifpack2_Chebyshev_def.hpp:155
T & get(const std::string &name, T def_value)
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_Chebyshev_def.hpp:45
static RCP< Time > getNewCounter(const std::string &name)
static RCP< Time > lookupCounter(const std::string &name)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void setParameters(const Teuchos::ParameterList &params)
Set (or reset) parameters.
Definition: Ifpack2_Chebyshev_def.hpp:54
double getComputeTime() const
The total time spent in all calls to compute().
Definition: Ifpack2_Chebyshev_def.hpp:150
int getNumApply() const
The total number of successful calls to apply().
Definition: Ifpack2_Chebyshev_def.hpp:140
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_Chebyshev_decl.hpp:193
void compute()
(Re)compute the left scaling, and (if applicable) estimate max and min eigenvalues of D_inv * A...
Definition: Ifpack2_Chebyshev_def.hpp:258
bool hasTransposeApply() const
Whether it&#39;s possible to apply the transpose of this operator.
Definition: Ifpack2_Chebyshev_def.hpp:125
T * getRawPtr() const
double getComputeFlops() const
The total number of floating-point operations taken by all calls to compute().
Definition: Ifpack2_Chebyshev_def.hpp:160
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Diagonally scaled Chebyshev iteration for Tpetra sparse matrices.
Definition: Ifpack2_Chebyshev_decl.hpp:165
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, returning the result in Y.
Definition: Ifpack2_Chebyshev_def.hpp:183
Chebyshev(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition: Ifpack2_Chebyshev_def.hpp:24
std::string description() const
A simple one-line description of this object.
Definition: Ifpack2_Chebyshev_def.hpp:283
void initialize()
Initialize the preconditioner.
Definition: Ifpack2_Chebyshev_def.hpp:244
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix is distributed.
Definition: Ifpack2_Chebyshev_def.hpp:68
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_Chebyshev_decl.hpp:184
int getNumInitialize() const
The total number of successful calls to initialize().
Definition: Ifpack2_Chebyshev_def.hpp:130
double getInitializeTime() const
The total time spent in all calls to initialize().
Definition: Ifpack2_Chebyshev_def.hpp:145
MatrixType::scalar_type getLambdaMaxForApply() const
The estimate of the maximum eigenvalue used in the apply().
Definition: Ifpack2_Chebyshev_def.hpp:438
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition: Ifpack2_Chebyshev_def.hpp:170
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to a Teuchos::FancyOStream.
Definition: Ifpack2_Chebyshev_def.hpp:310
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix for which this is a preconditioner.
Definition: Ifpack2_Chebyshev_def.hpp:81
TypeTo as(const TypeFrom &t)
bool isType(const std::string &name) const
Teuchos::RCP< const map_type > getDomainMap() const
The Tpetra::Map representing the domain of this operator.
Definition: Ifpack2_Chebyshev_def.hpp:101
static double wallTime()
virtual ~Chebyshev()
Destructor.
Definition: Ifpack2_Chebyshev_def.hpp:41
Teuchos::RCP< const map_type > getRangeMap() const
The Tpetra::Map representing the range of this operator.
Definition: Ifpack2_Chebyshev_def.hpp:114
int getNumCompute() const
The total number of successful calls to compute().
Definition: Ifpack2_Chebyshev_def.hpp:135
void applyMat(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) const
Compute Y = Op(A)*X, where Op(A) is either A, , or .
Definition: Ifpack2_Chebyshev_def.hpp:226
void setZeroStartingSolution(bool zeroStartingSolution)
Set this preconditioner&#39;s parameters.
Definition: Ifpack2_Chebyshev_def.hpp:62
bool is_null() const