Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_Hiptmair_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_HIPTMAIR_DEF_HPP
44 #define IFPACK2_HIPTMAIR_DEF_HPP
45 
46 #include "Ifpack2_Details_OneLevelFactory.hpp"
47 #include "Ifpack2_Parameters.hpp"
48 #include "Teuchos_TimeMonitor.hpp"
49 #include "Tpetra_MultiVector.hpp"
50 #include <cmath>
51 #include <iostream>
52 #include <sstream>
53 
54 namespace Ifpack2 {
55 
56 template <class MatrixType>
61  A_ (A),
62  PtAP_ (PtAP),
63  P_ (P),
64  // Default values
65  precType1_ ("CHEBYSHEV"),
66  precType2_ ("CHEBYSHEV"),
67  preOrPost_ ("both"),
68  ZeroStartingSolution_ (true),
69  // General
70  IsInitialized_ (false),
71  IsComputed_ (false),
72  NumInitialize_ (0),
73  NumCompute_ (0),
74  NumApply_ (0),
75  InitializeTime_ (0.0),
76  ComputeTime_ (0.0),
77  ApplyTime_ (0.0)
78 {}
79 
80 
81 template <class MatrixType>
83 
84 template <class MatrixType>
86 {
87  using Teuchos::as;
91 
92  ParameterList params = plist;
93 
94  // Get the current parameters' values. We don't assign to the
95  // instance data directly until we've gotten all the parameters.
96  // This ensures "transactional" semantics, so that if attempting to
97  // get some parameter throws an exception, the class' state doesn't
98  // change.
99  std::string precType1 = precType1_;
100  std::string precType2 = precType2_;
101  std::string preOrPost = preOrPost_;
102  Teuchos::ParameterList precList1 = precList1_;
103  Teuchos::ParameterList precList2 = precList2_;
104  bool zeroStartingSolution = ZeroStartingSolution_;
105 
106  precType1 = params.get("hiptmair: smoother type 1", precType1);
107  precType2 = params.get("hiptmair: smoother type 2", precType2);
108  precList1 = params.get("hiptmair: smoother list 1", precList1);
109  precList2 = params.get("hiptmair: smoother list 2", precList2);
110  preOrPost = params.get("hiptmair: pre or post", preOrPost);
111  zeroStartingSolution = params.get("hiptmair: zero starting solution",
112  zeroStartingSolution);
113 
114  // "Commit" the new values to the instance data.
115  precType1_ = precType1;
116  precType2_ = precType2;
117  precList1_ = precList1;
118  precList2_ = precList2;
119  preOrPost_ = preOrPost;
120  ZeroStartingSolution_ = zeroStartingSolution;
121 }
122 
123 
124 template <class MatrixType>
128  A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getComm: "
129  "The input matrix A is null. Please call setMatrix() with a nonnull "
130  "input matrix before calling this method.");
131  return A_->getComm ();
132 }
133 
134 
135 template <class MatrixType>
138  return A_;
139 }
140 
141 
142 template <class MatrixType>
145 {
147  A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getDomainMap: "
148  "The input matrix A is null. Please call setMatrix() with a nonnull "
149  "input matrix before calling this method.");
150  return A_->getDomainMap ();
151 }
152 
153 
154 template <class MatrixType>
157 {
159  A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getRangeMap: "
160  "The input matrix A is null. Please call setMatrix() with a nonnull "
161  "input matrix before calling this method.");
162  return A_->getRangeMap ();
163 }
164 
165 
166 template <class MatrixType>
168  // FIXME (mfh 17 Jan 2014) apply() does not currently work with mode
169  // != NO_TRANS, so it's correct to return false here.
170  return false;
171 }
172 
173 
174 template <class MatrixType>
176  return NumInitialize_;
177 }
178 
179 
180 template <class MatrixType>
182  return NumCompute_;
183 }
184 
185 
186 template <class MatrixType>
188  return NumApply_;
189 }
190 
191 
192 template <class MatrixType>
194  return InitializeTime_;
195 }
196 
197 
198 template <class MatrixType>
200  return ComputeTime_;
201 }
202 
203 
204 template <class MatrixType>
206  return ApplyTime_;
207 }
208 
209 
210 template <class MatrixType>
212 {
214  using Teuchos::RCP;
215  using Teuchos::rcp;
216 
218  A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::initialize: "
219  "The input matrix A is null. Please call setMatrix() with a nonnull "
220  "input matrix before calling this method.");
221 
222  // clear any previous allocation
223  IsInitialized_ = false;
224  IsComputed_ = false;
225 
226  Teuchos::Time timer ("initialize");
227  { // The body of code to time
228  Teuchos::TimeMonitor timeMon (timer);
229 
231 
232  ifpack2_prec1_=factory.create(precType1_,A_);
233  ifpack2_prec1_->initialize();
234  ifpack2_prec1_->setParameters(precList1_);
235 
236  ifpack2_prec2_=factory.create(precType2_,PtAP_);
237  ifpack2_prec2_->initialize();
238  ifpack2_prec2_->setParameters(precList2_);
239 
240  }
241  IsInitialized_ = true;
242  ++NumInitialize_;
243  InitializeTime_ += timer.totalElapsedTime ();
244 }
245 
246 
247 template <class MatrixType>
249 {
251  A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::compute: "
252  "The input matrix A is null. Please call setMatrix() with a nonnull "
253  "input matrix before calling this method.");
254 
255  // Don't time the initialize(); that gets timed separately.
256  if (! isInitialized ()) {
257  initialize ();
258  }
259 
260  Teuchos::Time timer ("compute");
261  { // The body of code to time
262  Teuchos::TimeMonitor timeMon (timer);
263  ifpack2_prec1_->compute();
264  ifpack2_prec2_->compute();
265  }
266  IsComputed_ = true;
267  ++NumCompute_;
268  ComputeTime_ += timer.totalElapsedTime ();
269 }
270 
271 
272 template <class MatrixType>
274 apply (const Tpetra::MultiVector<typename MatrixType::scalar_type,
275  typename MatrixType::local_ordinal_type,
276  typename MatrixType::global_ordinal_type,
277  typename MatrixType::node_type>& X,
278  Tpetra::MultiVector<typename MatrixType::scalar_type,
279  typename MatrixType::local_ordinal_type,
280  typename MatrixType::global_ordinal_type,
281  typename MatrixType::node_type>& Y,
282  Teuchos::ETransp mode,
283  typename MatrixType::scalar_type alpha,
284  typename MatrixType::scalar_type beta) const
285 {
286  using Teuchos::RCP;
287  using Teuchos::rcp;
288  using Teuchos::rcpFromRef;
289  typedef Tpetra::MultiVector<scalar_type, local_ordinal_type,
292  ! isComputed (), std::runtime_error,
293  "Ifpack2::Hiptmair::apply: You must call compute() before you may call apply().");
295  X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
296  "Ifpack2::Hiptmair::apply: The MultiVector inputs X and Y do not have the "
297  "same number of columns. X.getNumVectors() = " << X.getNumVectors ()
298  << " != Y.getNumVectors() = " << Y.getNumVectors () << ".");
299 
300  // Catch unimplemented cases: alpha != 1, beta != 0, mode != NO_TRANS.
302  alpha != STS::one (), std::logic_error,
303  "Ifpack2::Hiptmair::apply: alpha != 1 has not been implemented.");
304  TEUCHOS_TEST_FOR_EXCEPTION(
305  beta != STS::zero (), std::logic_error,
306  "Ifpack2::Hiptmair::apply: zero != 0 has not been implemented.");
307  TEUCHOS_TEST_FOR_EXCEPTION(
308  mode != Teuchos::NO_TRANS, std::logic_error,
309  "Ifpack2::Hiptmair::apply: mode != Teuchos::NO_TRANS has not been implemented.");
310 
311  Teuchos::Time timer ("apply");
312  { // The body of code to time
313  Teuchos::TimeMonitor timeMon (timer);
314 
315  // If X and Y are pointing to the same memory location,
316  // we need to create an auxiliary vector, Xcopy
317  RCP<const MV> Xcopy;
318  {
319  auto X_lcl_host = X.getLocalViewHost ();
320  auto Y_lcl_host = Y.getLocalViewHost ();
321 
322  if (X_lcl_host.data () == Y_lcl_host.data ()) {
323  Xcopy = rcp (new MV (X, Teuchos::Copy));
324  } else {
325  Xcopy = rcpFromRef (X);
326  }
327  }
328 
329  RCP<MV> Ycopy = rcpFromRef (Y);
330  if (ZeroStartingSolution_) {
331  Ycopy->putScalar (STS::zero ());
332  }
333 
334  // apply Hiptmair Smoothing
335  applyHiptmairSmoother (*Xcopy, *Ycopy);
336 
337  }
338  ++NumApply_;
339  ApplyTime_ += timer.totalElapsedTime ();
340 }
341 
342 template <class MatrixType>
344 applyHiptmairSmoother(const Tpetra::MultiVector<typename MatrixType::scalar_type,
345  typename MatrixType::local_ordinal_type,
346  typename MatrixType::global_ordinal_type,
347  typename MatrixType::node_type>& X,
348  Tpetra::MultiVector<typename MatrixType::scalar_type,
349  typename MatrixType::local_ordinal_type,
350  typename MatrixType::global_ordinal_type,
351  typename MatrixType::node_type>& Y) const
352 {
353  using Teuchos::RCP;
354  using Teuchos::rcp;
355  using Teuchos::rcpFromRef;
356  typedef Tpetra::MultiVector<scalar_type, local_ordinal_type,
357  global_ordinal_type, node_type> MV;
358  const scalar_type ZERO = STS::zero ();
359  const scalar_type ONE = STS::one ();
360 
361  RCP<MV> res1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ()));
362  RCP<MV> vec1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ()));
363  RCP<MV> res2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ()));
364  RCP<MV> vec2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ()));
365 
366  if (preOrPost_ == "pre" || preOrPost_ == "both") {
367  // apply initial relaxation to primary space
368  A_->apply (Y, *res1);
369  res1->update (ONE, X, -ONE);
370  vec1->putScalar (ZERO);
371  ifpack2_prec1_->apply (*res1, *vec1);
372  Y.update (ONE, *vec1, ONE);
373  }
374 
375  // project to auxiliary space and smooth
376  A_->apply (Y, *res1);
377  res1->update (ONE, X, -ONE);
378  P_->apply (*res1, *res2, Teuchos::TRANS);
379  vec2->putScalar (ZERO);
380  ifpack2_prec2_->apply (*res2, *vec2);
381  P_->apply (*vec2, *vec1, Teuchos::NO_TRANS);
382  Y.update (ONE,*vec1,ONE);
383 
384  if (preOrPost_ == "post" || preOrPost_ == "both") {
385  // smooth again on primary space
386  A_->apply (Y, *res1);
387  res1->update (ONE, X, -ONE);
388  vec1->putScalar (ZERO);
389  ifpack2_prec1_->apply (*res1, *vec1);
390  Y.update (ONE, *vec1, ONE);
391  }
392 }
393 
394 template <class MatrixType>
396 {
397  std::ostringstream os;
398 
399  // Output is a valid YAML dictionary in flow style. If you don't
400  // like everything on a single line, you should call describe()
401  // instead.
402  os << "\"Ifpack2::Hiptmair\": {";
403  if (this->getObjectLabel () != "") {
404  os << "Label: \"" << this->getObjectLabel () << "\", ";
405  }
406  os << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
407  << "Computed: " << (isComputed () ? "true" : "false") << ", ";
408 
409  if (A_.is_null ()) {
410  os << "Matrix: null";
411  }
412  else {
413  os << "Matrix: not null"
414  << ", Global matrix dimensions: ["
415  << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]";
416  }
417 
418  os << "}";
419  return os.str ();
420 }
421 
422 
423 template <class MatrixType>
426  const Teuchos::EVerbosityLevel verbLevel) const
427 {
428  using std::endl;
429  using std::setw;
430  using Teuchos::VERB_DEFAULT;
431  using Teuchos::VERB_NONE;
432  using Teuchos::VERB_LOW;
433  using Teuchos::VERB_MEDIUM;
434  using Teuchos::VERB_HIGH;
435  using Teuchos::VERB_EXTREME;
436 
437  const Teuchos::EVerbosityLevel vl =
438  (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
439 
440  if (vl != VERB_NONE) {
441  // describe() always starts with a tab by convention.
442  Teuchos::OSTab tab0 (out);
443  out << "\"Ifpack2::Hiptmair\":";
444 
445  Teuchos::OSTab tab1 (out);
446  if (this->getObjectLabel () != "") {
447  out << "Label: " << this->getObjectLabel () << endl;
448  }
449  out << "Initialized: " << (isInitialized () ? "true" : "false") << endl
450  << "Computed: " << (isComputed () ? "true" : "false") << endl
451  << "Global number of rows: " << A_->getGlobalNumRows () << endl
452  << "Global number of columns: " << A_->getGlobalNumCols () << endl
453  << "Matrix:";
454  if (A_.is_null ()) {
455  out << " null" << endl;
456  } else {
457  A_->describe (out, vl);
458  }
459  }
460 }
461 
462 } // namespace Ifpack2
463 
464 #define IFPACK2_HIPTMAIR_INSTANT(S,LO,GO,N) \
465  template class Ifpack2::Hiptmair< Tpetra::RowMatrix<S, LO, GO, N> >;
466 
467 #endif /* IFPACK2_HIPTMAIR_DEF_HPP */
void initialize()
Do any initialization that depends on the input matrix&#39;s structure.
Definition: Ifpack2_Hiptmair_def.hpp:211
Teuchos::RCP< prec_type > create(const std::string &precType, const Teuchos::RCP< const row_matrix_type > &matrix) const
Create an instance of Preconditioner given the string name of the preconditioner type.
Definition: Ifpack2_Details_OneLevelFactory_def.hpp:78
T & get(const std::string &name, T def_value)
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_Hiptmair_decl.hpp:85
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_Hiptmair_decl.hpp:82
double getComputeTime() const
Returns the time spent in Compute().
Definition: Ifpack2_Hiptmair_def.hpp:199
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Returns the operator&#39;s communicator.
Definition: Ifpack2_Hiptmair_def.hpp:126
bool hasTransposeApply() const
Whether this object&#39;s apply() method can apply the transpose (or conjugate transpose, if applicable).
Definition: Ifpack2_Hiptmair_def.hpp:167
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_Hiptmair_def.hpp:425
double getApplyTime() const
Returns the time spent in apply().
Definition: Ifpack2_Hiptmair_def.hpp:205
void setParameters(const Teuchos::ParameterList &params)
Set the preconditioner&#39;s parameters.
Definition: Ifpack2_Hiptmair_def.hpp:85
Teuchos::RCP< const Tpetra::RowMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > > getMatrix() const
Returns a reference to the matrix to be preconditioned.
Definition: Ifpack2_Hiptmair_def.hpp:137
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRangeMap() const
Tpetra::Map representing the range of this operator.
Definition: Ifpack2_Hiptmair_def.hpp:156
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_Hiptmair_decl.hpp:88
int getNumApply() const
Returns the number of calls to apply().
Definition: Ifpack2_Hiptmair_def.hpp:187
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Wrapper for Hiptmair smoothers.
Definition: Ifpack2_Hiptmair_decl.hpp:71
Hiptmair(const Teuchos::RCP< const row_matrix_type > &A, const Teuchos::RCP< const row_matrix_type > &PtAP, const Teuchos::RCP< const row_matrix_type > &P)
Constructor that takes 3 Tpetra matrices.
Definition: Ifpack2_Hiptmair_def.hpp:58
int getNumCompute() const
Returns the number of calls to Compute().
Definition: Ifpack2_Hiptmair_def.hpp:181
int getNumInitialize() const
Returns the number of calls to Initialize().
Definition: Ifpack2_Hiptmair_def.hpp:175
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_Hiptmair_decl.hpp:91
void compute()
Do any initialization that depends on the input matrix&#39;s values.
Definition: Ifpack2_Hiptmair_def.hpp:248
virtual ~Hiptmair()
Destructor.
Definition: Ifpack2_Hiptmair_def.hpp:82
std::string description() const
Return a simple one-line description of this object.
Definition: Ifpack2_Hiptmair_def.hpp:395
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getDomainMap() const
Tpetra::Map representing the domain of this operator.
Definition: Ifpack2_Hiptmair_def.hpp:144
TypeTo as(const TypeFrom &t)
double totalElapsedTime(bool readCurrentTime=false) const
double getInitializeTime() const
Returns the time spent in Initialize().
Definition: Ifpack2_Hiptmair_def.hpp:193
&quot;Factory&quot; for creating single-level preconditioners.
Definition: Ifpack2_Details_OneLevelFactory_decl.hpp:123
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_Hiptmair_def.hpp:274