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