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