10 #ifndef IFPACK2_RELAXATION_DEF_HPP
11 #define IFPACK2_RELAXATION_DEF_HPP
13 #include "Teuchos_StandardParameterEntryValidators.hpp"
15 #include "Tpetra_CrsMatrix.hpp"
16 #include "Tpetra_BlockCrsMatrix.hpp"
17 #include "Tpetra_BlockView.hpp"
19 #include "Ifpack2_Details_getCrsMatrix.hpp"
20 #include "MatrixMarket_Tpetra.hpp"
21 #include "Tpetra_Details_residual.hpp"
25 #include "KokkosSparse_gauss_seidel.hpp"
32 NonnegativeIntValidator () {}
42 const std::string& paramName,
43 const std::string& sublistName)
const
50 anyVal.
type () !=
typeid (int),
52 "Parameter \"" << paramName <<
"\" in sublist \"" << sublistName
53 <<
"\" has the wrong type." << endl <<
"Parameter: " << paramName
54 << endl <<
"Type specified: " << entryName << endl
55 <<
"Type required: int" << endl);
57 const int val = Teuchos::any_cast<
int> (anyVal);
60 "Parameter \"" << paramName <<
"\" in sublist \"" << sublistName
61 <<
"\" is negative." << endl <<
"Parameter: " << paramName
62 << endl <<
"Value specified: " << val << endl
63 <<
"Required range: [0, INT_MAX]" << endl);
68 return "NonnegativeIntValidator";
73 printDoc (
const std::string& docString,
74 std::ostream &out)
const
77 out <<
"#\tValidator Used: " << std::endl;
78 out <<
"#\t\tNonnegativeIntValidator" << std::endl;
85 template<class Scalar, const bool isOrdinal=Teuchos::ScalarTraits<Scalar>::isOrdinal>
89 static const Scalar eps ();
93 template<
class Scalar>
94 class SmallTraits<Scalar, true> {
96 static const Scalar eps () {
102 template<
class Scalar>
103 class SmallTraits<Scalar, false> {
105 static const Scalar eps () {
111 template<
class Scalar,
113 struct RealTraits {};
115 template<
class Scalar>
116 struct RealTraits<Scalar, false> {
117 using val_type = Scalar;
118 using mag_type = Scalar;
119 static KOKKOS_INLINE_FUNCTION mag_type real (
const val_type& z) {
124 template<
class Scalar>
125 struct RealTraits<Scalar, true> {
126 using val_type = Scalar;
128 static KOKKOS_INLINE_FUNCTION mag_type real (
const val_type& z) {
129 return Kokkos::ArithTraits<val_type>::real (z);
133 template<
class Scalar>
134 KOKKOS_INLINE_FUNCTION
typename RealTraits<Scalar>::mag_type
135 getRealValue (
const Scalar& z) {
136 return RealTraits<Scalar>::real (z);
143 template<
class MatrixType>
145 Relaxation<MatrixType>::
146 updateCachedMultiVector (
const Teuchos::RCP<
const Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>>& map,
147 size_t numVecs)
const
151 if (cachedMV_.is_null () ||
152 map.get () != cachedMV_->getMap ().get () ||
153 cachedMV_->getNumVectors () != numVecs) {
154 using MV = Tpetra::MultiVector<scalar_type, local_ordinal_type,
155 global_ordinal_type, node_type>;
156 cachedMV_ =
Teuchos::rcp (
new MV (map, numVecs,
false));
160 template<
class MatrixType>
165 Importer_ = Teuchos::null;
166 pointImporter_ = Teuchos::null;
167 Diagonal_ = Teuchos::null;
168 isInitialized_ =
false;
170 diagOffsets_ = Kokkos::View<size_t*, device_type>();
171 savedDiagOffsets_ =
false;
172 hasBlockCrsMatrix_ =
false;
173 serialGaussSeidel_ = Teuchos::null;
175 IsParallel_ = (A->getRowMap ()->getComm ()->getSize () > 1);
181 template<
class MatrixType>
185 IsParallel_ ((A.
is_null () || A->getRowMap ().
is_null () || A->getRowMap ()->getComm ().
is_null ()) ?
187 A->getRowMap ()->getComm ()->getSize () > 1)
189 this->setObjectLabel (
"Ifpack2::Relaxation");
193 template<
class MatrixType>
199 using Teuchos::parameterList;
202 using Teuchos::rcp_const_cast;
203 using Teuchos::rcp_implicit_cast;
204 using Teuchos::setStringToIntegralParameter;
207 if (validParams_.is_null ()) {
208 RCP<ParameterList> pl = parameterList (
"Ifpack2::Relaxation");
212 Array<std::string> precTypes (8);
213 precTypes[0] =
"Jacobi";
214 precTypes[1] =
"Gauss-Seidel";
215 precTypes[2] =
"Symmetric Gauss-Seidel";
216 precTypes[3] =
"MT Gauss-Seidel";
217 precTypes[4] =
"MT Symmetric Gauss-Seidel";
218 precTypes[5] =
"Richardson";
219 precTypes[6] =
"Two-stage Gauss-Seidel";
220 precTypes[7] =
"Two-stage Symmetric Gauss-Seidel";
221 Array<Details::RelaxationType> precTypeEnums (8);
222 precTypeEnums[0] = Details::JACOBI;
223 precTypeEnums[1] = Details::GS;
224 precTypeEnums[2] = Details::SGS;
225 precTypeEnums[3] = Details::MTGS;
226 precTypeEnums[4] = Details::MTSGS;
227 precTypeEnums[5] = Details::RICHARDSON;
228 precTypeEnums[6] = Details::GS2;
229 precTypeEnums[7] = Details::SGS2;
230 const std::string defaultPrecType (
"Jacobi");
231 setStringToIntegralParameter<Details::RelaxationType> (
"relaxation: type",
232 defaultPrecType,
"Relaxation method", precTypes (), precTypeEnums (),
235 const int numSweeps = 1;
236 RCP<PEV> numSweepsValidator =
237 rcp_implicit_cast<PEV> (
rcp (
new NonnegativeIntValidator));
238 pl->set (
"relaxation: sweeps", numSweeps,
"Number of relaxation sweeps",
239 rcp_const_cast<const PEV> (numSweepsValidator));
242 const int numOuterSweeps = 1;
243 RCP<PEV> numOuterSweepsValidator =
244 rcp_implicit_cast<PEV> (
rcp (
new NonnegativeIntValidator));
245 pl->set (
"relaxation: outer sweeps", numOuterSweeps,
"Number of outer local relaxation sweeps for two-stage GS",
246 rcp_const_cast<const PEV> (numOuterSweepsValidator));
248 const int numInnerSweeps = 1;
249 RCP<PEV> numInnerSweepsValidator =
250 rcp_implicit_cast<PEV> (
rcp (
new NonnegativeIntValidator));
251 pl->set (
"relaxation: inner sweeps", numInnerSweeps,
"Number of inner local relaxation sweeps for two-stage GS",
252 rcp_const_cast<const PEV> (numInnerSweepsValidator));
254 const scalar_type innerDampingFactor = STS::one ();
255 pl->set (
"relaxation: inner damping factor", innerDampingFactor,
"Damping factor for the inner sweep of two-stage GS");
257 const bool innerSpTrsv =
false;
258 pl->set (
"relaxation: inner sparse-triangular solve", innerSpTrsv,
"Specify whether to use sptrsv instead of JR iterations for two-stage GS");
260 const bool compactForm =
false;
261 pl->set (
"relaxation: compact form", compactForm,
"Specify whether to use compact form of recurrence for two-stage GS");
264 pl->set (
"relaxation: damping factor", dampingFactor);
266 const bool zeroStartingSolution =
true;
267 pl->set (
"relaxation: zero starting solution", zeroStartingSolution);
269 const bool doBackwardGS =
false;
270 pl->set (
"relaxation: backward mode", doBackwardGS);
272 const bool doL1Method =
false;
273 pl->set (
"relaxation: use l1", doL1Method);
275 const magnitude_type l1eta = (STM::one() + STM::one() + STM::one()) /
276 (STM::one() + STM::one());
277 pl->set (
"relaxation: l1 eta", l1eta);
280 pl->set (
"relaxation: min diagonal value", minDiagonalValue);
282 const bool fixTinyDiagEntries =
false;
283 pl->set (
"relaxation: fix tiny diagonal entries", fixTinyDiagEntries);
285 const bool checkDiagEntries =
false;
286 pl->set (
"relaxation: check diagonal entries", checkDiagEntries);
289 pl->set(
"relaxation: local smoothing indices", localSmoothingIndices);
291 const bool is_matrix_structurally_symmetric =
false;
292 pl->set(
"relaxation: symmetric matrix structure", is_matrix_structurally_symmetric);
294 const bool ifpack2_dump_matrix =
false;
295 pl->set(
"relaxation: ifpack2 dump matrix", ifpack2_dump_matrix);
297 const int cluster_size = 1;
298 pl->set(
"relaxation: mtgs cluster size", cluster_size);
300 pl->set(
"relaxation: mtgs coloring algorithm",
"Default");
302 const int long_row_threshold = 0;
303 pl->set(
"relaxation: long row threshold", long_row_threshold);
305 const bool timer_for_apply =
true;
306 pl->set(
"timer for apply", timer_for_apply);
308 validParams_ = rcp_const_cast<
const ParameterList> (pl);
314 template<
class MatrixType>
317 using Teuchos::getIntegralValue;
318 using Teuchos::getStringValue;
321 typedef scalar_type ST;
323 if (pl.
isType<
double>(
"relaxation: damping factor")) {
326 ST df = pl.
get<
double>(
"relaxation: damping factor");
327 pl.
remove(
"relaxation: damping factor");
328 pl.
set(
"relaxation: damping factor",df);
333 const Details::RelaxationType precType =
334 getIntegralValue<Details::RelaxationType> (pl,
"relaxation: type");
335 const std::string precTypeStr = getStringValue<Details::RelaxationType>(pl,
"relaxation: type");
337 pl.set<std::string>(
"relaxation: type", precTypeStr);
338 pl.get<std::string>(
"relaxation: type");
339 const int numSweeps = pl.get<
int> (
"relaxation: sweeps");
340 const ST dampingFactor = pl.get<ST> (
"relaxation: damping factor");
341 const bool zeroStartSol = pl.get<
bool> (
"relaxation: zero starting solution");
342 const bool doBackwardGS = pl.get<
bool> (
"relaxation: backward mode");
343 const bool doL1Method = pl.get<
bool> (
"relaxation: use l1");
344 const magnitude_type l1Eta = pl.get<magnitude_type> (
"relaxation: l1 eta");
345 const ST minDiagonalValue = pl.get<ST> (
"relaxation: min diagonal value");
346 const bool fixTinyDiagEntries = pl.get<
bool> (
"relaxation: fix tiny diagonal entries");
347 const bool checkDiagEntries = pl.get<
bool> (
"relaxation: check diagonal entries");
348 const bool is_matrix_structurally_symmetric = pl.get<
bool> (
"relaxation: symmetric matrix structure");
349 const bool ifpack2_dump_matrix = pl.get<
bool> (
"relaxation: ifpack2 dump matrix");
350 const bool timer_for_apply = pl.get<
bool> (
"timer for apply");
351 int cluster_size = 1;
352 if(pl.isParameter (
"relaxation: mtgs cluster size"))
353 cluster_size = pl.get<
int> (
"relaxation: mtgs cluster size");
354 int long_row_threshold = 0;
355 if(pl.isParameter (
"relaxation: long row threshold"))
356 long_row_threshold = pl.get<
int> (
"relaxation: long row threshold");
357 std::string color_algo_name = pl.get<std::string>(
"relaxation: mtgs coloring algorithm");
359 for(
char& c : color_algo_name)
361 if(color_algo_name ==
"default")
362 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_DEFAULT;
363 else if(color_algo_name ==
"serial")
364 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_SERIAL;
365 else if(color_algo_name ==
"vb")
366 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VB;
367 else if(color_algo_name ==
"vbbit")
368 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBBIT;
369 else if(color_algo_name ==
"vbcs")
370 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBCS;
371 else if(color_algo_name ==
"vbd")
372 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBD;
373 else if(color_algo_name ==
"vbdbit")
374 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBDBIT;
375 else if(color_algo_name ==
"eb")
376 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_EB;
379 std::ostringstream msg;
380 msg <<
"Ifpack2::Relaxation: 'relaxation: mtgs coloring algorithm' = '" << color_algo_name <<
"' is not valid.\n";
381 msg <<
"Choices (not case sensitive) are: Default, Serial, VB, VBBIT, VBCS, VBD, VBDBIT, EB.";
383 true, std::invalid_argument, msg.str());
389 if (!std::is_same<double, ST>::value && pl.isType<
double>(
"relaxation: inner damping factor")) {
392 ST df = pl.
get<
double>(
"relaxation: inner damping factor");
393 pl.remove(
"relaxation: inner damping factor");
394 pl.set(
"relaxation: inner damping factor",df);
397 if (long_row_threshold > 0) {
399 cluster_size != 1, std::invalid_argument,
"Ifpack2::Relaxation: "
400 "Requested long row MTGS/MTSGS algorithm and cluster GS/SGS, but those are not compatible.");
402 precType != Details::RelaxationType::MTGS && precType != Details::RelaxationType::MTSGS,
403 std::invalid_argument,
"Ifpack2::Relaxation: "
404 "Requested long row MTGS/MTSGS algorithm, but this is only compatible with preconditioner types "
405 "'MT Gauss-Seidel' and 'MT Symmetric Gauss-Seidel'.");
408 const ST innerDampingFactor = pl.get<ST> (
"relaxation: inner damping factor");
409 const int numInnerSweeps = pl.get<
int> (
"relaxation: inner sweeps");
410 const int numOuterSweeps = pl.get<
int> (
"relaxation: outer sweeps");
411 const bool innerSpTrsv = pl.get<
bool> (
"relaxation: inner sparse-triangular solve");
412 const bool compactForm = pl.get<
bool> (
"relaxation: compact form");
415 PrecType_ = precType;
416 NumSweeps_ = numSweeps;
417 DampingFactor_ = dampingFactor;
418 ZeroStartingSolution_ = zeroStartSol;
419 DoBackwardGS_ = doBackwardGS;
420 DoL1Method_ = doL1Method;
422 MinDiagonalValue_ = minDiagonalValue;
423 fixTinyDiagEntries_ = fixTinyDiagEntries;
424 checkDiagEntries_ = checkDiagEntries;
425 clusterSize_ = cluster_size;
426 longRowThreshold_ = long_row_threshold;
427 is_matrix_structurally_symmetric_ = is_matrix_structurally_symmetric;
428 ifpack2_dump_matrix_ = ifpack2_dump_matrix;
429 localSmoothingIndices_ = localSmoothingIndices;
431 NumInnerSweeps_ = numInnerSweeps;
432 NumOuterSweeps_ = numOuterSweeps;
433 InnerSpTrsv_ = innerSpTrsv;
434 InnerDampingFactor_ = innerDampingFactor;
435 CompactForm_ = compactForm;
436 TimerForApply_ = timer_for_apply;
440 template<
class MatrixType>
445 this->setParametersImpl(const_cast<Teuchos::ParameterList&>(pl));
449 template<
class MatrixType>
453 A_.
is_null (), std::runtime_error,
"Ifpack2::Relaxation::getComm: "
454 "The input matrix A is null. Please call setMatrix() with a nonnull "
455 "input matrix before calling this method.");
456 return A_->getRowMap ()->getComm ();
460 template<
class MatrixType>
467 template<
class MatrixType>
468 Teuchos::RCP<
const Tpetra::Map<
typename MatrixType::local_ordinal_type,
469 typename MatrixType::global_ordinal_type,
470 typename MatrixType::node_type> >
473 A_.
is_null (), std::runtime_error,
"Ifpack2::Relaxation::getDomainMap: "
474 "The input matrix A is null. Please call setMatrix() with a nonnull "
475 "input matrix before calling this method.");
476 return A_->getDomainMap ();
480 template<
class MatrixType>
481 Teuchos::RCP<
const Tpetra::Map<
typename MatrixType::local_ordinal_type,
482 typename MatrixType::global_ordinal_type,
483 typename MatrixType::node_type> >
486 A_.
is_null (), std::runtime_error,
"Ifpack2::Relaxation::getRangeMap: "
487 "The input matrix A is null. Please call setMatrix() with a nonnull "
488 "input matrix before calling this method.");
489 return A_->getRangeMap ();
493 template<
class MatrixType>
499 template<
class MatrixType>
501 return(NumInitialize_);
505 template<
class MatrixType>
511 template<
class MatrixType>
517 template<
class MatrixType>
519 return(InitializeTime_);
523 template<
class MatrixType>
525 return(ComputeTime_);
529 template<
class MatrixType>
535 template<
class MatrixType>
537 return(ComputeFlops_);
541 template<
class MatrixType>
548 template<
class MatrixType>
551 A_.
is_null (), std::runtime_error,
"Ifpack2::Relaxation::getNodeSmootherComplexity: "
552 "The input matrix A is null. Please call setMatrix() with a nonnull "
553 "input matrix, then call compute(), before calling this method.");
555 return A_->getLocalNumRows() + A_->getLocalNumEntries();
559 template<
class MatrixType>
562 apply (
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
563 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
571 using Teuchos::rcpFromRef;
575 A_.
is_null (), std::runtime_error,
"Ifpack2::Relaxation::apply: "
576 "The input matrix A is null. Please call setMatrix() with a nonnull "
577 "input matrix, then call compute(), before calling this method.");
581 "Ifpack2::Relaxation::apply: You must call compute() on this Ifpack2 "
582 "preconditioner instance before you may call apply(). You may call "
583 "isComputed() to find out if compute() has been called already.");
584 TEUCHOS_TEST_FOR_EXCEPTION(
585 X.getNumVectors() != Y.getNumVectors(),
587 "Ifpack2::Relaxation::apply: X and Y have different numbers of columns. "
588 "X has " << X.getNumVectors() <<
" columns, but Y has "
589 << Y.getNumVectors() <<
" columns.");
590 TEUCHOS_TEST_FOR_EXCEPTION(
591 beta != STS::zero (), std::logic_error,
592 "Ifpack2::Relaxation::apply: beta = " << beta <<
" != 0 case not "
596 const std::string timerName (
"Ifpack2::Relaxation::apply");
597 if (TimerForApply_) {
613 if (alpha == STS::zero ()) {
615 Y.putScalar (STS::zero ());
625 Xcopy = rcpFromRef (X);
633 case Ifpack2::Details::JACOBI:
634 ApplyInverseJacobi(*Xcopy,Y);
636 case Ifpack2::Details::GS:
637 ApplyInverseSerialGS(*Xcopy, Y, DoBackwardGS_ ? Tpetra::Backward : Tpetra::Forward);
639 case Ifpack2::Details::SGS:
640 ApplyInverseSerialGS(*Xcopy, Y, Tpetra::Symmetric);
642 case Ifpack2::Details::MTGS:
643 case Ifpack2::Details::GS2:
644 ApplyInverseMTGS_CrsMatrix(*Xcopy, Y, DoBackwardGS_ ? Tpetra::Backward : Tpetra::Forward);
646 case Ifpack2::Details::MTSGS:
647 case Ifpack2::Details::SGS2:
648 ApplyInverseMTGS_CrsMatrix(*Xcopy, Y, Tpetra::Symmetric);
650 case Ifpack2::Details::RICHARDSON:
651 ApplyInverseRichardson(*Xcopy,Y);
655 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
656 "Ifpack2::Relaxation::apply: Invalid preconditioner type enum value "
657 << PrecType_ <<
". Please report this bug to the Ifpack2 developers.");
659 if (alpha != STS::one ()) {
661 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
662 const double numVectors = as<double> (Y.getNumVectors ());
663 ApplyFlops_ += numGlobalRows * numVectors;
667 ApplyTime_ += (time.
wallTime() - startTime);
672 template<
class MatrixType>
675 applyMat (
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
676 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
680 A_.
is_null (), std::runtime_error,
"Ifpack2::Relaxation::applyMat: "
681 "The input matrix A is null. Please call setMatrix() with a nonnull "
682 "input matrix, then call compute(), before calling this method.");
684 ! isComputed (), std::runtime_error,
"Ifpack2::Relaxation::applyMat: "
685 "isComputed() must be true before you may call applyMat(). "
686 "Please call compute() before calling this method.");
687 TEUCHOS_TEST_FOR_EXCEPTION(
688 X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
689 "Ifpack2::Relaxation::applyMat: X.getNumVectors() = " << X.getNumVectors ()
690 <<
" != Y.getNumVectors() = " << Y.getNumVectors () <<
".");
691 A_->apply (X, Y, mode);
695 template<
class MatrixType>
698 const char methodName[] =
"Ifpack2::Relaxation::initialize";
701 (A_.
is_null (), std::runtime_error, methodName <<
": The "
702 "input matrix A is null. Please call setMatrix() with "
703 "a nonnull input matrix before calling this method.");
708 double startTime = timer->wallTime();
712 isInitialized_ =
false;
715 auto rowMap = A_->getRowMap ();
716 auto comm = rowMap.
is_null () ? Teuchos::null : rowMap->getComm ();
717 IsParallel_ = ! comm.is_null () && comm->getSize () > 1;
727 Importer_ = IsParallel_ ? A_->getGraph ()->getImporter () :
732 Teuchos::rcp_dynamic_cast<
const block_crs_matrix_type> (A_);
733 hasBlockCrsMatrix_ = ! A_bcrs.
is_null ();
736 serialGaussSeidel_ = Teuchos::null;
738 if (PrecType_ == Details::MTGS || PrecType_ == Details::MTSGS ||
739 PrecType_ == Details::GS2 || PrecType_ == Details::SGS2) {
740 auto crsMat = Details::getCrsMatrix(A_);
742 (crsMat.is_null(), std::logic_error, methodName <<
": "
743 "Multithreaded Gauss-Seidel methods currently only work "
744 "when the input matrix is a Tpetra::CrsMatrix.");
749 if (ifpack2_dump_matrix_) {
750 static int sequence_number = 0;
751 const std::string file_name =
"Ifpack2_MT_GS_" +
752 std::to_string (sequence_number++) +
".mtx";
753 using writer_type = Tpetra::MatrixMarket::Writer<crs_matrix_type>;
754 writer_type::writeSparseFile (file_name, crsMat);
757 this->mtKernelHandle_ =
Teuchos::rcp (
new mt_kernel_handle_type ());
758 if (mtKernelHandle_->get_gs_handle () ==
nullptr) {
759 if (PrecType_ == Details::GS2 || PrecType_ == Details::SGS2)
760 mtKernelHandle_->create_gs_handle (KokkosSparse::GS_TWOSTAGE);
761 else if(this->clusterSize_ == 1) {
762 mtKernelHandle_->create_gs_handle (KokkosSparse::GS_DEFAULT, this->mtColoringAlgorithm_);
763 mtKernelHandle_->get_point_gs_handle()->set_long_row_threshold(longRowThreshold_);
766 mtKernelHandle_->create_gs_handle (KokkosSparse::CLUSTER_DEFAULT, this->clusterSize_, this->mtColoringAlgorithm_);
768 local_matrix_device_type kcsr = crsMat->getLocalMatrixDevice ();
769 if (PrecType_ == Details::GS2 || PrecType_ == Details::SGS2) {
771 mtKernelHandle_->set_gs_set_num_inner_sweeps (NumInnerSweeps_);
772 mtKernelHandle_->set_gs_set_num_outer_sweeps (NumOuterSweeps_);
773 mtKernelHandle_->set_gs_set_inner_damp_factor (InnerDampingFactor_);
774 mtKernelHandle_->set_gs_twostage (!InnerSpTrsv_, A_->getLocalNumRows ());
775 mtKernelHandle_->set_gs_twostage_compact_form (CompactForm_);
778 KokkosSparse::Experimental::gauss_seidel_symbolic(
779 mtKernelHandle_.getRawPtr (),
780 A_->getLocalNumRows (),
781 A_->getLocalNumCols (),
784 is_matrix_structurally_symmetric_);
788 InitializeTime_ += (timer->wallTime() - startTime);
790 isInitialized_ =
true;
794 template <
typename BlockDiagView>
795 struct InvertDiagBlocks {
796 typedef typename BlockDiagView::size_type Size;
799 typedef Kokkos::MemoryTraits<Kokkos::Unmanaged> Unmanaged;
800 template <
typename View>
801 using UnmanagedView = Kokkos::View<
typename View::data_type,
typename View::array_layout,
802 typename View::device_type, Unmanaged>;
804 typedef typename BlockDiagView::non_const_value_type Scalar;
805 typedef typename BlockDiagView::device_type Device;
806 typedef Kokkos::View<Scalar**, Kokkos::LayoutRight, Device> RWrk;
807 typedef Kokkos::View<int**, Kokkos::LayoutRight, Device> IWrk;
809 UnmanagedView<BlockDiagView> block_diag_;
813 UnmanagedView<RWrk> rwrk_;
815 UnmanagedView<IWrk> iwrk_;
818 InvertDiagBlocks (BlockDiagView& block_diag)
819 : block_diag_(block_diag)
821 const auto blksz = block_diag.extent(1);
822 Kokkos::resize(rwrk_buf_, block_diag_.extent(0), blksz);
824 Kokkos::resize(iwrk_buf_, block_diag_.extent(0), blksz);
828 KOKKOS_INLINE_FUNCTION
829 void operator() (
const Size i,
int& jinfo)
const {
830 auto D_cur = Kokkos::subview(block_diag_, i, Kokkos::ALL(), Kokkos::ALL());
831 auto ipiv = Kokkos::subview(iwrk_, i, Kokkos::ALL());
832 auto work = Kokkos::subview(rwrk_, i, Kokkos::ALL());
834 Tpetra::GETF2(D_cur, ipiv, info);
839 Tpetra::GETRI(D_cur, ipiv, work, info);
845 template<
class MatrixType>
846 void Relaxation<MatrixType>::computeBlockCrs ()
859 using Teuchos::rcp_dynamic_cast;
860 using Teuchos::reduceAll;
861 typedef local_ordinal_type LO;
863 const std::string timerName (
"Ifpack2::Relaxation::computeBlockCrs");
868 double startTime = timer->
wallTime();
873 A_.
is_null (), std::runtime_error,
"Ifpack2::Relaxation::"
874 "computeBlockCrs: The input matrix A is null. Please call setMatrix() "
875 "with a nonnull input matrix, then call initialize(), before calling "
877 auto blockCrsA = rcp_dynamic_cast<
const block_crs_matrix_type> (A_);
879 blockCrsA.is_null(), std::logic_error,
"Ifpack2::Relaxation::"
880 "computeBlockCrs: A_ is not a BlockCrsMatrix, but it should be if we "
881 "got this far. Please report this bug to the Ifpack2 developers.");
883 const scalar_type one = STS::one ();
888 const LO lclNumMeshRows =
889 blockCrsA->getCrsGraph ().getLocalNumRows ();
890 const LO blockSize = blockCrsA->getBlockSize ();
892 if (! savedDiagOffsets_) {
893 blockDiag_ = block_diag_type ();
894 blockDiag_ = block_diag_type (
"Ifpack2::Relaxation::blockDiag_",
895 lclNumMeshRows, blockSize, blockSize);
896 if (Teuchos::as<LO>(diagOffsets_.extent (0) ) < lclNumMeshRows) {
899 diagOffsets_ = Kokkos::View<size_t*, device_type> ();
900 diagOffsets_ = Kokkos::View<size_t*, device_type> (
"offsets", lclNumMeshRows);
902 blockCrsA->getCrsGraph ().getLocalDiagOffsets (diagOffsets_);
904 (static_cast<size_t> (diagOffsets_.extent (0)) !=
905 static_cast<size_t> (blockDiag_.extent (0)),
906 std::logic_error,
"diagOffsets_.extent(0) = " <<
907 diagOffsets_.extent (0) <<
" != blockDiag_.extent(0) = "
908 << blockDiag_.extent (0) <<
909 ". Please report this bug to the Ifpack2 developers.");
910 savedDiagOffsets_ =
true;
912 blockCrsA->getLocalDiagCopy (blockDiag_, diagOffsets_);
919 unmanaged_block_diag_type blockDiag = blockDiag_;
921 if (DoL1Method_ && IsParallel_) {
922 const scalar_type two = one + one;
923 const size_t maxLength = A_->getLocalMaxNumRowEntries ();
924 nonconst_local_inds_host_view_type indices (
"indices",maxLength);
925 nonconst_values_host_view_type values_ (
"values",maxLength * blockSize * blockSize);
926 size_t numEntries = 0;
928 for (LO i = 0; i < lclNumMeshRows; ++i) {
930 blockCrsA->getLocalRowCopy (i, indices, values_, numEntries);
931 scalar_type * values =
reinterpret_cast<scalar_type*
>(values_.data());
933 auto diagBlock = Kokkos::subview (blockDiag, i, ALL (), ALL ());
934 for (LO subRow = 0; subRow < blockSize; ++subRow) {
935 magnitude_type diagonal_boost = STM::zero ();
936 for (
size_t k = 0 ; k < numEntries ; ++k) {
937 if (indices[k] >= lclNumMeshRows) {
938 const size_t offset = blockSize*blockSize*k + subRow*blockSize;
939 for (LO subCol = 0; subCol < blockSize; ++subCol) {
940 diagonal_boost += STS::magnitude (values[offset+subCol] / two);
944 if (STS::magnitude (diagBlock(subRow, subRow)) < L1Eta_ * diagonal_boost) {
945 diagBlock(subRow, subRow) += diagonal_boost;
953 Impl::InvertDiagBlocks<unmanaged_block_diag_type> idb(blockDiag);
954 typedef typename unmanaged_block_diag_type::execution_space exec_space;
955 typedef Kokkos::RangePolicy<exec_space, LO> range_type;
957 Kokkos::parallel_reduce (range_type (0, lclNumMeshRows), idb, info);
963 (info > 0, std::runtime_error,
"GETF2 or GETRI failed on = " << info
964 <<
" diagonal blocks.");
969 #ifdef HAVE_IFPACK2_DEBUG
970 const int numResults = 2;
972 int lclResults[2], gblResults[2];
973 lclResults[0] = info;
974 lclResults[1] = -info;
977 reduceAll<int, int> (* (A_->getGraph ()->getComm ()), REDUCE_MIN,
978 numResults, lclResults, gblResults);
980 (gblResults[0] != 0 || gblResults[1] != 0, std::runtime_error,
981 "Ifpack2::Relaxation::compute: When processing the input "
982 "Tpetra::BlockCrsMatrix, one or more diagonal block LU factorizations "
983 "failed on one or more (MPI) processes.");
984 #endif // HAVE_IFPACK2_DEBUG
985 serialGaussSeidel_ =
rcp(
new SerialGaussSeidel(blockCrsA, blockDiag_, localSmoothingIndices_, DampingFactor_));
988 ComputeTime_ += (timer->
wallTime() - startTime);
993 template<
class MatrixType>
1006 using Teuchos::reduceAll;
1010 using IST =
typename vector_type::impl_scalar_type;
1011 using KAT = Kokkos::ArithTraits<IST>;
1013 const char methodName[] =
"Ifpack2::Relaxation::compute";
1014 const scalar_type zero = STS::zero ();
1015 const scalar_type one = STS::one ();
1018 (A_.
is_null (), std::runtime_error, methodName <<
": "
1019 "The input matrix A is null. Please call setMatrix() with a nonnull "
1020 "input matrix, then call initialize(), before calling this method.");
1023 if (! isInitialized ()) {
1027 if (hasBlockCrsMatrix_) {
1034 double startTime = timer->
wallTime();
1046 IST oneOverMinDiagVal = KAT::one () /
static_cast<IST
> (SmallTraits<scalar_type>::eps ());
1047 if ( MinDiagonalValue_ != zero)
1048 oneOverMinDiagVal = KAT::one () /
static_cast<IST
> (MinDiagonalValue_);
1051 const magnitude_type minDiagValMag = STS::magnitude (MinDiagonalValue_);
1053 const LO numMyRows =
static_cast<LO
> (A_->getLocalNumRows ());
1056 (NumSweeps_ < 0, std::logic_error, methodName
1057 <<
": NumSweeps_ = " << NumSweeps_ <<
" < 0. "
1058 "Please report this bug to the Ifpack2 developers.");
1059 IsComputed_ =
false;
1061 if (Diagonal_.is_null()) {
1064 Diagonal_ =
rcp (
new vector_type (A_->getRowMap (),
false));
1067 if (checkDiagEntries_) {
1073 size_t numSmallDiagEntries = 0;
1074 size_t numZeroDiagEntries = 0;
1075 size_t numNegDiagEntries = 0;
1082 A_->getLocalDiagCopy (*Diagonal_);
1083 std::unique_ptr<vector_type> origDiag;
1084 origDiag = std::unique_ptr<vector_type> (
new vector_type (*Diagonal_,
Teuchos::Copy));
1085 auto diag2d = Diagonal_->getLocalViewHost(Tpetra::Access::ReadWrite);
1086 auto diag = Kokkos::subview(diag2d, Kokkos::ALL(), 0);
1093 if (numMyRows != 0) {
1095 minMagDiagEntryMag = d_0_mag;
1096 maxMagDiagEntryMag = d_0_mag;
1105 for (LO i = 0; i < numMyRows; ++i) {
1106 const IST d_i = diag(i);
1110 const auto d_i_real = getRealValue (d_i);
1114 if (d_i_real < STM::zero ()) {
1115 ++numNegDiagEntries;
1117 if (d_i_mag < minMagDiagEntryMag) {
1118 minMagDiagEntryMag = d_i_mag;
1120 if (d_i_mag > maxMagDiagEntryMag) {
1121 maxMagDiagEntryMag = d_i_mag;
1124 if (fixTinyDiagEntries_) {
1126 if (d_i_mag <= minDiagValMag) {
1127 ++numSmallDiagEntries;
1128 if (d_i_mag == STM::zero ()) {
1129 ++numZeroDiagEntries;
1131 diag(i) = oneOverMinDiagVal;
1134 diag(i) = KAT::one () / d_i;
1139 if (d_i_mag <= minDiagValMag) {
1140 ++numSmallDiagEntries;
1141 if (d_i_mag == STM::zero ()) {
1142 ++numZeroDiagEntries;
1145 diag(i) = KAT::one () / d_i;
1163 const Comm<int>& comm = * (A_->getRowMap ()->getComm ());
1166 Array<magnitude_type> localVals (2);
1167 localVals[0] = minMagDiagEntryMag;
1169 localVals[1] = -maxMagDiagEntryMag;
1170 Array<magnitude_type> globalVals (2);
1171 reduceAll<int, magnitude_type> (comm, REDUCE_MIN, 2,
1172 localVals.getRawPtr (),
1173 globalVals.getRawPtr ());
1174 globalMinMagDiagEntryMag_ = globalVals[0];
1175 globalMaxMagDiagEntryMag_ = -globalVals[1];
1177 Array<size_t> localCounts (3);
1178 localCounts[0] = numSmallDiagEntries;
1179 localCounts[1] = numZeroDiagEntries;
1180 localCounts[2] = numNegDiagEntries;
1181 Array<size_t> globalCounts (3);
1182 reduceAll<int, size_t> (comm, REDUCE_SUM, 3,
1183 localCounts.getRawPtr (),
1184 globalCounts.getRawPtr ());
1185 globalNumSmallDiagEntries_ = globalCounts[0];
1186 globalNumZeroDiagEntries_ = globalCounts[1];
1187 globalNumNegDiagEntries_ = globalCounts[2];
1191 vector_type diff (A_->getRowMap ());
1192 diff.reciprocal (*origDiag);
1193 diff.update (-one, *Diagonal_, one);
1194 globalDiagNormDiff_ = diff.norm2 ();
1201 bool debugAgainstSlowPath =
false;
1203 auto crsMat = Details::getCrsMatrix(A_);
1205 if (crsMat.get() && crsMat->isFillComplete ()) {
1210 if (invDiagKernel_.is_null())
1213 invDiagKernel_->setMatrix(crsMat);
1214 invDiagKernel_->compute(*Diagonal_,
1215 DoL1Method_ && IsParallel_, L1Eta_,
1216 fixTinyDiagEntries_, minDiagValMag);
1217 savedDiagOffsets_ =
true;
1221 #ifdef HAVE_IFPACK2_DEBUG
1222 debugAgainstSlowPath =
true;
1226 if (crsMat.is_null() || ! crsMat->isFillComplete () || debugAgainstSlowPath) {
1233 RCP<vector_type> Diagonal;
1234 if (debugAgainstSlowPath)
1235 Diagonal =
rcp(
new vector_type(A_->getRowMap ()));
1237 Diagonal = Diagonal_;
1239 A_->getLocalDiagCopy (*Diagonal);
1249 if (DoL1Method_ && IsParallel_) {
1251 auto diag = Diagonal->getLocalViewHost(Tpetra::Access::ReadWrite);
1253 const size_t maxLength = A_row.getLocalMaxNumRowEntries ();
1254 nonconst_local_inds_host_view_type indices(
"indices",maxLength);
1255 nonconst_values_host_view_type values(
"values",maxLength);
1258 for (LO i = 0; i < numMyRows; ++i) {
1259 A_row.getLocalRowCopy (i, indices, values, numEntries);
1261 for (
size_t k = 0 ; k < numEntries; ++k) {
1262 if (indices[k] >= numMyRows) {
1263 diagonal_boost += STS::magnitude (values[k] / two);
1266 if (KAT::magnitude (diag(i, 0)) < L1Eta_ * diagonal_boost) {
1267 diag(i, 0) += diagonal_boost;
1275 if (fixTinyDiagEntries_) {
1279 auto localDiag = Diagonal->getLocalViewDevice(Tpetra::Access::ReadWrite);
1280 Kokkos::parallel_for(Kokkos::RangePolicy<MyExecSpace>(0, localDiag.extent(0)),
1281 KOKKOS_LAMBDA (local_ordinal_type i) {
1282 auto d_i = localDiag(i, 0);
1285 if (d_i_mag <= minDiagValMag) {
1286 d_i = oneOverMinDiagVal;
1291 d_i = IST (KAT::one () / d_i);
1293 localDiag(i, 0) = d_i;
1297 Diagonal->reciprocal (*Diagonal);
1300 if (debugAgainstSlowPath) {
1302 Diagonal->update (STS::one (), *Diagonal_, -STS::one ());
1307 (err > 100*STM::eps(), std::logic_error, methodName <<
": "
1308 <<
"\"fast-path\" diagonal computation failed. "
1309 "\\|D1 - D2\\|_inf = " << err <<
".");
1316 if (STS::isComplex) {
1317 ComputeFlops_ += 4.0 * numMyRows;
1320 ComputeFlops_ += numMyRows;
1323 if (PrecType_ == Ifpack2::Details::MTGS ||
1324 PrecType_ == Ifpack2::Details::MTSGS ||
1325 PrecType_ == Ifpack2::Details::GS2 ||
1326 PrecType_ == Ifpack2::Details::SGS2) {
1329 using scalar_view_t =
typename local_matrix_device_type::values_type;
1332 (crsMat.is_null(), std::logic_error, methodName <<
": "
1333 "Multithreaded Gauss-Seidel methods currently only work "
1334 "when the input matrix is a Tpetra::CrsMatrix.");
1335 local_matrix_device_type kcsr = crsMat->getLocalMatrixDevice ();
1339 auto diagView_2d = Diagonal_->getLocalViewDevice (Tpetra::Access::ReadWrite);
1340 scalar_view_t diagView_1d = Kokkos::subview (diagView_2d, Kokkos::ALL (), 0);
1341 KokkosSparse::Experimental::gauss_seidel_numeric(
1342 mtKernelHandle_.getRawPtr (),
1343 A_->getLocalNumRows (),
1344 A_->getLocalNumCols (),
1349 is_matrix_structurally_symmetric_);
1351 else if(PrecType_ == Ifpack2::Details::GS || PrecType_ == Ifpack2::Details::SGS) {
1353 serialGaussSeidel_ =
rcp(
new SerialGaussSeidel(crsMat, Diagonal_, localSmoothingIndices_, DampingFactor_));
1355 serialGaussSeidel_ =
rcp(
new SerialGaussSeidel(A_, Diagonal_, localSmoothingIndices_, DampingFactor_));
1359 ComputeTime_ += (timer->
wallTime() - startTime);
1365 template<
class MatrixType>
1368 ApplyInverseRichardson (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1369 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const
1372 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1373 const double numVectors = as<double> (X.getNumVectors ());
1374 if (ZeroStartingSolution_) {
1378 Y.scale(DampingFactor_,X);
1384 double flopUpdate = 0.0;
1385 if (DampingFactor_ == STS::one ()) {
1387 flopUpdate = numGlobalRows * numVectors;
1391 flopUpdate = numGlobalRows * numVectors;
1393 ApplyFlops_ += flopUpdate;
1394 if (NumSweeps_ == 1) {
1400 const int startSweep = ZeroStartingSolution_ ? 1 : 0;
1403 updateCachedMultiVector(Y.getMap(),as<size_t>(numVectors));
1405 for (
int j = startSweep; j < NumSweeps_; ++j) {
1407 Tpetra::Details::residual(*A_,Y,X,*cachedMV_);
1408 Y.update(DampingFactor_,*cachedMV_,STS::one());
1422 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1423 const double dampingFlops = (DampingFactor_ == STS::one ()) ? 0.0 : 1.0;
1424 ApplyFlops_ += as<double> (NumSweeps_ - startSweep) * numVectors *
1425 (2.0 * numGlobalNonzeros + dampingFlops);
1429 template<
class MatrixType>
1431 Relaxation<MatrixType>::
1432 ApplyInverseJacobi (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1433 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const
1436 if (hasBlockCrsMatrix_) {
1437 ApplyInverseJacobi_BlockCrsMatrix (X, Y);
1441 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1442 const double numVectors = as<double> (X.getNumVectors ());
1443 if (ZeroStartingSolution_) {
1448 Y.elementWiseMultiply (DampingFactor_, *Diagonal_, X, STS::zero ());
1454 double flopUpdate = 0.0;
1455 if (DampingFactor_ == STS::one ()) {
1457 flopUpdate = numGlobalRows * numVectors;
1461 flopUpdate = 2.0 * numGlobalRows * numVectors;
1463 ApplyFlops_ += flopUpdate;
1464 if (NumSweeps_ == 1) {
1470 const int startSweep = ZeroStartingSolution_ ? 1 : 0;
1473 updateCachedMultiVector(Y.getMap(),as<size_t>(numVectors));
1475 for (
int j = startSweep; j < NumSweeps_; ++j) {
1477 Tpetra::Details::residual(*A_,Y,X,*cachedMV_);
1478 Y.elementWiseMultiply (DampingFactor_, *Diagonal_, *cachedMV_, STS::one ());
1492 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1493 const double dampingFlops = (DampingFactor_ == STS::one ()) ? 0.0 : 1.0;
1494 ApplyFlops_ += as<double> (NumSweeps_ - startSweep) * numVectors *
1495 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1498 template<
class MatrixType>
1500 Relaxation<MatrixType>::
1501 ApplyInverseJacobi_BlockCrsMatrix (
const Tpetra::MultiVector<scalar_type,
1503 global_ordinal_type,
1505 Tpetra::MultiVector<scalar_type,
1507 global_ordinal_type,
1508 node_type>& Y)
const
1510 using Tpetra::BlockMultiVector;
1511 using BMV = BlockMultiVector<scalar_type, local_ordinal_type,
1512 global_ordinal_type, node_type>;
1514 const block_crs_matrix_type* blockMatConst =
1515 dynamic_cast<const block_crs_matrix_type*
> (A_.
getRawPtr ());
1517 (blockMatConst ==
nullptr, std::logic_error,
"This method should "
1518 "never be called if the matrix A_ is not a BlockCrsMatrix. "
1519 "Please report this bug to the Ifpack2 developers.");
1524 block_crs_matrix_type* blockMat =
1525 const_cast<block_crs_matrix_type*
> (blockMatConst);
1527 auto meshRowMap = blockMat->getRowMap ();
1528 auto meshColMap = blockMat->getColMap ();
1529 const local_ordinal_type blockSize = blockMat->getBlockSize ();
1531 BMV X_blk (X, *meshColMap, blockSize);
1532 BMV Y_blk (Y, *meshRowMap, blockSize);
1534 if (ZeroStartingSolution_) {
1538 Y_blk.blockWiseMultiply (DampingFactor_, blockDiag_, X_blk);
1539 if (NumSweeps_ == 1) {
1544 auto pointRowMap = Y.getMap ();
1545 const size_t numVecs = X.getNumVectors ();
1549 BMV A_times_Y (*meshRowMap, *pointRowMap, blockSize, numVecs);
1553 const int startSweep = ZeroStartingSolution_ ? 1 : 0;
1555 for (
int j = startSweep; j < NumSweeps_; ++j) {
1556 blockMat->applyBlock (Y_blk, A_times_Y);
1558 Y_blk.blockJacobiUpdate (DampingFactor_, blockDiag_,
1559 X_blk, A_times_Y, STS::one ());
1563 template<
class MatrixType>
1565 Relaxation<MatrixType>::
1566 ApplyInverseSerialGS (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1567 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
1568 Tpetra::ESweepDirection direction)
const
1570 using this_type = Relaxation<MatrixType>;
1580 auto blockCrsMat = Teuchos::rcp_dynamic_cast<
const block_crs_matrix_type> (A_);
1581 auto crsMat = Details::getCrsMatrix(A_);
1582 if (blockCrsMat.get()) {
1583 const_cast<this_type&
> (*this).ApplyInverseSerialGS_BlockCrsMatrix (*blockCrsMat, X, Y, direction);
1585 else if (crsMat.get()) {
1586 ApplyInverseSerialGS_CrsMatrix (*crsMat, X, Y, direction);
1589 ApplyInverseSerialGS_RowMatrix (X, Y, direction);
1594 template<
class MatrixType>
1596 Relaxation<MatrixType>::
1597 ApplyInverseSerialGS_RowMatrix (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1598 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
1599 Tpetra::ESweepDirection direction)
const {
1606 using Teuchos::rcpFromRef;
1607 typedef Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> MV;
1612 if (ZeroStartingSolution_) {
1613 Y.putScalar (STS::zero ());
1616 size_t NumVectors = X.getNumVectors();
1620 if (Importer_.is_null ()) {
1621 updateCachedMultiVector (Y.getMap (), NumVectors);
1624 updateCachedMultiVector (Importer_->getTargetMap (), NumVectors);
1629 Y2 = rcpFromRef (Y);
1632 for (
int j = 0; j < NumSweeps_; ++j) {
1635 if (Importer_.is_null ()) {
1641 Y2->doImport (Y, *Importer_, Tpetra::INSERT);
1644 serialGaussSeidel_->apply(*Y2, X, direction);
1648 Tpetra::deep_copy (Y, *Y2);
1653 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1654 const double numVectors = as<double> (X.getNumVectors ());
1655 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1656 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1657 ApplyFlops_ += 2.0 * NumSweeps_ * numVectors *
1658 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1662 template<
class MatrixType>
1664 Relaxation<MatrixType>::
1665 ApplyInverseSerialGS_CrsMatrix(
const crs_matrix_type& A,
1666 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& B,
1667 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1668 Tpetra::ESweepDirection direction)
const
1670 using Teuchos::null;
1673 using Teuchos::rcpFromRef;
1674 using Teuchos::rcp_const_cast;
1675 typedef scalar_type Scalar;
1676 const char prefix[] =
"Ifpack2::Relaxation::SerialGS: ";
1680 ! A.isFillComplete (), std::runtime_error,
1681 prefix <<
"The matrix is not fill complete.");
1683 NumSweeps_ < 0, std::invalid_argument,
1684 prefix <<
"The number of sweeps must be nonnegative, "
1685 "but you provided numSweeps = " << NumSweeps_ <<
" < 0.");
1687 if (NumSweeps_ == 0) {
1691 RCP<const import_type> importer = A.getGraph ()->getImporter ();
1693 RCP<const map_type> domainMap = A.getDomainMap ();
1694 RCP<const map_type> rangeMap = A.getRangeMap ();
1695 RCP<const map_type> rowMap = A.getGraph ()->getRowMap ();
1696 RCP<const map_type> colMap = A.getGraph ()->getColMap ();
1698 #ifdef HAVE_IFPACK2_DEBUG
1704 ! X.getMap ()->isSameAs (*domainMap), std::runtime_error,
1705 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
1706 "multivector X be in the domain Map of the matrix.");
1708 ! B.getMap ()->isSameAs (*rangeMap), std::runtime_error,
1709 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
1710 "B be in the range Map of the matrix.");
1712 ! Diagonal_->getMap ()->isSameAs (*rowMap), std::runtime_error,
1713 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
1714 "D be in the row Map of the matrix.");
1716 ! rowMap->isSameAs (*rangeMap), std::runtime_error,
1717 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the row Map and the "
1718 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
1720 ! domainMap->isSameAs (*rangeMap), std::runtime_error,
1721 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the domain Map and "
1722 "the range Map of the matrix be the same.");
1734 RCP<multivector_type> X_colMap;
1735 RCP<multivector_type> X_domainMap;
1736 bool copyBackOutput =
false;
1737 if (importer.is_null ()) {
1738 X_colMap = Teuchos::rcpFromRef (X);
1739 X_domainMap = Teuchos::rcpFromRef (X);
1745 if (ZeroStartingSolution_) {
1746 X_colMap->putScalar (ZERO);
1751 updateCachedMultiVector(colMap, X.getNumVectors());
1752 X_colMap = cachedMV_;
1753 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
1755 if (ZeroStartingSolution_) {
1757 X_colMap->putScalar (ZERO);
1767 X_colMap->doImport (X, *importer, Tpetra::INSERT);
1769 copyBackOutput =
true;
1772 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
1773 if (! importer.is_null () && sweep > 0) {
1776 X_colMap->doImport (*X_domainMap, *importer, Tpetra::INSERT);
1779 serialGaussSeidel_->apply(*X_colMap, B, direction);
1782 if (copyBackOutput) {
1784 deep_copy (X , *X_domainMap);
1785 }
catch (std::exception& e) {
1787 true, std::runtime_error, prefix <<
"deep_copy(X, *X_domainMap) "
1788 "threw an exception: " << e.what ());
1803 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1804 const double numVectors = X.getNumVectors ();
1805 const double numGlobalRows = A_->getGlobalNumRows ();
1806 const double numGlobalNonzeros = A_->getGlobalNumEntries ();
1807 ApplyFlops_ += NumSweeps_ * numVectors *
1808 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1811 template<
class MatrixType>
1813 Relaxation<MatrixType>::
1814 ApplyInverseSerialGS_BlockCrsMatrix (
const block_crs_matrix_type& A,
1815 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1816 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
1817 Tpetra::ESweepDirection direction)
1819 using Tpetra::INSERT;
1822 using Teuchos::rcpFromRef;
1831 block_multivector_type yBlock(Y, *(A.getGraph ()->getDomainMap()), A.getBlockSize());
1832 const block_multivector_type xBlock(X, *(A.getColMap ()), A.getBlockSize());
1834 bool performImport =
false;
1835 RCP<block_multivector_type> yBlockCol;
1836 if (Importer_.is_null()) {
1837 yBlockCol = rcpFromRef(yBlock);
1840 if (yBlockColumnPointMap_.is_null() ||
1841 yBlockColumnPointMap_->getNumVectors() != yBlock.getNumVectors() ||
1842 yBlockColumnPointMap_->getBlockSize() != yBlock.getBlockSize()) {
1843 yBlockColumnPointMap_ =
1844 rcp(
new block_multivector_type(*(A.getColMap()), A.getBlockSize(),
1845 static_cast<local_ordinal_type
>(yBlock.getNumVectors())));
1847 yBlockCol = yBlockColumnPointMap_;
1848 if (pointImporter_.is_null()) {
1849 auto srcMap =
rcp(
new map_type(yBlock.getPointMap()));
1850 auto tgtMap =
rcp(
new map_type(yBlockCol->getPointMap()));
1851 pointImporter_ =
rcp(
new import_type(srcMap, tgtMap));
1853 performImport =
true;
1856 multivector_type yBlock_mv;
1857 multivector_type yBlockCol_mv;
1858 RCP<const multivector_type> yBlockColPointDomain;
1859 if (performImport) {
1860 yBlock_mv = yBlock.getMultiVectorView();
1861 yBlockCol_mv = yBlockCol->getMultiVectorView();
1862 yBlockColPointDomain =
1863 yBlockCol_mv.offsetView(A.getDomainMap(), 0);
1866 if (ZeroStartingSolution_) {
1867 yBlockCol->putScalar(STS::zero ());
1869 else if (performImport) {
1870 yBlockCol_mv.doImport(yBlock_mv, *pointImporter_, Tpetra::INSERT);
1873 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
1874 if (performImport && sweep > 0) {
1875 yBlockCol_mv.doImport(yBlock_mv, *pointImporter_, Tpetra::INSERT);
1877 serialGaussSeidel_->applyBlock(*yBlockCol, xBlock, direction);
1878 if (performImport) {
1879 Tpetra::deep_copy(Y, *yBlockColPointDomain);
1884 template<
class MatrixType>
1886 Relaxation<MatrixType>::
1887 ApplyInverseMTGS_CrsMatrix(
1888 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& B,
1889 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1890 Tpetra::ESweepDirection direction)
const
1892 using Teuchos::null;
1895 using Teuchos::rcpFromRef;
1896 using Teuchos::rcp_const_cast;
1899 typedef scalar_type Scalar;
1901 const char prefix[] =
"Ifpack2::Relaxation::(reordered)MTGaussSeidel: ";
1904 auto crsMat = Details::getCrsMatrix(A_);
1906 (crsMat.is_null(), std::logic_error,
"Ifpack2::Relaxation::apply: "
1907 "Multithreaded Gauss-Seidel methods currently only work when the "
1908 "input matrix is a Tpetra::CrsMatrix.");
1912 (! localSmoothingIndices_.is_null (), std::logic_error,
1913 "Ifpack2's implementation of Multithreaded Gauss-Seidel does not "
1914 "implement the case where the user supplies an iteration order. "
1915 "This error used to appear as \"MT GaussSeidel ignores the given "
1917 "I tried to add more explanation, but I didn't implement \"MT "
1918 "GaussSeidel\" [sic]. "
1919 "You'll have to ask the person who did.");
1922 (! crsMat->isFillComplete (), std::runtime_error, prefix <<
"The "
1923 "input CrsMatrix is not fill complete. Please call fillComplete "
1924 "on the matrix, then do setup again, before calling apply(). "
1925 "\"Do setup\" means that if only the matrix's values have changed "
1926 "since last setup, you need only call compute(). If the matrix's "
1927 "structure may also have changed, you must first call initialize(), "
1928 "then call compute(). If you have not set up this preconditioner "
1929 "for this matrix before, you must first call initialize(), then "
1932 (NumSweeps_ < 0, std::logic_error, prefix <<
": NumSweeps_ = "
1933 << NumSweeps_ <<
" < 0. Please report this bug to the Ifpack2 "
1935 if (NumSweeps_ == 0) {
1939 RCP<const import_type> importer = crsMat->getGraph ()->getImporter ();
1941 ! crsMat->getGraph ()->getExporter ().is_null (), std::runtime_error,
1942 "This method's implementation currently requires that the matrix's row, "
1943 "domain, and range Maps be the same. This cannot be the case, because "
1944 "the matrix has a nontrivial Export object.");
1946 RCP<const map_type> domainMap = crsMat->getDomainMap ();
1947 RCP<const map_type> rangeMap = crsMat->getRangeMap ();
1948 RCP<const map_type> rowMap = crsMat->getGraph ()->getRowMap ();
1949 RCP<const map_type> colMap = crsMat->getGraph ()->getColMap ();
1951 #ifdef HAVE_IFPACK2_DEBUG
1957 ! X.getMap ()->isSameAs (*domainMap), std::runtime_error,
1958 "Ifpack2::Relaxation::MTGaussSeidel requires that the input "
1959 "multivector X be in the domain Map of the matrix.");
1961 ! B.getMap ()->isSameAs (*rangeMap), std::runtime_error,
1962 "Ifpack2::Relaxation::MTGaussSeidel requires that the input "
1963 "B be in the range Map of the matrix.");
1965 ! rowMap->isSameAs (*rangeMap), std::runtime_error,
1966 "Ifpack2::Relaxation::MTGaussSeidel requires that the row Map and the "
1967 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
1969 ! domainMap->isSameAs (*rangeMap), std::runtime_error,
1970 "Ifpack2::Relaxation::MTGaussSeidel requires that the domain Map and "
1971 "the range Map of the matrix be the same.");
1977 #endif // HAVE_IFPACK2_DEBUG
1987 RCP<multivector_type> X_colMap;
1988 RCP<multivector_type> X_domainMap;
1989 bool copyBackOutput =
false;
1990 if (importer.is_null ()) {
1991 if (X.isConstantStride ()) {
1992 X_colMap = rcpFromRef (X);
1993 X_domainMap = rcpFromRef (X);
2000 if (ZeroStartingSolution_) {
2001 X_colMap->putScalar (ZERO);
2010 updateCachedMultiVector(colMap,as<size_t>(X.getNumVectors()));
2011 X_colMap = cachedMV_;
2015 X_domainMap = X_colMap;
2016 if (! ZeroStartingSolution_) {
2018 deep_copy (*X_domainMap , X);
2019 }
catch (std::exception& e) {
2020 std::ostringstream os;
2021 os <<
"Ifpack2::Relaxation::MTGaussSeidel: "
2022 "deep_copy(*X_domainMap, X) threw an exception: "
2023 << e.what () <<
".";
2027 copyBackOutput =
true;
2041 updateCachedMultiVector(colMap,as<size_t>(X.getNumVectors()));
2042 X_colMap = cachedMV_;
2044 X_domainMap = X_colMap->offsetViewNonConst (domainMap, 0);
2046 if (ZeroStartingSolution_) {
2048 X_colMap->putScalar (ZERO);
2058 X_colMap->doImport (X, *importer, Tpetra::CombineMode::INSERT);
2060 copyBackOutput =
true;
2066 RCP<const multivector_type> B_in;
2067 if (B.isConstantStride ()) {
2068 B_in = rcpFromRef (B);
2074 RCP<multivector_type> B_in_nonconst =
rcp (
new multivector_type(rowMap, B.getNumVectors()));
2076 deep_copy (*B_in_nonconst, B);
2077 }
catch (std::exception& e) {
2078 std::ostringstream os;
2079 os <<
"Ifpack2::Relaxation::MTGaussSeidel: "
2080 "deep_copy(*B_in_nonconst, B) threw an exception: "
2081 << e.what () <<
".";
2084 B_in = rcp_const_cast<
const multivector_type> (B_in_nonconst);
2098 local_matrix_device_type kcsr = crsMat->getLocalMatrixDevice ();
2100 bool update_y_vector =
true;
2102 bool zero_x_vector =
false;
2104 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
2105 if (! importer.is_null () && sweep > 0) {
2108 X_colMap->doImport (*X_domainMap, *importer, Tpetra::CombineMode::INSERT);
2111 if (direction == Tpetra::Symmetric) {
2112 KokkosSparse::Experimental::symmetric_gauss_seidel_apply
2113 (mtKernelHandle_.getRawPtr(), A_->getLocalNumRows(), A_->getLocalNumCols(),
2114 kcsr.graph.row_map, kcsr.graph.entries, kcsr.values,
2115 X_colMap->getLocalViewDevice(Tpetra::Access::ReadWrite),
2116 B_in->getLocalViewDevice(Tpetra::Access::ReadOnly),
2117 zero_x_vector, update_y_vector, DampingFactor_, 1);
2119 else if (direction == Tpetra::Forward) {
2120 KokkosSparse::Experimental::forward_sweep_gauss_seidel_apply
2121 (mtKernelHandle_.getRawPtr(), A_->getLocalNumRows(), A_->getLocalNumCols(),
2122 kcsr.graph.row_map,kcsr.graph.entries, kcsr.values,
2123 X_colMap->getLocalViewDevice(Tpetra::Access::ReadWrite),
2124 B_in->getLocalViewDevice(Tpetra::Access::ReadOnly),
2125 zero_x_vector, update_y_vector, DampingFactor_, 1);
2127 else if (direction == Tpetra::Backward) {
2128 KokkosSparse::Experimental::backward_sweep_gauss_seidel_apply
2129 (mtKernelHandle_.getRawPtr(), A_->getLocalNumRows(), A_->getLocalNumCols(),
2130 kcsr.graph.row_map,kcsr.graph.entries, kcsr.values,
2131 X_colMap->getLocalViewDevice(Tpetra::Access::ReadWrite),
2132 B_in->getLocalViewDevice(Tpetra::Access::ReadOnly),
2133 zero_x_vector, update_y_vector, DampingFactor_, 1);
2137 true, std::invalid_argument,
2138 prefix <<
"The 'direction' enum does not have any of its valid "
2139 "values: Forward, Backward, or Symmetric.");
2141 update_y_vector =
false;
2144 if (copyBackOutput) {
2146 deep_copy (X , *X_domainMap);
2147 }
catch (std::exception& e) {
2149 true, std::runtime_error, prefix <<
"deep_copy(X, *X_domainMap) "
2150 "threw an exception: " << e.what ());
2154 const double dampingFlops = (DampingFactor_ == STS::one ()) ? 0.0 : 1.0;
2155 const double numVectors = as<double> (X.getNumVectors ());
2156 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
2157 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
2158 double ApplyFlops = NumSweeps_ * numVectors *
2159 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
2160 if (direction == Tpetra::Symmetric)
2162 ApplyFlops_ += ApplyFlops;
2165 template<
class MatrixType>
2168 std::ostringstream os;
2173 os <<
"\"Ifpack2::Relaxation\": {";
2175 os <<
"Initialized: " << (isInitialized () ?
"true" :
"false") <<
", "
2176 <<
"Computed: " << (isComputed () ?
"true" :
"false") <<
", ";
2182 if (PrecType_ == Ifpack2::Details::JACOBI) {
2184 }
else if (PrecType_ == Ifpack2::Details::GS) {
2185 os <<
"Gauss-Seidel";
2186 }
else if (PrecType_ == Ifpack2::Details::SGS) {
2187 os <<
"Symmetric Gauss-Seidel";
2188 }
else if (PrecType_ == Ifpack2::Details::MTGS) {
2189 os <<
"MT Gauss-Seidel";
2190 }
else if (PrecType_ == Ifpack2::Details::MTSGS) {
2191 os <<
"MT Symmetric Gauss-Seidel";
2192 }
else if (PrecType_ == Ifpack2::Details::GS2) {
2193 os <<
"Two-stage Gauss-Seidel";
2194 }
else if (PrecType_ == Ifpack2::Details::SGS2) {
2195 os <<
"Two-stage Symmetric Gauss-Seidel";
2200 if(hasBlockCrsMatrix_)
2203 os <<
", " <<
"sweeps: " << NumSweeps_ <<
", "
2204 <<
"damping factor: " << DampingFactor_ <<
", ";
2206 if (PrecType_ == Ifpack2::Details::MTGS || PrecType_ == Ifpack2::Details::MTSGS) {
2207 os <<
"\"relaxation: mtgs cluster size\": " << clusterSize_ <<
", ";
2208 os <<
"\"relaxation: long row threshold\": " << longRowThreshold_ <<
", ";
2209 os <<
"\"relaxation: symmetric matrix structure\": " << (is_matrix_structurally_symmetric_ ?
"true" :
"false") <<
", ";
2210 os <<
"\"relaxation: relaxation: mtgs coloring algorithm\": ";
2211 switch(mtColoringAlgorithm_)
2213 case KokkosGraph::COLORING_DEFAULT:
2214 os <<
"DEFAULT";
break;
2215 case KokkosGraph::COLORING_SERIAL:
2216 os <<
"SERIAL";
break;
2217 case KokkosGraph::COLORING_VB:
2219 case KokkosGraph::COLORING_VBBIT:
2220 os <<
"VBBIT";
break;
2221 case KokkosGraph::COLORING_VBCS:
2222 os <<
"VBCS";
break;
2223 case KokkosGraph::COLORING_VBD:
2225 case KokkosGraph::COLORING_VBDBIT:
2226 os <<
"VBDBIT";
break;
2227 case KokkosGraph::COLORING_EB:
2235 if (PrecType_ == Ifpack2::Details::GS2 ||
2236 PrecType_ == Ifpack2::Details::SGS2) {
2237 os <<
"outer sweeps: " << NumOuterSweeps_ <<
", "
2238 <<
"inner sweeps: " << NumInnerSweeps_ <<
", "
2239 <<
"inner damping factor: " << InnerDampingFactor_ <<
", ";
2243 os <<
"use l1: " << DoL1Method_ <<
", "
2244 <<
"l1 eta: " << L1Eta_ <<
", ";
2248 os <<
"Matrix: null";
2251 os <<
"Global matrix dimensions: ["
2252 << A_->getGlobalNumRows () <<
", " << A_->getGlobalNumCols () <<
"]"
2253 <<
", Global nnz: " << A_->getGlobalNumEntries();
2261 template<
class MatrixType>
2280 const int myRank = this->getComm ()->getRank ();
2292 out <<
"\"Ifpack2::Relaxation\":" << endl;
2294 out <<
"MatrixType: \"" << TypeNameTraits<MatrixType>::name () <<
"\""
2296 if (this->getObjectLabel () !=
"") {
2297 out <<
"Label: " << this->getObjectLabel () << endl;
2299 out <<
"Initialized: " << (isInitialized () ?
"true" :
"false") << endl
2300 <<
"Computed: " << (isComputed () ?
"true" :
"false") << endl
2301 <<
"Parameters: " << endl;
2304 out <<
"\"relaxation: type\": ";
2305 if (PrecType_ == Ifpack2::Details::JACOBI) {
2307 }
else if (PrecType_ == Ifpack2::Details::GS) {
2308 out <<
"Gauss-Seidel";
2309 }
else if (PrecType_ == Ifpack2::Details::SGS) {
2310 out <<
"Symmetric Gauss-Seidel";
2311 }
else if (PrecType_ == Ifpack2::Details::MTGS) {
2312 out <<
"MT Gauss-Seidel";
2313 }
else if (PrecType_ == Ifpack2::Details::MTSGS) {
2314 out <<
"MT Symmetric Gauss-Seidel";
2315 }
else if (PrecType_ == Ifpack2::Details::GS2) {
2316 out <<
"Two-stage Gauss-Seidel";
2317 }
else if (PrecType_ == Ifpack2::Details::SGS2) {
2318 out <<
"Two-stage Symmetric Gauss-Seidel";
2325 <<
"\"relaxation: sweeps\": " << NumSweeps_ << endl
2326 <<
"\"relaxation: damping factor\": " << DampingFactor_ << endl
2327 <<
"\"relaxation: min diagonal value\": " << MinDiagonalValue_ << endl
2328 <<
"\"relaxation: zero starting solution\": " << ZeroStartingSolution_ << endl
2329 <<
"\"relaxation: backward mode\": " << DoBackwardGS_ << endl
2330 <<
"\"relaxation: use l1\": " << DoL1Method_ << endl
2331 <<
"\"relaxation: l1 eta\": " << L1Eta_ << endl;
2332 if (PrecType_ == Ifpack2::Details::MTGS || PrecType_ == Ifpack2::Details::MTSGS) {
2333 out <<
"\"relaxation: mtgs cluster size\": " << clusterSize_ << endl;
2334 out <<
"\"relaxation: long row threshold\": " << longRowThreshold_ << endl;
2335 out <<
"\"relaxation: symmetric matrix structure\": " << (is_matrix_structurally_symmetric_ ?
"true" :
"false") << endl;
2336 out <<
"\"relaxation: relaxation: mtgs coloring algorithm\": ";
2337 switch(mtColoringAlgorithm_)
2339 case KokkosGraph::COLORING_DEFAULT:
2340 out <<
"DEFAULT";
break;
2341 case KokkosGraph::COLORING_SERIAL:
2342 out <<
"SERIAL";
break;
2343 case KokkosGraph::COLORING_VB:
2345 case KokkosGraph::COLORING_VBBIT:
2346 out <<
"VBBIT";
break;
2347 case KokkosGraph::COLORING_VBCS:
2348 out <<
"VBCS";
break;
2349 case KokkosGraph::COLORING_VBD:
2350 out <<
"VBD";
break;
2351 case KokkosGraph::COLORING_VBDBIT:
2352 out <<
"VBDBIT";
break;
2353 case KokkosGraph::COLORING_EB:
2360 if (PrecType_ == Ifpack2::Details::GS2 || PrecType_ == Ifpack2::Details::SGS2) {
2361 out <<
"\"relaxation: inner damping factor\": " << InnerDampingFactor_ << endl;
2362 out <<
"\"relaxation: outer sweeps\" : " << NumOuterSweeps_ << endl;
2363 out <<
"\"relaxation: inner sweeps\" : " << NumInnerSweeps_ << endl;
2366 out <<
"Computed quantities:" << endl;
2369 out <<
"Global number of rows: " << A_->getGlobalNumRows () << endl
2370 <<
"Global number of columns: " << A_->getGlobalNumCols () << endl;
2372 if (checkDiagEntries_ && isComputed ()) {
2373 out <<
"Properties of input diagonal entries:" << endl;
2376 out <<
"Magnitude of minimum-magnitude diagonal entry: "
2377 << globalMinMagDiagEntryMag_ << endl
2378 <<
"Magnitude of maximum-magnitude diagonal entry: "
2379 << globalMaxMagDiagEntryMag_ << endl
2380 <<
"Number of diagonal entries with small magnitude: "
2381 << globalNumSmallDiagEntries_ << endl
2382 <<
"Number of zero diagonal entries: "
2383 << globalNumZeroDiagEntries_ << endl
2384 <<
"Number of diagonal entries with negative real part: "
2385 << globalNumNegDiagEntries_ << endl
2386 <<
"Abs 2-norm diff between computed and actual inverse "
2387 <<
"diagonal: " << globalDiagNormDiff_ << endl;
2390 if (isComputed ()) {
2391 out <<
"Saved diagonal offsets: "
2392 << (savedDiagOffsets_ ?
"true" :
"false") << endl;
2394 out <<
"Call counts and total times (in seconds): " << endl;
2397 out <<
"initialize: " << endl;
2400 out <<
"Call count: " << NumInitialize_ << endl;
2401 out <<
"Total time: " << InitializeTime_ << endl;
2403 out <<
"compute: " << endl;
2406 out <<
"Call count: " << NumCompute_ << endl;
2407 out <<
"Total time: " << ComputeTime_ << endl;
2409 out <<
"apply: " << endl;
2412 out <<
"Call count: " << NumApply_ << endl;
2413 out <<
"Total time: " << ApplyTime_ << endl;
2422 #define IFPACK2_RELAXATION_INSTANT(S,LO,GO,N) \
2423 template class Ifpack2::Relaxation< Tpetra::RowMatrix<S, LO, GO, N> >;
2425 #endif // IFPACK2_RELAXATION_DEF_HPP
bool hasTransposeApply() const
Whether apply() and applyMat() let you apply the transpose or conjugate transpose.
Definition: Ifpack2_Relaxation_def.hpp:494
double getComputeFlops() const
Total number of floating-point operations over all calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:536
double getApplyFlops() const
Total number of floating-point operations over all calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:542
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object's attributes to the given output stream.
Definition: Ifpack2_Relaxation_def.hpp:2264
bool is_null(const boost::shared_ptr< T > &p)
basic_OSTab< char > OSTab
static magnitudeType eps()
Relaxation(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition: Ifpack2_Relaxation_def.hpp:183
T & get(const std::string &name, T def_value)
void compute()
Compute the preconditioner ("numeric setup");.
Definition: Ifpack2_Relaxation_def.hpp:994
virtual void printDoc(std::string const &docString, std::ostream &out) const =0
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition: Ifpack2_Relaxation_def.hpp:549
virtual const std::string getXMLTypeName() const =0
static std::ostream & printLines(std::ostream &os, const std::string &linePrefix, const std::string &lines)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix and vectors are distributed.
Definition: Ifpack2_Relaxation_def.hpp:451
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_Relaxation_def.hpp:162
int getNumApply() const
Total number of calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:512
bool remove(std::string const &name, bool throwIfNotExists=true)
double getComputeTime() const
Total time in seconds spent in all calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:524
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:232
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getDomainMap() const
Returns the Tpetra::Map object associated with the domain of this operator.
Definition: Ifpack2_Relaxation_def.hpp:471
void setParameters(const Teuchos::ParameterList ¶ms)
Set the relaxation / preconditioner parameters.
Definition: Ifpack2_Relaxation_def.hpp:441
File for utility functions.
std::string description() const
A simple one-line description of this object.
Definition: Ifpack2_Relaxation_def.hpp:2166
int getNumInitialize() const
Total number of calls to initialize().
Definition: Ifpack2_Relaxation_def.hpp:500
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
virtual ValidStringsList validStringValues() const =0
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRangeMap() const
Returns the Tpetra::Map object associated with the range of this operator.
Definition: Ifpack2_Relaxation_def.hpp:484
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:229
double getInitializeTime() const
Total time in seconds spent in all calls to initialize().
Definition: Ifpack2_Relaxation_def.hpp:518
any & getAny(bool activeQry=true)
Compute scaled damped residual for Chebyshev.
Definition: Ifpack2_Details_InverseDiagonalKernel_decl.hpp:45
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
Apply the input matrix to X, returning the result in Y.
Definition: Ifpack2_Relaxation_def.hpp:675
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix to be preconditioned.
Definition: Ifpack2_Relaxation_def.hpp:462
TypeTo as(const TypeFrom &t)
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:226
bool isType(const std::string &name) const
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:223
std::string typeName() const
const std::type_info & type() const
int getNumCompute() const
Total number of calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:506
Relaxation preconditioners for Tpetra::RowMatrix and Tpetra::CrsMatrix sparse matrices.
Definition: Ifpack2_Relaxation_decl.hpp:206
double getApplyTime() const
Total time in seconds spent in all calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:530
void getValidParameters(Teuchos::ParameterList ¶ms)
Fills a list which contains all the parameters possibly used by Ifpack2.
Definition: Ifpack2_Parameters.cpp:18
void initialize()
Initialize the preconditioner ("symbolic setup").
Definition: Ifpack2_Relaxation_def.hpp:696
Tpetra::RowMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > row_matrix_type
Tpetra::RowMatrix specialization used by this class.
Definition: Ifpack2_Relaxation_decl.hpp:242
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_Relaxation_def.hpp:562
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a list of all the parameters that this class accepts.
Definition: Ifpack2_Relaxation_def.hpp:195
Teuchos::ScalarTraits< scalar_type >::magnitudeType magnitude_type
The type of the magnitude (absolute value) of a matrix entry.
Definition: Ifpack2_Relaxation_decl.hpp:238
virtual void validate(ParameterEntry const &entry, std::string const ¶mName, std::string const &sublistName) const =0