Ifpack2 Templated Preconditioning Package Version 1.0
Loading...
Searching...
No Matches
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"
16#include "Teuchos_TypeNameTraits.hpp"
17#include <iostream>
18#include <sstream>
19
20
21namespace Ifpack2 {
22
23template<class MatrixType>
25Chebyshev (const Teuchos::RCP<const row_matrix_type>& A)
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
43template<class MatrixType>
46
47
48template<class MatrixType>
49void Chebyshev<MatrixType>::setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
50{
51 if (A.getRawPtr () != impl_.getMatrix ().getRawPtr ()) {
52 IsInitialized_ = false;
53 IsComputed_ = false;
54 impl_.setMatrix (A);
55 }
56}
57
58
59template<class MatrixType>
60void
61Chebyshev<MatrixType>::setParameters (const Teuchos::ParameterList& List)
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
70template<class MatrixType>
71void
73{
74 impl_.setZeroStartingSolution(zeroStartingSolution);
75}
76
77template<class MatrixType>
78Teuchos::RCP<const Teuchos::Comm<int> >
80{
81 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix ();
82 TEUCHOS_TEST_FOR_EXCEPTION(
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
90template<class MatrixType>
91Teuchos::RCP<const typename Chebyshev<MatrixType>::row_matrix_type>
93getMatrix() const {
94 return impl_.getMatrix ();
95}
96
97
98template<class MatrixType>
99Teuchos::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> >
104getCrsMatrix() 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
111template<class MatrixType>
112Teuchos::RCP<const typename Chebyshev<MatrixType>::map_type>
114getDomainMap () const
115{
116 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix ();
117 TEUCHOS_TEST_FOR_EXCEPTION(
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
125template<class MatrixType>
126Teuchos::RCP<const typename Chebyshev<MatrixType>::map_type>
128getRangeMap () const
129{
130 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix ();
131 TEUCHOS_TEST_FOR_EXCEPTION(
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
139template<class MatrixType>
141 return impl_.hasTransposeApply ();
142}
143
144
145template<class MatrixType>
147 return NumInitialize_;
148}
149
150
151template<class MatrixType>
153 return NumCompute_;
154}
155
156
157template<class MatrixType>
159 return NumApply_;
160}
161
162
163template<class MatrixType>
165 return InitializeTime_;
166}
167
168
169template<class MatrixType>
171 return ComputeTime_;
172}
173
174
175template<class MatrixType>
177 return ApplyTime_;
178}
179
180
181template<class MatrixType>
183 return ComputeFlops_;
184}
185
186
187template<class MatrixType>
189 return ApplyFlops_;
190}
191
192template<class MatrixType>
194 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
195 TEUCHOS_TEST_FOR_EXCEPTION(
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
205template<class MatrixType>
206void
208apply (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{
214 Teuchos::RCP<Teuchos::Time> timer;
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 {
228 Teuchos::RCP<Teuchos::TimeMonitor> timeMon;
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().
234 TEUCHOS_TEST_FOR_EXCEPTION(
235 ! isComputed (), std::runtime_error,
236 "Ifpack2::Chebyshev::apply(): You must call the compute() method before "
237 "you may call apply().");
238 TEUCHOS_TEST_FOR_EXCEPTION(
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
250template<class MatrixType>
251void
253applyMat (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{
257 TEUCHOS_TEST_FOR_EXCEPTION(
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 ();
262 TEUCHOS_TEST_FOR_EXCEPTION(
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
271template<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");
277 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
278 if (timer.is_null ()) {
279 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
280 }
281 IsInitialized_ = true;
282 ++NumInitialize_;
283}
284
285
286template<class MatrixType>
288{
289 const std::string timerName ("Ifpack2::Chebyshev::compute");
290 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
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
313template <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
341template <class MatrixType>
343describe (Teuchos::FancyOStream& out,
344 const Teuchos::EVerbosityLevel verbLevel) const
345{
346 using Teuchos::TypeNameTraits;
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
397template<class MatrixType>
398void
400applyImpl (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
476template<class MatrixType>
477typename 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
Diagonally scaled Chebyshev iteration for Tpetra sparse matrices.
Definition Ifpack2_Chebyshev_decl.hpp:174
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:189
double getInitializeTime() const
The total time spent in all calls to initialize().
Definition Ifpack2_Chebyshev_def.hpp:164
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
std::string description() const
A simple one-line description of this object.
Definition Ifpack2_Chebyshev_def.hpp:314
Chebyshev(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition Ifpack2_Chebyshev_def.hpp:25
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 map_type > getRangeMap() const
The Tpetra::Map representing the range of this operator.
Definition Ifpack2_Chebyshev_def.hpp:128
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 initialize()
Initialize the preconditioner.
Definition Ifpack2_Chebyshev_def.hpp:272
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix for which this is a preconditioner.
Definition Ifpack2_Chebyshev_def.hpp:93
int getNumApply() const
The total number of successful calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:158
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:186
bool isInitialized() const
Definition Ifpack2_Chebyshev_decl.hpp:408
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:195
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition Ifpack2_Chebyshev_def.hpp:193
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:183
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition Ifpack2_Chebyshev_def.hpp:49
bool isComputed() const
Definition Ifpack2_Chebyshev_decl.hpp:455
int getNumCompute() const
The total number of successful calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:152
void setParameters(const Teuchos::ParameterList &params)
Set (or reset) parameters.
Definition Ifpack2_Chebyshev_def.hpp:61
double getComputeFlops() const
The total number of floating-point operations taken by all calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:182
double getComputeTime() const
The total time spent in all calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:170
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
void setZeroStartingSolution(bool zeroStartingSolution)
Set this preconditioner's parameters.
Definition Ifpack2_Chebyshev_def.hpp:72
Teuchos::RCP< const map_type > getDomainMap() const
The Tpetra::Map representing the domain of this operator.
Definition Ifpack2_Chebyshev_def.hpp:114
int getNumInitialize() const
The total number of successful calls to initialize().
Definition Ifpack2_Chebyshev_def.hpp:146
virtual ~Chebyshev()
Destructor.
Definition Ifpack2_Chebyshev_def.hpp:44
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix is distributed.
Definition Ifpack2_Chebyshev_def.hpp:79
double getApplyFlops() const
The total number of floating-point operations taken by all calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:188
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
MatrixType::scalar_type getLambdaMaxForApply() const
The estimate of the maximum eigenvalue used in the apply().
Definition Ifpack2_Chebyshev_def.hpp:477
bool hasTransposeApply() const
Whether it's possible to apply the transpose of this operator.
Definition Ifpack2_Chebyshev_def.hpp:140
double getApplyTime() const
The total time spent in all calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:176
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:41