Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_BlockRelaxation_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_BLOCKRELAXATION_DEF_HPP
44 #define IFPACK2_BLOCKRELAXATION_DEF_HPP
45 
47 #include "Ifpack2_LinearPartitioner.hpp"
48 #include "Ifpack2_LinePartitioner.hpp"
49 #include "Ifpack2_Zoltan2Partitioner_decl.hpp"
50 #include "Ifpack2_Zoltan2Partitioner_def.hpp"
52 #include "Ifpack2_Details_UserPartitioner_def.hpp"
53 #include "Ifpack2_LocalFilter.hpp"
54 #include "Ifpack2_Parameters.hpp"
55 #include "Teuchos_TimeMonitor.hpp"
56 #include "Tpetra_BlockCrsMatrix_Helpers_decl.hpp"
57 
58 namespace Ifpack2 {
59 
60 template<class MatrixType,class ContainerType>
63 {
64  if (A.getRawPtr () != A_.getRawPtr ()) { // it's a different matrix
65  IsInitialized_ = false;
66  IsComputed_ = false;
67  Partitioner_ = Teuchos::null;
68  W_ = Teuchos::null;
69 
70  if (! A.is_null ()) {
71  IsParallel_ = (A->getRowMap ()->getComm ()->getSize () != 1);
73  Teuchos::rcp_dynamic_cast<const block_crs_matrix_type> (A);
74  hasBlockCrsMatrix_ = !A_bcrs.is_null();
75  }
76  if (! Container_.is_null ()) {
77  //This just frees up the container's memory.
78  //The container will be fully re-constructed during initialize().
79  Container_->clearBlocks();
80  }
81  NumLocalBlocks_ = 0;
82 
83  A_ = A;
84  computeImporter();
85  }
86 }
87 
88 template<class MatrixType,class ContainerType>
91 :
92  Container_ (Teuchos::null),
93  Partitioner_ (Teuchos::null),
94  PartitionerType_ ("linear"),
95  NumSweeps_ (1),
96  NumLocalBlocks_(0),
97  containerType_ ("TriDi"),
98  PrecType_ (Ifpack2::Details::JACOBI),
99  ZeroStartingSolution_ (true),
100  hasBlockCrsMatrix_ (false),
101  DoBackwardGS_ (false),
102  OverlapLevel_ (0),
103  nonsymCombine_(0),
104  schwarzCombineMode_("ZERO"),
105  DampingFactor_ (STS::one ()),
106  IsInitialized_ (false),
107  IsComputed_ (false),
108  NumInitialize_ (0),
109  NumCompute_ (0),
110  TimerForApply_(true),
111  NumApply_ (0),
112  InitializeTime_ (0.0),
113  ComputeTime_ (0.0),
114  NumLocalRows_ (0),
115  NumGlobalRows_ (0),
116  NumGlobalNonzeros_ (0),
117  W_ (Teuchos::null),
118  Importer_ (Teuchos::null)
119 {
120  setMatrix(A);
121 }
122 
123 template<class MatrixType,class ContainerType>
126 {}
127 
128 template<class MatrixType,class ContainerType>
132 {
133  Teuchos::RCP<Teuchos::ParameterList> validParams = Teuchos::parameterList ("Ifpack2::BlockRelaxation");
134 
135  validParams->set("relaxation: container", "TriDi");
136  validParams->set("relaxation: backward mode",false);
137  validParams->set("relaxation: type", "Jacobi");
138  validParams->set("relaxation: sweeps", 1);
139  validParams->set("relaxation: damping factor", STS::one());
140  validParams->set("relaxation: zero starting solution", true);
141  validParams->set("block relaxation: decouple dofs", false);
142  validParams->set("schwarz: compute condest", false); // mfh 24 Mar 2015: for backwards compatibility ONLY
143  validParams->set("schwarz: combine mode", "ZERO"); // use string mode for this
144  validParams->set("schwarz: use reordering", true);
145  validParams->set("schwarz: filter singletons", false);
146  validParams->set("schwarz: overlap level", 0);
147  validParams->set("partitioner: type", "greedy");
148  validParams->set("zoltan2: algorithm", "phg");
149  validParams->set("partitioner: local parts", 1);
150  validParams->set("partitioner: overlap", 0);
151  validParams->set("partitioner: combine mode", "ZERO"); // use string mode for this
153  validParams->set("partitioner: parts", tmp0);
155  validParams->set("partitioner: global ID parts", tmp1);
156  validParams->set("partitioner: nonsymmetric overlap combine", false);
157  validParams->set("partitioner: maintain sparsity", false);
158  validParams->set("fact: ilut level-of-fill", 1.0);
159  validParams->set("fact: absolute threshold", 0.0);
160  validParams->set("fact: relative threshold", 1.0);
161  validParams->set("fact: relax value", 0.0);
162 
163  Teuchos::ParameterList dummyList;
164  validParams->set("Amesos2",dummyList);
165  validParams->sublist("Amesos2").disableRecursiveValidation();
166  validParams->set("Amesos2 solver name", "KLU2");
167 
169  validParams->set("partitioner: map", tmp);
170 
171  validParams->set("partitioner: line detection threshold", 0.0);
172  validParams->set("partitioner: PDE equations", 1);
174  typename MatrixType::local_ordinal_type,
175  typename MatrixType::global_ordinal_type,
176  typename MatrixType::node_type> > dummy;
177  validParams->set("partitioner: coordinates",dummy);
178  validParams->set("timer for apply", true);
179  validParams->set("partitioner: subparts per part", 1);
180  validParams->set("partitioner: block size", -1);
181  validParams->set("partitioner: print level", false);
182 
183  return validParams;
184 }
185 
186 template<class MatrixType,class ContainerType>
187 void
190 {
191  // CAG: Copied from Relaxation
192  // FIXME (aprokop 18 Oct 2013) Casting away const is bad here.
193  // but otherwise, we will get [unused] in pl
194  this->setParametersImpl(const_cast<Teuchos::ParameterList&>(pl));
195 }
196 
197 template<class MatrixType,class ContainerType>
198 void
201 {
202  if (List.isType<double>("relaxation: damping factor")) {
203  // Make sure that ST=complex can run with a damping factor that is
204  // a double.
205  scalar_type df = List.get<double>("relaxation: damping factor");
206  List.remove("relaxation: damping factor");
207  List.set("relaxation: damping factor",df);
208  }
209 
210  // Note that the validation process does not change List.
212  validparams = this->getValidParameters();
213  List.validateParameters (*validparams);
214 
215  if (List.isParameter ("relaxation: container")) {
216  // If the container type isn't a string, this will throw, but it
217  // rightfully should.
218 
219  // If its value does not match the currently registered Container types,
220  // the ContainerFactory will throw with an informative message.
221  containerType_ = List.get<std::string> ("relaxation: container");
222  // Intercept more human-readable aliases for the *TriDi containers
223  if(containerType_ == "Tridiagonal") {
224  containerType_ = "TriDi";
225  }
226  if(containerType_ == "Block Tridiagonal") {
227  containerType_ = "BlockTriDi";
228  }
229  }
230 
231  if (List.isParameter ("relaxation: type")) {
232  const std::string relaxType = List.get<std::string> ("relaxation: type");
233 
234  if (relaxType == "Jacobi") {
235  PrecType_ = Ifpack2::Details::JACOBI;
236  }
237  else if (relaxType == "MT Split Jacobi") {
238  PrecType_ = Ifpack2::Details::MTSPLITJACOBI;
239  }
240  else if (relaxType == "Gauss-Seidel") {
241  PrecType_ = Ifpack2::Details::GS;
242  }
243  else if (relaxType == "Symmetric Gauss-Seidel") {
244  PrecType_ = Ifpack2::Details::SGS;
245  }
246  else {
248  (true, std::invalid_argument, "Ifpack2::BlockRelaxation::"
249  "setParameters: Invalid parameter value \"" << relaxType
250  << "\" for parameter \"relaxation: type\".");
251  }
252  }
253 
254  if (List.isParameter ("relaxation: sweeps")) {
255  NumSweeps_ = List.get<int> ("relaxation: sweeps");
256  }
257 
258  // Users may specify this as a floating-point literal. In that
259  // case, it may have type double, even if scalar_type is something
260  // else. We take care to try the various types that make sense.
261  if (List.isParameter ("relaxation: damping factor")) {
262  if (List.isType<double> ("relaxation: damping factor")) {
263  const double dampingFactor =
264  List.get<double> ("relaxation: damping factor");
265  DampingFactor_ = static_cast<scalar_type> (dampingFactor);
266  }
267  else if (List.isType<scalar_type> ("relaxation: damping factor")) {
268  DampingFactor_ = List.get<scalar_type> ("relaxation: damping factor");
269  }
270  else if (List.isType<magnitude_type> ("relaxation: damping factor")) {
271  const magnitude_type dampingFactor =
272  List.get<magnitude_type> ("relaxation: damping factor");
273  DampingFactor_ = static_cast<scalar_type> (dampingFactor);
274  }
275  else {
277  (true, std::invalid_argument, "Ifpack2::BlockRelaxation::"
278  "setParameters: Parameter \"relaxation: damping factor\" "
279  "has the wrong type.");
280  }
281  }
282 
283  if (List.isParameter ("relaxation: zero starting solution")) {
284  ZeroStartingSolution_ = List.get<bool> ("relaxation: zero starting solution");
285  }
286 
287  if (List.isParameter ("relaxation: backward mode")) {
288  DoBackwardGS_ = List.get<bool> ("relaxation: backward mode");
289  }
290 
291  if (List.isParameter ("partitioner: type")) {
292  PartitionerType_ = List.get<std::string> ("partitioner: type");
293  }
294 
295  // Users may specify this as an int literal, so we need to allow
296  // both int and local_ordinal_type (not necessarily same as int).
297  if (List.isParameter ("partitioner: local parts")) {
298  if (List.isType<local_ordinal_type> ("partitioner: local parts")) {
299  NumLocalBlocks_ = List.get<local_ordinal_type> ("partitioner: local parts");
300  }
301  else if (! std::is_same<int, local_ordinal_type>::value &&
302  List.isType<int> ("partitioner: local parts")) {
303  NumLocalBlocks_ = List.get<int> ("partitioner: local parts");
304  }
305  else {
307  (true, std::invalid_argument, "Ifpack2::BlockRelaxation::"
308  "setParameters: Parameter \"partitioner: local parts\" "
309  "has the wrong type.");
310  }
311  }
312 
313  if (List.isParameter ("partitioner: overlap level")) {
314  if (List.isType<int> ("partitioner: overlap level")) {
315  OverlapLevel_ = List.get<int> ("partitioner: overlap level");
316  }
317  else if (! std::is_same<int, local_ordinal_type>::value &&
318  List.isType<local_ordinal_type> ("partitioner: overlap level")) {
319  OverlapLevel_ = List.get<local_ordinal_type> ("partitioner: overlap level");
320  }
321  else {
323  (true, std::invalid_argument, "Ifpack2::BlockRelaxation::"
324  "setParameters: Parameter \"partitioner: overlap level\" "
325  "has the wrong type.");
326  }
327  }
328  // when using global ID parts, assume that some blocks overlap even if
329  // user did not explicitly set the overlap level in the input file.
330  if ( ( List.isParameter("partitioner: global ID parts")) && (OverlapLevel_ < 1)) OverlapLevel_ = 1;
331 
332  if (List.isParameter ("partitioner: nonsymmetric overlap combine"))
333  nonsymCombine_ = List.get<bool> ("partitioner: nonsymmetric overlap combine");
334 
335  if (List.isParameter ("partitioner: combine mode"))
336  schwarzCombineMode_ = List.get<std::string> ("partitioner: combine mode");
337 
338  std::string defaultContainer = "TriDi";
339  if(std::is_same<ContainerType, Container<MatrixType> >::value)
340  {
341  //Generic container template parameter, container type specified in List
342  Ifpack2::getParameter(List, "relaxation: container", defaultContainer);
343  }
344  // check parameters
345  if (PrecType_ != Ifpack2::Details::JACOBI) {
346  OverlapLevel_ = 0;
347  }
348  if (NumLocalBlocks_ < static_cast<local_ordinal_type> (0)) {
349  NumLocalBlocks_ = A_->getLocalNumRows() / (-NumLocalBlocks_);
350  }
351 
352  decouple_ = false;
353  if(List.isParameter("block relaxation: decouple dofs"))
354  decouple_ = List.get<bool>("block relaxation: decouple dofs");
355 
356  // other checks are performed in Partitioner_
357 
358  // NTS: Sanity check to be removed at a later date when Backward mode is enabled
360  DoBackwardGS_, std::runtime_error,
361  "Ifpack2::BlockRelaxation:setParameters: Setting the \"relaxation: "
362  "backward mode\" parameter to true is not yet supported.");
363 
364  if(List.isParameter("timer for apply"))
365  TimerForApply_ = List.get<bool>("timer for apply");
366 
367  // copy the list as each subblock's constructor will
368  // require it later
369  List_ = List;
370 }
371 
372 template<class MatrixType,class ContainerType>
375 {
377  (A_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::getComm: "
378  "The matrix is null. You must call setMatrix() with a nonnull matrix "
379  "before you may call this method.");
380  return A_->getComm ();
381 }
382 
383 template<class MatrixType,class ContainerType>
384 Teuchos::RCP<const Tpetra::RowMatrix<typename MatrixType::scalar_type,
385  typename MatrixType::local_ordinal_type,
386  typename MatrixType::global_ordinal_type,
387  typename MatrixType::node_type> >
389  return A_;
390 }
391 
392 template<class MatrixType,class ContainerType>
393 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,
394  typename MatrixType::global_ordinal_type,
395  typename MatrixType::node_type> >
397 getDomainMap () const
398 {
400  (A_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::"
401  "getDomainMap: The matrix is null. You must call setMatrix() with a "
402  "nonnull matrix before you may call this method.");
403  return A_->getDomainMap ();
404 }
405 
406 template<class MatrixType,class ContainerType>
407 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,
408  typename MatrixType::global_ordinal_type,
409  typename MatrixType::node_type> >
411 getRangeMap () const
412 {
414  (A_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::"
415  "getRangeMap: The matrix is null. You must call setMatrix() with a "
416  "nonnull matrix before you may call this method.");
417  return A_->getRangeMap ();
418 }
419 
420 template<class MatrixType,class ContainerType>
421 bool
423 hasTransposeApply () const {
424  return true;
425 }
426 
427 template<class MatrixType,class ContainerType>
428 int
431  return NumInitialize_;
432 }
433 
434 template<class MatrixType,class ContainerType>
435 int
438 {
439  return NumCompute_;
440 }
441 
442 template<class MatrixType,class ContainerType>
443 int
445 getNumApply () const
446 {
447  return NumApply_;
448 }
449 
450 template<class MatrixType,class ContainerType>
451 double
454 {
455  return InitializeTime_;
456 }
457 
458 template<class MatrixType,class ContainerType>
459 double
462 {
463  return ComputeTime_;
464 }
465 
466 template<class MatrixType,class ContainerType>
467 double
469 getApplyTime () const
470 {
471  return ApplyTime_;
472 }
473 
474 
475 template<class MatrixType,class ContainerType>
478  A_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::getNodeSmootherComplexity: "
479  "The input matrix A is null. Please call setMatrix() with a nonnull "
480  "input matrix, then call compute(), before calling this method.");
481  // Relaxation methods cost roughly one apply + one block-diagonal inverse per iteration
482  // NOTE: This approximates all blocks as dense, which may overstate the cost if you have a sparse (or banded) container.
483  size_t block_nnz = 0;
484  for (local_ordinal_type i = 0; i < NumLocalBlocks_; ++i)
485  block_nnz += Partitioner_->numRowsInPart(i) *Partitioner_->numRowsInPart(i);
486 
487  return block_nnz + A_->getLocalNumEntries();
488 }
489 
490 template<class MatrixType,class ContainerType>
491 void
493 apply (const Tpetra::MultiVector<typename MatrixType::scalar_type,
494  typename MatrixType::local_ordinal_type,
495  typename MatrixType::global_ordinal_type,
496  typename MatrixType::node_type>& X,
497  Tpetra::MultiVector<typename MatrixType::scalar_type,
498  typename MatrixType::local_ordinal_type,
499  typename MatrixType::global_ordinal_type,
500  typename MatrixType::node_type>& Y,
501  Teuchos::ETransp mode,
502  scalar_type alpha,
503  scalar_type beta) const
504 {
506  (A_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::apply: "
507  "The matrix is null. You must call setMatrix() with a nonnull matrix, "
508  "then call initialize() and compute() (in that order), before you may "
509  "call this method.");
511  ! isComputed (), std::runtime_error, "Ifpack2::BlockRelaxation::apply: "
512  "isComputed() must be true prior to calling apply.");
513  TEUCHOS_TEST_FOR_EXCEPTION(
514  X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
515  "Ifpack2::BlockRelaxation::apply: X.getNumVectors() = "
516  << X.getNumVectors () << " != Y.getNumVectors() = "
517  << Y.getNumVectors () << ".");
518  TEUCHOS_TEST_FOR_EXCEPTION(
519  mode != Teuchos::NO_TRANS, std::logic_error, "Ifpack2::BlockRelaxation::"
520  "apply: This method currently only implements the case mode == Teuchos::"
521  "NO_TRANS. Transposed modes are not currently supported.");
522  TEUCHOS_TEST_FOR_EXCEPTION(
523  alpha != Teuchos::ScalarTraits<scalar_type>::one (), std::logic_error,
524  "Ifpack2::BlockRelaxation::apply: This method currently only implements "
525  "the case alpha == 1. You specified alpha = " << alpha << ".");
526  TEUCHOS_TEST_FOR_EXCEPTION(
527  beta != Teuchos::ScalarTraits<scalar_type>::zero (), std::logic_error,
528  "Ifpack2::BlockRelaxation::apply: This method currently only implements "
529  "the case beta == 0. You specified beta = " << beta << ".");
530 
531  const std::string timerName ("Ifpack2::BlockRelaxation::apply");
533  if (TimerForApply_) {
534  timer = Teuchos::TimeMonitor::lookupCounter (timerName);
535  if (timer.is_null ()) {
536  timer = Teuchos::TimeMonitor::getNewCounter (timerName);
537  }
538  }
539 
540  Teuchos::Time time = Teuchos::Time(timerName);
541  double startTime = time.wallTime();
542 
543  {
545  if (TimerForApply_)
546  timeMon = Teuchos::rcp(new Teuchos::TimeMonitor(*timer));
547 
548  // If X and Y are pointing to the same memory location,
549  // we need to create an auxiliary vector, Xcopy
550  Teuchos::RCP<const MV> X_copy;
551  {
552  if (X.aliases(Y)) {
553  X_copy = rcp (new MV (X, Teuchos::Copy));
554  } else {
555  X_copy = rcpFromRef (X);
556  }
557  }
558 
559  if (ZeroStartingSolution_) {
560  Y.putScalar (STS::zero ());
561  }
562 
563  // Flops are updated in each of the following.
564  switch (PrecType_) {
565  case Ifpack2::Details::JACOBI:
566  ApplyInverseJacobi(*X_copy,Y);
567  break;
568  case Ifpack2::Details::GS:
569  ApplyInverseGS(*X_copy,Y);
570  break;
571  case Ifpack2::Details::SGS:
572  ApplyInverseSGS(*X_copy,Y);
573  break;
574  case Ifpack2::Details::MTSPLITJACOBI:
575  //note: for this method, the container is always BlockTriDi
576  Container_->applyInverseJacobi(*X_copy, Y, DampingFactor_, ZeroStartingSolution_, NumSweeps_);
577  break;
578  default:
579  TEUCHOS_TEST_FOR_EXCEPTION
580  (true, std::logic_error, "Ifpack2::BlockRelaxation::apply: Invalid "
581  "PrecType_ enum value " << PrecType_ << ". Valid values are Ifpack2::"
582  "Details::JACOBI = " << Ifpack2::Details::JACOBI << ", Ifpack2::Details"
583  "::GS = " << Ifpack2::Details::GS << ", and Ifpack2::Details::SGS = "
584  << Ifpack2::Details::SGS << ". Please report this bug to the Ifpack2 "
585  "developers.");
586  }
587  }
588 
589  ApplyTime_ += (time.wallTime() - startTime);
590  ++NumApply_;
591 }
592 
593 template<class MatrixType,class ContainerType>
594 void
596 applyMat (const Tpetra::MultiVector<typename MatrixType::scalar_type,
597  typename MatrixType::local_ordinal_type,
598  typename MatrixType::global_ordinal_type,
599  typename MatrixType::node_type>& X,
600  Tpetra::MultiVector<typename MatrixType::scalar_type,
601  typename MatrixType::local_ordinal_type,
602  typename MatrixType::global_ordinal_type,
603  typename MatrixType::node_type>& Y,
604  Teuchos::ETransp mode) const
605 {
606  A_->apply (X, Y, mode);
607 }
608 
609 template<class MatrixType,class ContainerType>
610 void
613 {
614  using Teuchos::rcp;
615  typedef Tpetra::RowGraph<local_ordinal_type, global_ordinal_type, node_type>
616  row_graph_type;
617 
619  (A_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::initialize: "
620  "The matrix is null. You must call setMatrix() with a nonnull matrix "
621  "before you may call this method.");
622 
624  Teuchos::TimeMonitor::getNewCounter ("Ifpack2::BlockRelaxation::initialize");
625  double startTime = timer->wallTime();
626 
627  { // Timing of initialize starts here
628  Teuchos::TimeMonitor timeMon (*timer);
629  IsInitialized_ = false;
630 
631  // Check whether we have a BlockCrsMatrix
633  Teuchos::rcp_dynamic_cast<const block_crs_matrix_type> (A_);
634  hasBlockCrsMatrix_ = !A_bcrs.is_null();
635 
636  if(!hasBlockCrsMatrix_ && List_.isParameter("relaxation: container") && List_.get<std::string>("relaxation: container") == "BlockTriDi" ) {
637  TEUCHOS_FUNC_TIME_MONITOR("Ifpack2::BlockRelaxation::initialize::convertToBlockCrsMatrix");
638  int block_size = List_.get<int>("partitioner: block size");
640  (block_size == -1, "A pointwise matrix and block_size = -1 were given as inputs.");
641  A_bcrs = Tpetra::convertToBlockCrsMatrix(*Teuchos::rcp_dynamic_cast<const crs_matrix_type>(A_), block_size);
642  A_ = A_bcrs;
643  hasBlockCrsMatrix_ = true;
644  Kokkos::DefaultExecutionSpace().fence();
645  }
646 
647  NumLocalRows_ = A_->getLocalNumRows ();
648  NumGlobalRows_ = A_->getGlobalNumRows ();
649  NumGlobalNonzeros_ = A_->getGlobalNumEntries ();
650 
651  // NTS: Will need to add support for Zoltan2 partitions later Also,
652  // will need a better way of handling the Graph typing issue.
653  // Especially with ordinal types w.r.t the container.
654  Partitioner_ = Teuchos::null;
655 
656  if (PartitionerType_ == "linear") {
657  Partitioner_ =
658  rcp (new Ifpack2::LinearPartitioner<row_graph_type> (A_->getGraph ()));
659  } else if (PartitionerType_ == "line") {
660  Partitioner_ =
662  } else if (PartitionerType_ == "user") {
663  Partitioner_ =
664  rcp (new Ifpack2::Details::UserPartitioner<row_graph_type> (A_->getGraph () ) );
665  } else if (PartitionerType_ == "zoltan2") {
666  #if defined(HAVE_IFPACK2_ZOLTAN2)
667  if (A_->getGraph ()->getComm ()->getSize () == 1) {
668  // Only one MPI, so call zoltan2 with global graph
669  Partitioner_ =
670  rcp (new Ifpack2::Zoltan2Partitioner<row_graph_type> (A_->getGraph ()) );
671  } else {
672  // Form local matrix to get local graph for calling zoltan2
674  Partitioner_ =
675  rcp (new Ifpack2::Zoltan2Partitioner<row_graph_type> (A_local->getGraph ()) );
676  }
677  #else
679  (true, std::logic_error, "Ifpack2::BlockRelaxation::initialize: Zoltan2 not enabled.");
680  #endif
681  } else {
682  // We should have checked for this in setParameters(), so it's a
683  // logic_error, not an invalid_argument or runtime_error.
685  (true, std::logic_error, "Ifpack2::BlockRelaxation::initialize: Unknown "
686  "partitioner type " << PartitionerType_ << ". Valid values are "
687  "\"linear\", \"line\", and \"user\".");
688  }
689 
690  // need to partition the graph of A
691  Partitioner_->setParameters (List_);
692  Partitioner_->compute ();
693 
694  // get actual number of partitions
695  NumLocalBlocks_ = Partitioner_->numLocalParts ();
696 
697  // Note: Unlike Ifpack, we'll punt on computing W_ until compute(), which is where
698  // we assume that the type of relaxation has been chosen.
699 
700  if (A_->getComm()->getSize() != 1) {
701  IsParallel_ = true;
702  } else {
703  IsParallel_ = false;
704  }
705 
706  // We should have checked for this in setParameters(), so it's a
707  // logic_error, not an invalid_argument or runtime_error.
709  (NumSweeps_ < 0, std::logic_error, "Ifpack2::BlockRelaxation::initialize: "
710  "NumSweeps_ = " << NumSweeps_ << " < 0.");
711 
712  // Extract the submatrices
713  ExtractSubmatricesStructure ();
714 
715  // Compute the weight vector if we're doing overlapped Jacobi (and
716  // only if we're doing overlapped Jacobi).
717  if (PrecType_ == Ifpack2::Details::JACOBI && OverlapLevel_ > 0) {
719  (hasBlockCrsMatrix_, std::runtime_error,
720  "Ifpack2::BlockRelaxation::initialize: "
721  "We do not support overlapped Jacobi yet for Tpetra::BlockCrsMatrix. Sorry!");
722 
723  // weight of each vertex
724  W_ = rcp (new vector_type (A_->getRowMap ()));
725  W_->putScalar (STS::zero ());
726  {
727  Teuchos::ArrayRCP<scalar_type > w_ptr = W_->getDataNonConst(0);
728 
729  for (local_ordinal_type i = 0 ; i < NumLocalBlocks_ ; ++i) {
730  for (size_t j = 0 ; j < Partitioner_->numRowsInPart(i) ; ++j) {
731  local_ordinal_type LID = (*Partitioner_)(i,j);
732  w_ptr[LID] += STS::one();
733  }
734  }
735  }
736  // communicate to sum together W_[k]'s (# of blocks/patches) that update
737  // kth dof) and have this information in overlapped/extended vector.
738  // only needed when Schwarz combine mode is ADD as opposed to ZERO (which is RAS)
739 
740  if (schwarzCombineMode_ == "ADD") {
741  typedef Tpetra::MultiVector< typename MatrixType::scalar_type, typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type,typename MatrixType::node_type> scMV;
742  Teuchos::RCP<const import_type> theImport = A_->getGraph()->getImporter();
743  if (!theImport.is_null()) {
744  scMV nonOverLapW(theImport->getSourceMap(), 1, false);
745  Teuchos::ArrayRCP<scalar_type > w_ptr = W_->getDataNonConst(0);
746  Teuchos::ArrayRCP<scalar_type> nonOverLapWArray = nonOverLapW.getDataNonConst(0);
747  nonOverLapW.putScalar(STS::zero ());
748  for (int ii = 0; ii < (int) theImport->getSourceMap()->getLocalNumElements(); ii++) nonOverLapWArray[ii] = w_ptr[ii];
749  nonOverLapWArray = Teuchos::null;
750  w_ptr = Teuchos::null;
751  nonOverLapW.doExport (*W_, *theImport, Tpetra::ADD);
752  W_->doImport( nonOverLapW, *theImport, Tpetra::INSERT);
753  }
754 
755  }
756  W_->reciprocal (*W_);
757  }
758  } // timing of initialize stops here
759 
760  InitializeTime_ += (timer->wallTime() - startTime);
761  ++NumInitialize_;
762  IsInitialized_ = true;
763 }
764 
765 
766 template<class MatrixType,class ContainerType>
767 void
770 {
771  using Teuchos::rcp;
772 
774  (A_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::compute: "
775  "The matrix is null. You must call setMatrix() with a nonnull matrix, "
776  "then call initialize(), before you may call this method.");
777 
778  if (! isInitialized ()) {
779  initialize ();
780  }
781 
783  Teuchos::TimeMonitor::getNewCounter ("Ifpack2::BlockRelaxation::compute");
784 
785  double startTime = timer->wallTime();
786 
787  {
788  Teuchos::TimeMonitor timeMon (*timer);
789 
790  // reset values
791  IsComputed_ = false;
792 
793  Container_->compute(); // compute each block matrix
794  }
795 
796  ComputeTime_ += (timer->wallTime() - startTime);
797  ++NumCompute_;
798  IsComputed_ = true;
799 }
800 
801 template<class MatrixType, class ContainerType>
802 void
805 {
807  (Partitioner_.is_null (), std::runtime_error, "Ifpack2::BlockRelaxation::"
808  "ExtractSubmatricesStructure: Partitioner object is null.");
809 
810  std::string containerType = ContainerType::getName ();
811  if (containerType == "Generic") {
812  // ContainerType is Container<row_matrix_type>. Thus, we need to
813  // get the container name from the parameter list. We use "TriDi"
814  // as the default container type.
815  containerType = containerType_;
816  }
817  //Whether the Container will define blocks (partitions)
818  //in terms of individual DOFs, and not by nodes (blocks).
819  bool pointIndexed = decouple_ && hasBlockCrsMatrix_;
821  if(decouple_)
822  {
823  //dofs [per node] is how many blocks each partition will be split into
824  auto A_bcrs = Teuchos::rcp_dynamic_cast<const block_crs_matrix_type>(A_);
825  local_ordinal_type dofs = hasBlockCrsMatrix_ ?
826  A_bcrs->getBlockSize() : List_.get<int>("partitioner: PDE equations");
827  blockRows.resize(NumLocalBlocks_ * dofs);
828  if(hasBlockCrsMatrix_)
829  {
830  for(local_ordinal_type i = 0; i < NumLocalBlocks_; i++)
831  {
832  size_t blockSize = Partitioner_->numRowsInPart(i);
833  //block i will be split into j different blocks,
834  //each corresponding to a different dof
835  for(local_ordinal_type j = 0; j < dofs; j++)
836  {
837  local_ordinal_type blockIndex = i * dofs + j;
838  blockRows[blockIndex].resize(blockSize);
839  for(size_t k = 0; k < blockSize; k++)
840  {
841  //here, the row and dof are combined to get the point index
842  //(what the row would be if A were a CrsMatrix)
843  blockRows[blockIndex][k] = (*Partitioner_)(i, k) * dofs + j;
844  }
845  }
846  }
847  }
848  else
849  {
850  //Rows in each partition are distributed round-robin to the blocks -
851  //that's how MueLu stores DOFs in a non-block matrix
852  for(local_ordinal_type i = 0; i < NumLocalBlocks_; i++)
853  {
854  //#ifdef HAVE_IFPACK2_DEBUG
855  TEUCHOS_TEST_FOR_EXCEPTION(Partitioner_->numRowsInPart(i) % dofs != 0, std::logic_error,
856  "Expected size of all blocks (partitions) to be divisible by MueLu dofs/node.");
857  size_t blockSize = Partitioner_->numRowsInPart(i) / dofs;
858  //#endif
859  //block i will be split into j different blocks,
860  //each corresponding to a different dof
861  for(local_ordinal_type j = 0; j < dofs; j++)
862  {
863  local_ordinal_type blockIndex = i * dofs + j;
864  blockRows[blockIndex].resize(blockSize);
865  for(size_t k = 0; k < blockSize; k++)
866  {
867  blockRows[blockIndex][k] = (*Partitioner_)(i, k * dofs + j);
868  }
869  }
870  }
871  }
872  }
873  else
874  {
875  //No decoupling - just get the rows directly from Partitioner
876  blockRows.resize(NumLocalBlocks_);
877  for(local_ordinal_type i = 0; i < NumLocalBlocks_; ++i)
878  {
879  const size_t numRows = Partitioner_->numRowsInPart (i);
880  blockRows[i].resize(numRows);
881  // Extract a list of the indices of each partitioner row.
882  for (size_t j = 0; j < numRows; ++j)
883  {
884  blockRows[i][j] = (*Partitioner_) (i,j);
885  }
886  }
887  }
888  //right before constructing the
889  Container_ = ContainerFactory<MatrixType>::build(containerType, A_, blockRows, Importer_, pointIndexed);
890  Container_->setParameters(List_);
891  Container_->initialize();
892 }
893 
894 template<class MatrixType,class ContainerType>
895 void
896 BlockRelaxation<MatrixType,ContainerType>::
897 ApplyInverseJacobi (const MV& X, MV& Y) const
898 {
899  const size_t NumVectors = X.getNumVectors ();
900 
901  MV AY (Y.getMap (), NumVectors);
902 
903  // Initial matvec not needed
904  int starting_iteration = 0;
905  if (OverlapLevel_ > 0)
906  {
907  //Overlapping jacobi, with view of W_
908  auto WView = W_->getLocalViewHost (Tpetra::Access::ReadOnly);
909  if(ZeroStartingSolution_) {
910  auto XView = X.getLocalViewHost (Tpetra::Access::ReadOnly);
911  auto YView = Y.getLocalViewHost (Tpetra::Access::ReadWrite);
912  Container_->DoOverlappingJacobi(XView, YView, WView, DampingFactor_, nonsymCombine_);
913  starting_iteration = 1;
914  }
915  const scalar_type ONE = STS::one();
916  for(int j = starting_iteration; j < NumSweeps_; j++)
917  {
918  applyMat (Y, AY);
919  AY.update (ONE, X, -ONE);
920  {
921  auto AYView = AY.getLocalViewHost (Tpetra::Access::ReadOnly);
922  auto YView = Y.getLocalViewHost (Tpetra::Access::ReadWrite);
923  Container_->DoOverlappingJacobi (AYView, YView, WView, DampingFactor_, nonsymCombine_);
924  }
925  }
926  }
927  else
928  {
929  //Non-overlapping
930  if(ZeroStartingSolution_)
931  {
932  auto XView = X.getLocalViewHost (Tpetra::Access::ReadOnly);
933  auto YView = Y.getLocalViewHost (Tpetra::Access::ReadWrite);
934  Container_->DoJacobi (XView, YView, DampingFactor_);
935  starting_iteration = 1;
936  }
937  const scalar_type ONE = STS::one();
938  for(int j = starting_iteration; j < NumSweeps_; j++)
939  {
940  applyMat (Y, AY);
941  AY.update (ONE, X, -ONE);
942  {
943  auto AYView = AY.getLocalViewHost (Tpetra::Access::ReadOnly);
944  auto YView = Y.getLocalViewHost (Tpetra::Access::ReadWrite);
945  Container_->DoJacobi (AYView, YView, DampingFactor_);
946  }
947  }
948  }
949 }
950 
951 template<class MatrixType,class ContainerType>
952 void
953 BlockRelaxation<MatrixType,ContainerType>::
954 ApplyInverseGS (const MV& X, MV& Y) const
955 {
956  using Teuchos::Ptr;
957  using Teuchos::ptr;
958  size_t numVecs = X.getNumVectors();
959  //Get view of X (is never modified in this function)
960  auto XView = X.getLocalViewHost (Tpetra::Access::ReadOnly);
961  auto YView = Y.getLocalViewHost (Tpetra::Access::ReadWrite);
962  //Pre-import Y, if parallel
963  Ptr<MV> Y2;
964  bool deleteY2 = false;
965  if(IsParallel_)
966  {
967  Y2 = ptr(new MV(Importer_->getTargetMap(), numVecs));
968  deleteY2 = true;
969  }
970  else
971  Y2 = ptr(&Y);
972  if(IsParallel_)
973  {
974  for(int j = 0; j < NumSweeps_; ++j)
975  {
976  //do import once per sweep
977  Y2->doImport(Y, *Importer_, Tpetra::INSERT);
978  auto Y2View = Y2->getLocalViewHost (Tpetra::Access::ReadWrite);
979  Container_->DoGaussSeidel(XView, YView, Y2View, DampingFactor_);
980  }
981  }
982  else
983  {
984  auto Y2View = Y2->getLocalViewHost (Tpetra::Access::ReadWrite);
985  for(int j = 0; j < NumSweeps_; ++j)
986  {
987  Container_->DoGaussSeidel(XView, YView, Y2View, DampingFactor_);
988  }
989  }
990  if(deleteY2)
991  delete Y2.get();
992 }
993 
994 template<class MatrixType,class ContainerType>
995 void
996 BlockRelaxation<MatrixType,ContainerType>::
997 ApplyInverseSGS (const MV& X, MV& Y) const
998 {
999  using Teuchos::Ptr;
1000  using Teuchos::ptr;
1001  //Get view of X (is never modified in this function)
1002  auto XView = X.getLocalViewHost (Tpetra::Access::ReadOnly);
1003  auto YView = Y.getLocalViewHost (Tpetra::Access::ReadWrite);
1004  //Pre-import Y, if parallel
1005  Ptr<MV> Y2;
1006  bool deleteY2 = false;
1007  if(IsParallel_)
1008  {
1009  Y2 = ptr(new MV(Importer_->getTargetMap(), X.getNumVectors()));
1010  deleteY2 = true;
1011  }
1012  else
1013  Y2 = ptr(&Y);
1014  if(IsParallel_)
1015  {
1016  for(int j = 0; j < NumSweeps_; ++j)
1017  {
1018  //do import once per sweep
1019  Y2->doImport(Y, *Importer_, Tpetra::INSERT);
1020  auto Y2View = Y2->getLocalViewHost (Tpetra::Access::ReadWrite);
1021  Container_->DoSGS(XView, YView, Y2View, DampingFactor_);
1022  }
1023  }
1024  else
1025  {
1026  auto Y2View = Y2->getLocalViewHost (Tpetra::Access::ReadWrite);
1027  for(int j = 0; j < NumSweeps_; ++j)
1028  {
1029  Container_->DoSGS(XView, YView, Y2View, DampingFactor_);
1030  }
1031  }
1032  if(deleteY2)
1033  delete Y2.get();
1034 }
1035 
1036 template<class MatrixType,class ContainerType>
1037 void BlockRelaxation<MatrixType,ContainerType>::computeImporter () const
1038 {
1039  using Teuchos::RCP;
1040  using Teuchos::rcp;
1041  using Teuchos::Ptr;
1042  using Teuchos::ArrayView;
1043  using Teuchos::Array;
1044  using Teuchos::Comm;
1045  using Teuchos::rcp_dynamic_cast;
1046  if(IsParallel_)
1047  {
1048  if(hasBlockCrsMatrix_)
1049  {
1050  const RCP<const block_crs_matrix_type> bcrs =
1051  rcp_dynamic_cast<const block_crs_matrix_type>(A_);
1052  int bs_ = bcrs->getBlockSize();
1053  RCP<const map_type> oldDomainMap = A_->getDomainMap();
1054  RCP<const map_type> oldColMap = A_->getColMap();
1055  // Because A is a block CRS matrix, import will not do what you think it does
1056  // We have to construct the correct maps for it
1057  global_size_t numGlobalElements = oldColMap->getGlobalNumElements() * bs_;
1058  global_ordinal_type indexBase = oldColMap->getIndexBase();
1059  RCP<const Comm<int>> comm = oldColMap->getComm();
1060  ArrayView<const global_ordinal_type> oldColElements = oldColMap->getLocalElementList();
1061  Array<global_ordinal_type> newColElements(bs_ * oldColElements.size());
1062  for(int i = 0; i < oldColElements.size(); i++)
1063  {
1064  for(int j = 0; j < bs_; j++)
1065  newColElements[i * bs_ + j] = oldColElements[i] * bs_ + j;
1066  }
1067  RCP<map_type> colMap(new map_type(numGlobalElements, newColElements, indexBase, comm));
1068  // Create the importer
1069  Importer_ = rcp(new import_type(oldDomainMap, colMap));
1070  }
1071  else if(!A_.is_null())
1072  {
1073  Importer_ = A_->getGraph()->getImporter();
1074  if(Importer_.is_null())
1075  Importer_ = rcp(new import_type(A_->getDomainMap(), A_->getColMap()));
1076  }
1077  }
1078  //otherwise, Importer_ is not needed and is left NULL
1079 }
1080 
1081 template<class MatrixType, class ContainerType>
1082 std::string
1084 description () const
1085 {
1086  std::ostringstream out;
1087 
1088  // Output is a valid YAML dictionary in flow style. If you don't
1089  // like everything on a single line, you should call describe()
1090  // instead.
1091  out << "\"Ifpack2::BlockRelaxation\": {";
1092  if (this->getObjectLabel () != "") {
1093  out << "Label: \"" << this->getObjectLabel () << "\", ";
1094  }
1095  // out << "Initialized: " << (isInitialized () ? "true" : "false") << ", ";
1096  // out << "Computed: " << (isComputed () ? "true" : "false") << ", ";
1097  if (A_.is_null ()) {
1098  out << "Matrix: null, ";
1099  }
1100  else {
1101  // out << "Matrix: not null"
1102  // << ", Global matrix dimensions: ["
1103  out << "Global matrix dimensions: ["
1104  << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "], ";
1105  }
1106 
1107  // It's useful to print this instance's relaxation method. If you
1108  // want more info than that, call describe() instead.
1109  out << "\"relaxation: type\": ";
1110  if (PrecType_ == Ifpack2::Details::JACOBI) {
1111  out << "Block Jacobi";
1112  } else if (PrecType_ == Ifpack2::Details::GS) {
1113  out << "Block Gauss-Seidel";
1114  } else if (PrecType_ == Ifpack2::Details::SGS) {
1115  out << "Block Symmetric Gauss-Seidel";
1116  } else if (PrecType_ == Ifpack2::Details::MTSPLITJACOBI) {
1117  out << "MT Split Jacobi";
1118  } else {
1119  out << "INVALID";
1120  }
1121 
1122  // BlockCrs if we have that
1123  if(hasBlockCrsMatrix_)
1124  out<<", BlockCrs";
1125 
1126  // Print the approximate # rows per part
1127  int approx_rows_per_part = A_->getLocalNumRows()/Partitioner_->numLocalParts();
1128  out <<", blocksize: "<<approx_rows_per_part;
1129 
1130  out << ", overlap: " << OverlapLevel_;
1131 
1132  out << ", " << "sweeps: " << NumSweeps_ << ", "
1133  << "damping factor: " << DampingFactor_ << ", ";
1134 
1135  std::string containerType = ContainerType::getName();
1136  out << "block container: " << ((containerType == "Generic") ? containerType_ : containerType);
1137  if(List_.isParameter("partitioner: PDE equations"))
1138  out << ", dofs/node: "<<List_.get<int>("partitioner: PDE equations");
1139 
1140 
1141  out << "}";
1142  return out.str();
1143 }
1144 
1145 template<class MatrixType,class ContainerType>
1146 void
1149  const Teuchos::EVerbosityLevel verbLevel) const
1150 {
1151  using std::endl;
1152  using std::setw;
1154  using Teuchos::VERB_DEFAULT;
1155  using Teuchos::VERB_NONE;
1156  using Teuchos::VERB_LOW;
1157  using Teuchos::VERB_MEDIUM;
1158  using Teuchos::VERB_HIGH;
1159  using Teuchos::VERB_EXTREME;
1160 
1161  Teuchos::EVerbosityLevel vl = verbLevel;
1162  if (vl == VERB_DEFAULT) vl = VERB_LOW;
1163  const int myImageID = A_->getComm()->getRank();
1164 
1165  // Convention requires that describe() begin with a tab.
1166  Teuchos::OSTab tab (out);
1167 
1168  // none: print nothing
1169  // low: print O(1) info from node 0
1170  // medium:
1171  // high:
1172  // extreme:
1173  if (vl != VERB_NONE && myImageID == 0) {
1174  out << "Ifpack2::BlockRelaxation<"
1175  << TypeNameTraits<MatrixType>::name () << ", "
1176  << TypeNameTraits<ContainerType>::name () << " >:";
1177  Teuchos::OSTab tab1 (out);
1178 
1179  if (this->getObjectLabel () != "") {
1180  out << "label: \"" << this->getObjectLabel () << "\"" << endl;
1181  }
1182  out << "initialized: " << (isInitialized () ? "true" : "false") << endl
1183  << "computed: " << (isComputed () ? "true" : "false") << endl;
1184 
1185  std::string precType;
1186  if (PrecType_ == Ifpack2::Details::JACOBI) {
1187  precType = "Block Jacobi";
1188  } else if (PrecType_ == Ifpack2::Details::GS) {
1189  precType = "Block Gauss-Seidel";
1190  } else if (PrecType_ == Ifpack2::Details::SGS) {
1191  precType = "Block Symmetric Gauss-Seidel";
1192  }
1193  out << "type: " << precType << endl
1194  << "global number of rows: " << A_->getGlobalNumRows () << endl
1195  << "global number of columns: " << A_->getGlobalNumCols () << endl
1196  << "number of sweeps: " << NumSweeps_ << endl
1197  << "damping factor: " << DampingFactor_ << endl
1198  << "nonsymmetric overlap combine" << nonsymCombine_ << endl
1199  << "backwards mode: "
1200  << ((PrecType_ == Ifpack2::Details::GS && DoBackwardGS_) ? "true" : "false")
1201  << endl
1202  << "zero starting solution: "
1203  << (ZeroStartingSolution_ ? "true" : "false") << endl;
1204  }
1205 }
1206 
1207 }//namespace Ifpack2
1208 
1209 
1210 // Macro that does explicit template instantiation (ETI) for
1211 // Ifpack2::BlockRelaxation. S, LO, GO, N correspond to the four
1212 // template parameters of Ifpack2::Preconditioner and
1213 // Tpetra::RowMatrix.
1214 //
1215 // We only instantiate for MatrixType = Tpetra::RowMatrix. There's no
1216 // need to instantiate for Tpetra::CrsMatrix too. All Ifpack2
1217 // preconditioners can and should do dynamic casts if they need a type
1218 // more specific than RowMatrix. This keeps build time short and
1219 // library and executable sizes small.
1220 
1221 #ifdef HAVE_IFPACK2_EXPLICIT_INSTANTIATION
1222 
1223 #define IFPACK2_BLOCKRELAXATION_INSTANT(S,LO,GO,N) \
1224  template \
1225  class Ifpack2::BlockRelaxation< \
1226  Tpetra::RowMatrix<S, LO, GO, N>, \
1227  Ifpack2::Container<Tpetra::RowMatrix<S, LO, GO, N> > >;
1228 
1229 #endif // HAVE_IFPACK2_EXPLICIT_INSTANTIATION
1230 
1231 #endif // IFPACK2_BLOCKRELAXATION_DEF_HPP
Ifpack2::BlockRelaxation class declaration.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the input matrix is distributed.
Definition: Ifpack2_BlockRelaxation_def.hpp:374
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
ParameterList & disableRecursiveValidation()
std::string description() const
A one-line description of this object.
Definition: Ifpack2_BlockRelaxation_def.hpp:1084
double getApplyTime() const
Returns the time spent in apply().
Definition: Ifpack2_BlockRelaxation_def.hpp:469
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static RCP< Time > getNewCounter(const std::string &name)
static RCP< Time > lookupCounter(const std::string &name)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
int getNumApply() const
Returns the number of calls to apply().
Definition: Ifpack2_BlockRelaxation_def.hpp:445
void getParameter(const Teuchos::ParameterList &params, const std::string &name, T &value)
Set a value from a ParameterList if a parameter with the specified name exists.
Definition: Ifpack2_Parameters.hpp:59
Teuchos::RCP< const map_type > getRangeMap() const
Returns the Tpetra::Map object associated with the range of this operator.
Definition: Ifpack2_BlockRelaxation_def.hpp:411
int getNumCompute() const
Returns the number of calls to compute().
Definition: Ifpack2_BlockRelaxation_def.hpp:437
void setParameters(const Teuchos::ParameterList &params)
Sets all the parameters for the preconditioner.
Definition: Ifpack2_BlockRelaxation_def.hpp:189
void compute()
compute the preconditioner for the specified matrix, diagonal perturbation thresholds and relaxation ...
Definition: Ifpack2_BlockRelaxation_def.hpp:769
Block relaxation preconditioners (or smoothers) for Tpetra::RowMatrix and Tpetra::CrsMatrix sparse ma...
Definition: Ifpack2_BlockRelaxation_decl.hpp:82
double getInitializeTime() const
Returns the time spent in initialize().
Definition: Ifpack2_BlockRelaxation_def.hpp:453
Declaration of a user-defined partitioner in which the user can define a partition of the graph...
bool isParameter(const std::string &name) const
T * getRawPtr() const
bool remove(std::string const &name, bool throwIfNotExists=true)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
double getComputeTime() const
Returns the time spent in compute().
Definition: Ifpack2_BlockRelaxation_def.hpp:461
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition: Ifpack2_BlockRelaxation_def.hpp:476
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_BlockRelaxation_def.hpp:62
virtual ~BlockRelaxation()
Destructor.
Definition: Ifpack2_BlockRelaxation_def.hpp:125
Teuchos::RCP< const map_type > getDomainMap() const
Returns the Tpetra::Map object associated with the domain of this operator.
Definition: Ifpack2_BlockRelaxation_def.hpp:397
Partition in which the user can define a nonoverlapping partition of the graph in any way they choose...
Definition: Ifpack2_Details_UserPartitioner_decl.hpp:69
void resize(size_type new_size, const value_type &x=value_type())
int getNumInitialize() const
Returns the number of calls to initialize().
Definition: Ifpack2_BlockRelaxation_def.hpp:430
void initialize()
Initialize.
Definition: Ifpack2_BlockRelaxation_def.hpp:612
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
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_BlockRelaxation_def.hpp:1148
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_BlockRelaxation_decl.hpp:100
void applyMat(const MV &X, MV &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS) const
Applies the matrix to a Tpetra::MultiVector.
Definition: Ifpack2_BlockRelaxation_def.hpp:596
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_BlockRelaxation_decl.hpp:97
bool isType(const std::string &name) const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
Access only local rows and columns of a sparse matrix.
Definition: Ifpack2_LocalFilter_decl.hpp:161
static double wallTime()
static Teuchos::RCP< BaseContainer > build(std::string containerType, const Teuchos::RCP< const MatrixType > &A, const Teuchos::Array< Teuchos::Array< local_ordinal_type >> &partitions, const Teuchos::RCP< const import_type > importer, bool pointIndexed)
Build a specialization of Ifpack2::Container given a key that has been registered.
Definition: Ifpack2_ContainerFactory_def.hpp:89
Teuchos::RCP< const row_matrix_type > getMatrix() const
The input matrix of this preconditioner&#39;s constructor.
Definition: Ifpack2_BlockRelaxation_def.hpp:388
void getValidParameters(Teuchos::ParameterList &params)
Fills a list which contains all the parameters possibly used by Ifpack2.
Definition: Ifpack2_Parameters.cpp:51
Ifpack2::LinePartitioner: A class to define partitions into a set of lines.
Definition: Ifpack2_LinePartitioner_decl.hpp:78
A class to define linear partitions.
Definition: Ifpack2_LinearPartitioner_decl.hpp:60
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a list of all the parameters that this class accepts.
Definition: Ifpack2_BlockRelaxation_def.hpp:131
void apply(const MV &X, MV &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, scalar_type alpha=Teuchos::ScalarTraits< scalar_type >::one(), scalar_type beta=Teuchos::ScalarTraits< scalar_type >::zero()) const
Applies the preconditioner to X, returns the result in Y.
Definition: Ifpack2_BlockRelaxation_def.hpp:493
BlockRelaxation(const Teuchos::RCP< const row_matrix_type > &Matrix)
Constructor.
Definition: Ifpack2_BlockRelaxation_def.hpp:90
bool is_null() const