Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_Diagonal_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_DIAGONAL_DEF_HPP
11 #define IFPACK2_DIAGONAL_DEF_HPP
12 
13 #include "Ifpack2_Diagonal_decl.hpp"
14 #include "Tpetra_CrsMatrix.hpp"
15 
16 namespace Ifpack2 {
17 
18 template <class MatrixType>
20  : matrix_(A)
21  , initializeTime_(0.0)
22  , computeTime_(0.0)
23  , applyTime_(0.0)
24  , numInitialize_(0)
25  , numCompute_(0)
26  , numApply_(0)
27  , isInitialized_(false)
28  , isComputed_(false) {}
29 
30 template <class MatrixType>
32  : matrix_(A)
33  , initializeTime_(0.0)
34  , computeTime_(0.0)
35  , applyTime_(0.0)
36  , numInitialize_(0)
37  , numCompute_(0)
38  , numApply_(0)
39  , isInitialized_(false)
40  , isComputed_(false) {}
41 
42 template <class MatrixType>
44  : userInverseDiag_(diag)
45  , inverseDiag_(diag)
46  , initializeTime_(0.0)
47  , computeTime_(0.0)
48  , applyTime_(0.0)
49  , numInitialize_(0)
50  , numCompute_(0)
51  , numApply_(0)
52  , isInitialized_(false)
53  , isComputed_(false) {}
54 
55 template <class MatrixType>
57 
58 template <class MatrixType>
61  if (matrix_.is_null()) {
62  if (userInverseDiag_.is_null()) {
64  true, std::runtime_error,
65  "Ifpack2::Diagonal::getDomainMap: "
66  "The input matrix A is null, and you did not provide a vector of "
67  "inverse diagonal entries. Please call setMatrix() with a nonnull "
68  "input matrix before calling this method.");
69  } else {
70  return userInverseDiag_->getMap();
71  }
72  } else {
73  return matrix_->getDomainMap();
74  }
75 }
76 
77 template <class MatrixType>
80  if (matrix_.is_null()) {
81  if (userInverseDiag_.is_null()) {
83  true, std::runtime_error,
84  "Ifpack2::Diagonal::getRangeMap: "
85  "The input matrix A is null, and you did not provide a vector of "
86  "inverse diagonal entries. Please call setMatrix() with a nonnull "
87  "input matrix before calling this method.");
88  } else {
89  return userInverseDiag_->getMap();
90  }
91  } else {
92  return matrix_->getRangeMap();
93  }
94 }
95 
96 template <class MatrixType>
99 
100 template <class MatrixType>
102  inverseDiag_ = Teuchos::null;
103  offsets_ = offsets_type();
104  isInitialized_ = false;
105  isComputed_ = false;
106 }
107 
108 template <class MatrixType>
111  if (A.getRawPtr() != matrix_.getRawPtr()) { // it's a different matrix
112  reset();
113  matrix_ = A;
114  }
115 }
116 
117 template <class MatrixType>
119  // Either the matrix to precondition must be nonnull, or the user
120  // must have provided a Vector of diagonal entries.
122  matrix_.is_null() && userInverseDiag_.is_null(), std::runtime_error,
123  "Ifpack2::Diagonal::initialize: The matrix to precondition is null, "
124  "and you did not provide a Tpetra::Vector of diagonal entries. "
125  "Please call setMatrix() with a nonnull input before calling this method.");
126 
127  // If the user did provide an input matrix, then that takes
128  // precedence over the vector of inverse diagonal entries, if they
129  // provided one earlier. This is only possible if they created this
130  // Diagonal instance using the constructor that takes a
131  // Tpetra::Vector pointer, and then called setMatrix() with a
132  // nonnull input matrix.
133  if (!matrix_.is_null()) {
134  // If you call initialize(), it means that you are asserting that
135  // the structure of the input sparse matrix may have changed.
136  // This means we should always recompute the diagonal offsets, if
137  // the input matrix is a Tpetra::CrsMatrix.
139  Teuchos::rcp_dynamic_cast<const crs_matrix_type>(matrix_);
140 
141  if (A_crs.is_null()) {
142  offsets_ = offsets_type(); // offsets are no longer valid
143  } else {
144  const size_t lclNumRows = A_crs->getLocalNumRows();
145  if (offsets_.extent(0) < lclNumRows) {
146  offsets_ = offsets_type(); // clear first to save memory
147  offsets_ = offsets_type("offsets", lclNumRows);
148  }
149  A_crs->getCrsGraph()->getLocalDiagOffsets(offsets_);
150  }
151  }
152 
153  isInitialized_ = true;
154  ++numInitialize_;
155 }
156 
157 template <class MatrixType>
159  // Either the matrix to precondition must be nonnull, or the user
160  // must have provided a Vector of diagonal entries.
162  matrix_.is_null() && userInverseDiag_.is_null(), std::runtime_error,
163  "Ifpack2::Diagonal::compute: The matrix to precondition is null, "
164  "and you did not provide a Tpetra::Vector of diagonal entries. "
165  "Please call setMatrix() with a nonnull input before calling this method.");
166 
167  if (!isInitialized_) {
168  initialize();
169  }
170 
171  // If the user did provide an input matrix, then that takes
172  // precedence over the vector of inverse diagonal entries, if they
173  // provided one earlier. This is only possible if they created this
174  // Diagonal instance using the constructor that takes a
175  // Tpetra::Vector pointer, and then called setMatrix() with a
176  // nonnull input matrix.
177  if (matrix_.is_null()) { // accept the user's diagonal
178  inverseDiag_ = userInverseDiag_;
179  } else {
180  Teuchos::RCP<vector_type> tmpVec(new vector_type(matrix_->getRowMap()));
182  Teuchos::rcp_dynamic_cast<const crs_matrix_type>(matrix_);
183  if (A_crs.is_null()) {
184  // Get the diagonal entries from the Tpetra::RowMatrix.
185  matrix_->getLocalDiagCopy(*tmpVec);
186  } else {
187  // Get the diagonal entries from the Tpetra::CrsMatrix using the
188  // precomputed offsets.
189  A_crs->getLocalDiagCopy(*tmpVec, offsets_);
190  }
191  tmpVec->reciprocal(*tmpVec); // invert the diagonal entries
192  inverseDiag_ = tmpVec;
193  }
194 
195  isComputed_ = true;
196  ++numCompute_;
197 }
198 
199 template <class MatrixType>
201  apply(const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
202  Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
203  Teuchos::ETransp /*mode*/,
204  scalar_type alpha,
205  scalar_type beta) const {
207  !isComputed(), std::runtime_error,
208  "Ifpack2::Diagonal::apply: You "
209  "must first call compute() before you may call apply(). Once you have "
210  "called compute(), you need not call it again unless the values in the "
211  "matrix have changed, or unless you have called setMatrix().");
212 
213  // FIXME (mfh 12 Sep 2014) This assumes that row Map == range Map ==
214  // domain Map. If the preconditioner has a matrix, we should ask
215  // the matrix whether we need to do an Import before and/or an
216  // Export after.
217 
218  Y.elementWiseMultiply(alpha, *inverseDiag_, X, beta);
219  ++numApply_;
220 }
221 
222 template <class MatrixType>
224  return numInitialize_;
225 }
226 
227 template <class MatrixType>
229  return numCompute_;
230 }
231 
232 template <class MatrixType>
234  return numApply_;
235 }
236 
237 template <class MatrixType>
239  return initializeTime_;
240 }
241 
242 template <class MatrixType>
244  return computeTime_;
245 }
246 
247 template <class MatrixType>
249  return applyTime_;
250 }
251 
252 template <class MatrixType>
254  std::ostringstream out;
255 
256  // Output is a valid YAML dictionary in flow style. If you don't
257  // like everything on a single line, you should call describe()
258  // instead.
259  out << "\"Ifpack2::Diagonal\": "
260  << "{";
261  if (this->getObjectLabel() != "") {
262  out << "Label: \"" << this->getObjectLabel() << "\", ";
263  }
264  if (matrix_.is_null()) {
265  out << "Matrix: null";
266  } else {
267  out << "Matrix: not null"
268  << ", Global matrix dimensions: ["
269  << matrix_->getGlobalNumRows() << ", "
270  << matrix_->getGlobalNumCols() << "]";
271  }
272 
273  out << "}";
274  return out.str();
275 }
276 
277 template <class MatrixType>
280  const Teuchos::EVerbosityLevel verbLevel) const {
281  using std::endl;
282 
283  const Teuchos::EVerbosityLevel vl =
284  (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
285  if (vl != Teuchos::VERB_NONE) {
286  Teuchos::OSTab tab0(out);
287  out << "\"Ifpack2::Diagonal\":";
288  Teuchos::OSTab tab1(out);
289  out << "Template parameter: "
291  if (this->getObjectLabel() != "") {
292  out << "Label: \"" << this->getObjectLabel() << "\", ";
293  }
294  out << "Number of initialize calls: " << numInitialize_ << endl
295  << "Number of compute calls: " << numCompute_ << endl
296  << "Number of apply calls: " << numApply_ << endl;
297  }
298 }
299 
300 } // namespace Ifpack2
301 
302 #define IFPACK2_DIAGONAL_INSTANT(S, LO, GO, N) \
303  template class Ifpack2::Diagonal<Tpetra::RowMatrix<S, LO, GO, N> >;
304 
305 #endif
std::string description() const
Return a one-line description of this object.
Definition: Ifpack2_Diagonal_def.hpp:253
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, putting the result in Y.
Definition: Ifpack2_Diagonal_def.hpp:201
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Diagonal preconditioner.
Definition: Ifpack2_Diagonal_decl.hpp:38
Teuchos::RCP< const map_type > getDomainMap() const
The Tpetra::Map representing this operator&#39;s domain.
Definition: Ifpack2_Diagonal_def.hpp:60
T * getRawPtr() const
Diagonal(const Teuchos::RCP< const row_matrix_type > &A)
Constructor that takes a Tpetra::RowMatrix.
Definition: Ifpack2_Diagonal_def.hpp:19
void compute()
Compute the preconditioner.
Definition: Ifpack2_Diagonal_def.hpp:158
virtual ~Diagonal()
Destructor.
Definition: Ifpack2_Diagonal_def.hpp:56
double getComputeTime() const
Return the time spent in compute().
Definition: Ifpack2_Diagonal_def.hpp:243
int getNumCompute() const
Return the number of calls to compute().
Definition: Ifpack2_Diagonal_def.hpp:228
double getInitializeTime() const
Return the time spent in initialize().
Definition: Ifpack2_Diagonal_def.hpp:238
void setParameters(const Teuchos::ParameterList &params)
Sets parameters on this object.
Definition: Ifpack2_Diagonal_def.hpp:98
int getNumInitialize() const
Return the number of calls to initialize().
Definition: Ifpack2_Diagonal_def.hpp:223
double getApplyTime() const
Return the time spent in apply().
Definition: Ifpack2_Diagonal_def.hpp:248
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_Diagonal_def.hpp:110
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object with some verbosity level to an FancyOStream object.
Definition: Ifpack2_Diagonal_def.hpp:279
Teuchos::RCP< const map_type > getRangeMap() const
The Tpetra::Map representing this operator&#39;s range.
Definition: Ifpack2_Diagonal_def.hpp:79
void initialize()
Initialize.
Definition: Ifpack2_Diagonal_def.hpp:118
Tpetra::CrsMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > crs_matrix_type
Tpetra::CrsMatrix specialization used by this class.
Definition: Ifpack2_Diagonal_decl.hpp:60
int getNumApply() const
Return the number of calls to apply().
Definition: Ifpack2_Diagonal_def.hpp:233
static std::string name()
Tpetra::Vector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > vector_type
Tpetra::Vector specialization used by this class.
Definition: Ifpack2_Diagonal_decl.hpp:73
bool is_null() const