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
20namespace Ifpack2 {
21
22template <class MatrixType>
24 Chebyshev(const Teuchos::RCP<const row_matrix_type>& A)
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
40template <class MatrixType>
43
44template <class MatrixType>
45void Chebyshev<MatrixType>::setMatrix(const Teuchos::RCP<const row_matrix_type>& A) {
46 if (A.getRawPtr() != impl_.getMatrix().getRawPtr()) {
47 IsInitialized_ = false;
48 IsComputed_ = false;
49 impl_.setMatrix(A);
50 }
51}
52
53template <class MatrixType>
54void Chebyshev<MatrixType>::setParameters(const Teuchos::ParameterList& List) {
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
61template <class MatrixType>
62void Chebyshev<MatrixType>::setZeroStartingSolution(bool zeroStartingSolution) {
63 impl_.setZeroStartingSolution(zeroStartingSolution);
64}
65
66template <class MatrixType>
67Teuchos::RCP<const Teuchos::Comm<int> >
69 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
70 TEUCHOS_TEST_FOR_EXCEPTION(
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
78template <class MatrixType>
79Teuchos::RCP<const typename Chebyshev<MatrixType>::row_matrix_type>
81 getMatrix() const {
82 return impl_.getMatrix();
83}
84
85template <class MatrixType>
86Teuchos::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
98template <class MatrixType>
99Teuchos::RCP<const typename Chebyshev<MatrixType>::map_type>
101 getDomainMap() const {
102 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
103 TEUCHOS_TEST_FOR_EXCEPTION(
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
111template <class MatrixType>
112Teuchos::RCP<const typename Chebyshev<MatrixType>::map_type>
114 getRangeMap() const {
115 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
116 TEUCHOS_TEST_FOR_EXCEPTION(
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
124template <class MatrixType>
126 return impl_.hasTransposeApply();
127}
128
129template <class MatrixType>
131 return NumInitialize_;
132}
133
134template <class MatrixType>
136 return NumCompute_;
137}
138
139template <class MatrixType>
141 return NumApply_;
142}
143
144template <class MatrixType>
146 return InitializeTime_;
147}
148
149template <class MatrixType>
151 return ComputeTime_;
152}
153
154template <class MatrixType>
156 return ApplyTime_;
157}
158
159template <class MatrixType>
161 return ComputeFlops_;
162}
163
164template <class MatrixType>
166 return ApplyFlops_;
167}
168
169template <class MatrixType>
171 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
172 TEUCHOS_TEST_FOR_EXCEPTION(
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
181template <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 {
188 Teuchos::RCP<Teuchos::Time> timer;
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 {
202 Teuchos::RCP<Teuchos::TimeMonitor> timeMon;
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().
208 TEUCHOS_TEST_FOR_EXCEPTION(
209 !isComputed(), std::runtime_error,
210 "Ifpack2::Chebyshev::apply(): You must call the compute() method before "
211 "you may call apply().");
212 TEUCHOS_TEST_FOR_EXCEPTION(
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
224template <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 {
229 TEUCHOS_TEST_FOR_EXCEPTION(
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();
234 TEUCHOS_TEST_FOR_EXCEPTION(
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
243template <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");
249 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter(timerName);
250 if (timer.is_null()) {
251 timer = Teuchos::TimeMonitor::getNewCounter(timerName);
252 }
253 IsInitialized_ = true;
254 ++NumInitialize_;
255}
256
257template <class MatrixType>
259 const std::string timerName("Ifpack2::Chebyshev::compute");
260 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter(timerName);
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
282template <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
308template <class MatrixType>
310 describe(Teuchos::FancyOStream& out,
311 const Teuchos::EVerbosityLevel verbLevel) const {
312 using std::endl;
313 using Teuchos::TypeNameTraits;
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
362template <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
437template <class MatrixType>
438typename 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
Diagonally scaled Chebyshev iteration for Tpetra sparse matrices.
Definition Ifpack2_Chebyshev_decl.hpp:172
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:187
double getInitializeTime() const
The total time spent in all calls to initialize().
Definition Ifpack2_Chebyshev_def.hpp:145
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
std::string description() const
A simple one-line description of this object.
Definition Ifpack2_Chebyshev_def.hpp:283
Chebyshev(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition Ifpack2_Chebyshev_def.hpp:24
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 map_type > getRangeMap() const
The Tpetra::Map representing the range of this operator.
Definition Ifpack2_Chebyshev_def.hpp:114
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 initialize()
Initialize the preconditioner.
Definition Ifpack2_Chebyshev_def.hpp:244
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix for which this is a preconditioner.
Definition Ifpack2_Chebyshev_def.hpp:81
int getNumApply() const
The total number of successful calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:140
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:184
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:193
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition Ifpack2_Chebyshev_def.hpp:170
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:181
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition Ifpack2_Chebyshev_def.hpp:45
int getNumCompute() const
The total number of successful calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:135
void setParameters(const Teuchos::ParameterList &params)
Set (or reset) parameters.
Definition Ifpack2_Chebyshev_def.hpp:54
double getComputeFlops() const
The total number of floating-point operations taken by all calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:160
double getComputeTime() const
The total time spent in all calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:150
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
void setZeroStartingSolution(bool zeroStartingSolution)
Set this preconditioner's parameters.
Definition Ifpack2_Chebyshev_def.hpp:62
Teuchos::RCP< const map_type > getDomainMap() const
The Tpetra::Map representing the domain of this operator.
Definition Ifpack2_Chebyshev_def.hpp:101
int getNumInitialize() const
The total number of successful calls to initialize().
Definition Ifpack2_Chebyshev_def.hpp:130
virtual ~Chebyshev()
Destructor.
Definition Ifpack2_Chebyshev_def.hpp:41
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix is distributed.
Definition Ifpack2_Chebyshev_def.hpp:68
double getApplyFlops() const
The total number of floating-point operations taken by all calls to apply().
Definition Ifpack2_Chebyshev_def.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
MatrixType::scalar_type getLambdaMaxForApply() const
The estimate of the maximum eigenvalue used in the apply().
Definition Ifpack2_Chebyshev_def.hpp:438
bool hasTransposeApply() const
Whether it's possible to apply the transpose of this operator.
Definition Ifpack2_Chebyshev_def.hpp:125
double getApplyTime() const
The total time spent in all calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:155
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:40