Ifpack2 Templated Preconditioning Package Version 1.0
Loading...
Searching...
No Matches
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"
49#include "Teuchos_TypeNameTraits.hpp"
50#include <iostream>
51#include <sstream>
52
53
54namespace Ifpack2 {
55
56template<class MatrixType>
58Chebyshev (const Teuchos::RCP<const row_matrix_type>& A)
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
76template<class MatrixType>
79
80
81template<class MatrixType>
82void Chebyshev<MatrixType>::setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
83{
84 if (A.getRawPtr () != impl_.getMatrix ().getRawPtr ()) {
85 IsInitialized_ = false;
86 IsComputed_ = false;
87 impl_.setMatrix (A);
88 }
89}
90
91
92template<class MatrixType>
93void
94Chebyshev<MatrixType>::setParameters (const Teuchos::ParameterList& List)
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
103template<class MatrixType>
104void
106{
107 impl_.setZeroStartingSolution(zeroStartingSolution);
108}
109
110template<class MatrixType>
111Teuchos::RCP<const Teuchos::Comm<int> >
113{
114 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix ();
115 TEUCHOS_TEST_FOR_EXCEPTION(
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
123template<class MatrixType>
124Teuchos::RCP<const typename Chebyshev<MatrixType>::row_matrix_type>
126getMatrix() const {
127 return impl_.getMatrix ();
128}
129
130
131template<class MatrixType>
132Teuchos::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> >
137getCrsMatrix() 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
144template<class MatrixType>
145Teuchos::RCP<const typename Chebyshev<MatrixType>::map_type>
147getDomainMap () const
148{
149 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix ();
150 TEUCHOS_TEST_FOR_EXCEPTION(
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
158template<class MatrixType>
159Teuchos::RCP<const typename Chebyshev<MatrixType>::map_type>
161getRangeMap () const
162{
163 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix ();
164 TEUCHOS_TEST_FOR_EXCEPTION(
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
172template<class MatrixType>
174 return impl_.hasTransposeApply ();
175}
176
177
178template<class MatrixType>
180 return NumInitialize_;
181}
182
183
184template<class MatrixType>
186 return NumCompute_;
187}
188
189
190template<class MatrixType>
192 return NumApply_;
193}
194
195
196template<class MatrixType>
198 return InitializeTime_;
199}
200
201
202template<class MatrixType>
204 return ComputeTime_;
205}
206
207
208template<class MatrixType>
210 return ApplyTime_;
211}
212
213
214template<class MatrixType>
216 return ComputeFlops_;
217}
218
219
220template<class MatrixType>
222 return ApplyFlops_;
223}
224
225template<class MatrixType>
227 Teuchos::RCP<const row_matrix_type> A = impl_.getMatrix();
228 TEUCHOS_TEST_FOR_EXCEPTION(
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
238template<class MatrixType>
239void
241apply (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{
247 Teuchos::RCP<Teuchos::Time> timer;
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 {
261 Teuchos::RCP<Teuchos::TimeMonitor> timeMon;
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().
267 TEUCHOS_TEST_FOR_EXCEPTION(
268 ! isComputed (), std::runtime_error,
269 "Ifpack2::Chebyshev::apply(): You must call the compute() method before "
270 "you may call apply().");
271 TEUCHOS_TEST_FOR_EXCEPTION(
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
283template<class MatrixType>
284void
286applyMat (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{
290 TEUCHOS_TEST_FOR_EXCEPTION(
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 ();
295 TEUCHOS_TEST_FOR_EXCEPTION(
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
304template<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");
310 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
311 if (timer.is_null ()) {
312 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
313 }
314 IsInitialized_ = true;
315 ++NumInitialize_;
316}
317
318
319template<class MatrixType>
321{
322 const std::string timerName ("Ifpack2::Chebyshev::compute");
323 Teuchos::RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
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
346template <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
374template <class MatrixType>
376describe (Teuchos::FancyOStream& out,
377 const Teuchos::EVerbosityLevel verbLevel) const
378{
379 using Teuchos::TypeNameTraits;
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
430template<class MatrixType>
431void
433applyImpl (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
509template<class MatrixType>
510typename 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
Diagonally scaled Chebyshev iteration for Tpetra sparse matrices.
Definition Ifpack2_Chebyshev_decl.hpp:208
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:223
double getInitializeTime() const
The total time spent in all calls to initialize().
Definition Ifpack2_Chebyshev_def.hpp:197
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
std::string description() const
A simple one-line description of this object.
Definition Ifpack2_Chebyshev_def.hpp:347
Chebyshev(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition Ifpack2_Chebyshev_def.hpp:58
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 map_type > getRangeMap() const
The Tpetra::Map representing the range of this operator.
Definition Ifpack2_Chebyshev_def.hpp:161
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 initialize()
Initialize the preconditioner.
Definition Ifpack2_Chebyshev_def.hpp:305
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix for which this is a preconditioner.
Definition Ifpack2_Chebyshev_def.hpp:126
int getNumApply() const
The total number of successful calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:191
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:220
bool isInitialized() const
Definition Ifpack2_Chebyshev_decl.hpp:442
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:229
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition Ifpack2_Chebyshev_def.hpp:226
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition Ifpack2_Chebyshev_decl.hpp:217
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition Ifpack2_Chebyshev_def.hpp:82
bool isComputed() const
Definition Ifpack2_Chebyshev_decl.hpp:489
int getNumCompute() const
The total number of successful calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:185
void setParameters(const Teuchos::ParameterList &params)
Set (or reset) parameters.
Definition Ifpack2_Chebyshev_def.hpp:94
double getComputeFlops() const
The total number of floating-point operations taken by all calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:215
double getComputeTime() const
The total time spent in all calls to compute().
Definition Ifpack2_Chebyshev_def.hpp:203
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
void setZeroStartingSolution(bool zeroStartingSolution)
Set this preconditioner's parameters.
Definition Ifpack2_Chebyshev_def.hpp:105
Teuchos::RCP< const map_type > getDomainMap() const
The Tpetra::Map representing the domain of this operator.
Definition Ifpack2_Chebyshev_def.hpp:147
int getNumInitialize() const
The total number of successful calls to initialize().
Definition Ifpack2_Chebyshev_def.hpp:179
virtual ~Chebyshev()
Destructor.
Definition Ifpack2_Chebyshev_def.hpp:77
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix is distributed.
Definition Ifpack2_Chebyshev_def.hpp:112
double getApplyFlops() const
The total number of floating-point operations taken by all calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:221
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
MatrixType::scalar_type getLambdaMaxForApply() const
The estimate of the maximum eigenvalue used in the apply().
Definition Ifpack2_Chebyshev_def.hpp:510
bool hasTransposeApply() const
Whether it's possible to apply the transpose of this operator.
Definition Ifpack2_Chebyshev_def.hpp:173
double getApplyTime() const
The total time spent in all calls to apply().
Definition Ifpack2_Chebyshev_def.hpp:209
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:74