44 #ifndef IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP 45 #define IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP 56 #include "Ifpack2_Details_ChebyshevKernel.hpp" 57 #include "Kokkos_ArithTraits.hpp" 58 #include "Teuchos_FancyOStream.hpp" 59 #include "Teuchos_oblackholestream.hpp" 60 #include "Tpetra_Details_residual.hpp" 70 const char computeBeforeApplyReminder[] =
71 "This means one of the following:\n" 72 " - you have not yet called compute() on this instance, or \n" 73 " - you didn't call compute() after calling setParameters().\n\n" 74 "After creating an Ifpack2::Chebyshev instance,\n" 75 "you must _always_ call compute() at least once before calling apply().\n" 76 "After calling compute() once, you do not need to call it again,\n" 77 "unless the matrix has changed or you have changed parameters\n" 78 "(by calling setParameters()).";
84 template<
class XV,
class SizeType =
typename XV::
size_type>
85 struct V_ReciprocalThresholdSelfFunctor
87 typedef typename XV::execution_space execution_space;
88 typedef typename XV::non_const_value_type value_type;
89 typedef SizeType size_type;
90 typedef Kokkos::Details::ArithTraits<value_type> KAT;
91 typedef typename KAT::mag_type mag_type;
94 const value_type minVal_;
95 const mag_type minValMag_;
97 V_ReciprocalThresholdSelfFunctor (
const XV& X,
98 const value_type& min_val) :
101 minValMag_ (KAT::abs (min_val))
104 KOKKOS_INLINE_FUNCTION
105 void operator() (
const size_type& i)
const 107 const mag_type X_i_abs = KAT::abs (X_[i]);
109 if (X_i_abs < minValMag_) {
113 X_[i] = KAT::one () / X_[i];
118 template<
class XV,
class SizeType =
typename XV::
size_type>
119 struct LocalReciprocalThreshold {
121 compute (
const XV& X,
122 const typename XV::non_const_value_type& minVal)
124 typedef typename XV::execution_space execution_space;
125 Kokkos::RangePolicy<execution_space, SizeType> policy (0, X.extent (0));
126 V_ReciprocalThresholdSelfFunctor<XV, SizeType> op (X, minVal);
127 Kokkos::parallel_for (policy, op);
131 template <
class TpetraVectorType,
132 const bool classic = TpetraVectorType::node_type::classic>
133 struct GlobalReciprocalThreshold {};
135 template <
class TpetraVectorType>
136 struct GlobalReciprocalThreshold<TpetraVectorType, true> {
138 compute (TpetraVectorType& V,
139 const typename TpetraVectorType::scalar_type& min_val)
141 typedef typename TpetraVectorType::scalar_type scalar_type;
142 typedef typename TpetraVectorType::mag_type mag_type;
143 typedef Kokkos::Details::ArithTraits<scalar_type> STS;
145 const scalar_type ONE = STS::one ();
146 const mag_type min_val_abs = STS::abs (min_val);
148 Teuchos::ArrayRCP<scalar_type> V_0 = V.getDataNonConst (0);
149 const size_t lclNumRows = V.getLocalLength ();
151 for (
size_t i = 0; i < lclNumRows; ++i) {
152 const scalar_type V_0i = V_0[i];
153 if (STS::abs (V_0i) < min_val_abs) {
162 template <
class TpetraVectorType>
163 struct GlobalReciprocalThreshold<TpetraVectorType, false> {
165 compute (TpetraVectorType& X,
166 const typename TpetraVectorType::scalar_type& minVal)
168 typedef typename TpetraVectorType::impl_scalar_type value_type;
169 typedef typename TpetraVectorType::device_type::memory_space memory_space;
171 X.template sync<memory_space> ();
172 X.template modify<memory_space> ();
174 const value_type minValS =
static_cast<value_type
> (minVal);
175 auto X_0 = Kokkos::subview (X.template getLocalView<memory_space> (),
177 LocalReciprocalThreshold<decltype (X_0) >::compute (X_0, minValS);
182 template <
typename S,
typename L,
typename G,
typename N>
184 reciprocal_threshold (Tpetra::Vector<S,L,G,N>& V,
const S& minVal)
186 GlobalReciprocalThreshold<Tpetra::Vector<S,L,G,N> >::compute (V, minVal);
194 template<
class OneDViewType,
195 class LocalOrdinal =
typename OneDViewType::size_type>
196 class PositivizeVector {
197 static_assert (Kokkos::Impl::is_view<OneDViewType>::value,
198 "OneDViewType must be a 1-D Kokkos::View.");
199 static_assert (static_cast<int> (OneDViewType::rank) == 1,
200 "This functor only works with a 1-D View.");
201 static_assert (std::is_integral<LocalOrdinal>::value,
202 "The second template parameter, LocalOrdinal, " 203 "must be an integer type.");
205 PositivizeVector (
const OneDViewType& x) : x_ (x) {}
207 KOKKOS_INLINE_FUNCTION
void 208 operator () (
const LocalOrdinal& i)
const 210 typedef typename OneDViewType::non_const_value_type IST;
211 typedef Kokkos::Details::ArithTraits<IST> STS;
212 typedef Kokkos::Details::ArithTraits<typename STS::mag_type> STM;
214 if (STS::real (x_(i)) < STM::zero ()) {
225 template<
class ScalarType,
class MV>
226 void Chebyshev<ScalarType, MV>::checkInputMatrix ()
const 228 TEUCHOS_TEST_FOR_EXCEPTION(
229 ! A_.is_null () && A_->getGlobalNumRows () != A_->getGlobalNumCols (),
230 std::invalid_argument,
231 "Ifpack2::Chebyshev: The input matrix A must be square. " 232 "A has " << A_->getGlobalNumRows () <<
" rows and " 233 << A_->getGlobalNumCols () <<
" columns.");
237 if (debug_ && ! A_.is_null ()) {
238 Teuchos::RCP<const map_type> domainMap = A_->getDomainMap ();
239 Teuchos::RCP<const map_type> rangeMap = A_->getRangeMap ();
244 TEUCHOS_TEST_FOR_EXCEPTION(
245 ! domainMap->isSameAs (*rangeMap), std::invalid_argument,
246 "Ifpack2::Chebyshev: The domain Map and range Map of the matrix must be " 247 "the same (in the sense of isSameAs())." << std::endl <<
"We only check " 248 "for this in debug mode.");
253 template<
class ScalarType,
class MV>
255 Chebyshev<ScalarType, MV>::
256 checkConstructorInput ()
const 261 if (STS::isComplex) {
262 TEUCHOS_TEST_FOR_EXCEPTION
263 (
true, std::logic_error,
"Ifpack2::Chebyshev: This class' implementation " 264 "of Chebyshev iteration only works for real-valued, symmetric positive " 265 "definite matrices. However, you instantiated this class for ScalarType" 266 " = " << Teuchos::TypeNameTraits<ScalarType>::name () <<
", which is a " 267 "complex-valued type. While this may be algorithmically correct if all " 268 "of the complex numbers in the matrix have zero imaginary part, we " 269 "forbid using complex ScalarType altogether in order to remind you of " 270 "the limitations of our implementation (and of the algorithm itself).");
277 template<
class ScalarType,
class MV>
281 savedDiagOffsets_ (false),
282 computedLambdaMax_ (
STS::nan ()),
283 computedLambdaMin_ (
STS::nan ()),
284 lambdaMaxForApply_ (
STS::nan ()),
285 lambdaMinForApply_ (
STS::nan ()),
286 eigRatioForApply_ (
STS::nan ()),
287 userLambdaMax_ (
STS::nan ()),
288 userLambdaMin_ (
STS::nan ()),
290 minDiagVal_ (
STS::eps ()),
293 zeroStartingSolution_ (true),
294 assumeMatrixUnchanged_ (false),
295 textbookAlgorithm_ (false),
296 computeMaxResNorm_ (false),
299 checkConstructorInput ();
302 template<
class ScalarType,
class MV>
305 Teuchos::ParameterList& params) :
307 savedDiagOffsets_ (false),
308 computedLambdaMax_ (
STS::nan ()),
309 computedLambdaMin_ (
STS::nan ()),
310 lambdaMaxForApply_ (
STS::nan ()),
311 boostFactor_ (static_cast<
MT> (1.1)),
312 lambdaMinForApply_ (
STS::nan ()),
313 eigRatioForApply_ (
STS::nan ()),
314 userLambdaMax_ (
STS::nan ()),
315 userLambdaMin_ (
STS::nan ()),
317 minDiagVal_ (
STS::eps ()),
320 zeroStartingSolution_ (true),
321 assumeMatrixUnchanged_ (false),
322 textbookAlgorithm_ (false),
323 computeMaxResNorm_ (false),
326 checkConstructorInput ();
327 setParameters (params);
330 template<
class ScalarType,
class MV>
337 using Teuchos::rcp_const_cast;
349 const ST defaultLambdaMax = STS::nan ();
350 const ST defaultLambdaMin = STS::nan ();
357 const ST defaultEigRatio = Teuchos::as<ST> (30);
358 const MT defaultBoostFactor =
static_cast<MT> (1.1);
359 const ST defaultMinDiagVal = STS::eps ();
360 const int defaultNumIters = 1;
361 const int defaultEigMaxIters = 10;
362 const bool defaultZeroStartingSolution =
true;
363 const bool defaultAssumeMatrixUnchanged =
false;
364 const bool defaultTextbookAlgorithm =
false;
365 const bool defaultComputeMaxResNorm =
false;
366 const bool defaultDebug =
false;
372 RCP<const V> userInvDiagCopy;
373 ST lambdaMax = defaultLambdaMax;
374 ST lambdaMin = defaultLambdaMin;
375 ST eigRatio = defaultEigRatio;
376 MT boostFactor = defaultBoostFactor;
377 ST minDiagVal = defaultMinDiagVal;
378 int numIters = defaultNumIters;
379 int eigMaxIters = defaultEigMaxIters;
380 bool zeroStartingSolution = defaultZeroStartingSolution;
381 bool assumeMatrixUnchanged = defaultAssumeMatrixUnchanged;
382 bool textbookAlgorithm = defaultTextbookAlgorithm;
383 bool computeMaxResNorm = defaultComputeMaxResNorm;
384 bool debug = defaultDebug;
391 if (plist.isType<
bool> (
"debug")) {
392 debug = plist.get<
bool> (
"debug");
394 else if (plist.isType<
int> (
"debug")) {
395 const int debugInt = plist.get<
bool> (
"debug");
396 debug = debugInt != 0;
409 const char opInvDiagLabel[] =
"chebyshev: operator inv diagonal";
410 if (plist.isParameter (opInvDiagLabel)) {
412 RCP<const V> userInvDiag;
414 if (plist.isType<
const V*> (opInvDiagLabel)) {
415 const V* rawUserInvDiag =
416 plist.get<
const V*> (opInvDiagLabel);
418 userInvDiag = rcp (rawUserInvDiag,
false);
420 else if (plist.isType<
const V*> (opInvDiagLabel)) {
421 V* rawUserInvDiag = plist.get<
V*> (opInvDiagLabel);
423 userInvDiag = rcp (const_cast<const V*> (rawUserInvDiag),
false);
425 else if (plist.isType<RCP<const V>> (opInvDiagLabel)) {
426 userInvDiag = plist.get<RCP<const V> > (opInvDiagLabel);
428 else if (plist.isType<RCP<V>> (opInvDiagLabel)) {
429 RCP<V> userInvDiagNonConst =
430 plist.get<RCP<V> > (opInvDiagLabel);
431 userInvDiag = rcp_const_cast<
const V> (userInvDiagNonConst);
433 else if (plist.isType<
const V> (opInvDiagLabel)) {
434 const V& userInvDiagRef = plist.get<
const V> (opInvDiagLabel);
435 userInvDiagCopy = rcp (
new V (userInvDiagRef, Teuchos::Copy));
436 userInvDiag = userInvDiagCopy;
438 else if (plist.isType<
V> (opInvDiagLabel)) {
439 V& userInvDiagNonConstRef = plist.get<
V> (opInvDiagLabel);
440 const V& userInvDiagRef =
const_cast<const V&
> (userInvDiagNonConstRef);
441 userInvDiagCopy = rcp (
new V (userInvDiagRef, Teuchos::Copy));
442 userInvDiag = userInvDiagCopy;
452 if (! userInvDiag.is_null () && userInvDiagCopy.is_null ()) {
453 userInvDiagCopy = rcp (
new V (*userInvDiag, Teuchos::Copy));
465 if (plist.isParameter (
"chebyshev: max eigenvalue")) {
466 if (plist.isType<
double>(
"chebyshev: max eigenvalue"))
467 lambdaMax = plist.get<
double> (
"chebyshev: max eigenvalue");
469 lambdaMax = plist.get<
ST> (
"chebyshev: max eigenvalue");
470 TEUCHOS_TEST_FOR_EXCEPTION(
471 STS::isnaninf (lambdaMax), std::invalid_argument,
472 "Ifpack2::Chebyshev::setParameters: \"chebyshev: max eigenvalue\" " 473 "parameter is NaN or Inf. This parameter is optional, but if you " 474 "choose to supply it, it must have a finite value.");
476 if (plist.isParameter (
"chebyshev: min eigenvalue")) {
477 if (plist.isType<
double>(
"chebyshev: min eigenvalue"))
478 lambdaMin = plist.get<
double> (
"chebyshev: min eigenvalue");
480 lambdaMin = plist.get<
ST> (
"chebyshev: min eigenvalue");
481 TEUCHOS_TEST_FOR_EXCEPTION(
482 STS::isnaninf (lambdaMin), std::invalid_argument,
483 "Ifpack2::Chebyshev::setParameters: \"chebyshev: min eigenvalue\" " 484 "parameter is NaN or Inf. This parameter is optional, but if you " 485 "choose to supply it, it must have a finite value.");
489 if (plist.isParameter (
"smoother: Chebyshev alpha")) {
490 if (plist.isType<
double>(
"smoother: Chebyshev alpha"))
491 eigRatio = plist.get<
double> (
"smoother: Chebyshev alpha");
493 eigRatio = plist.get<
ST> (
"smoother: Chebyshev alpha");
496 eigRatio = plist.get (
"chebyshev: ratio eigenvalue", eigRatio);
497 TEUCHOS_TEST_FOR_EXCEPTION(
498 STS::isnaninf (eigRatio), std::invalid_argument,
499 "Ifpack2::Chebyshev::setParameters: \"chebyshev: ratio eigenvalue\" " 500 "parameter (also called \"smoother: Chebyshev alpha\") is NaN or Inf. " 501 "This parameter is optional, but if you choose to supply it, it must have " 508 TEUCHOS_TEST_FOR_EXCEPTION(
509 STS::real (eigRatio) < STS::real (STS::one ()),
510 std::invalid_argument,
511 "Ifpack2::Chebyshev::setParameters: \"chebyshev: ratio eigenvalue\"" 512 "parameter (also called \"smoother: Chebyshev alpha\") must be >= 1, " 513 "but you supplied the value " << eigRatio <<
".");
518 const char paramName[] =
"chebyshev: boost factor";
520 if (plist.isParameter (paramName)) {
521 if (plist.isType<
MT> (paramName)) {
522 boostFactor = plist.get<
MT> (paramName);
524 else if (! std::is_same<double, MT>::value &&
525 plist.isType<
double> (paramName)) {
526 const double dblBF = plist.get<
double> (paramName);
527 boostFactor =
static_cast<MT> (dblBF);
530 TEUCHOS_TEST_FOR_EXCEPTION
531 (
true, std::invalid_argument,
532 "Ifpack2::Chebyshev::setParameters: \"chebyshev: boost factor\"" 533 "parameter must have type magnitude_type (MT) or double.");
543 plist.set (paramName, defaultBoostFactor);
545 TEUCHOS_TEST_FOR_EXCEPTION
546 (boostFactor < Teuchos::ScalarTraits<MT>::one (), std::invalid_argument,
547 "Ifpack2::Chebyshev::setParameters: \"" << paramName <<
"\" parameter " 548 "must be >= 1, but you supplied the value " << boostFactor <<
".");
552 minDiagVal = plist.get (
"chebyshev: min diagonal value", minDiagVal);
553 TEUCHOS_TEST_FOR_EXCEPTION(
554 STS::isnaninf (minDiagVal), std::invalid_argument,
555 "Ifpack2::Chebyshev::setParameters: \"chebyshev: min diagonal value\" " 556 "parameter is NaN or Inf. This parameter is optional, but if you choose " 557 "to supply it, it must have a finite value.");
560 if (plist.isParameter (
"smoother: sweeps")) {
561 numIters = plist.get<
int> (
"smoother: sweeps");
563 if (plist.isParameter (
"relaxation: sweeps")) {
564 numIters = plist.get<
int> (
"relaxation: sweeps");
566 numIters = plist.get (
"chebyshev: degree", numIters);
567 TEUCHOS_TEST_FOR_EXCEPTION(
568 numIters < 0, std::invalid_argument,
569 "Ifpack2::Chebyshev::setParameters: \"chebyshev: degree\" parameter (also " 570 "called \"smoother: sweeps\" or \"relaxation: sweeps\") must be a " 571 "nonnegative integer. You gave a value of " << numIters <<
".");
574 if (plist.isParameter (
"eigen-analysis: iterations")) {
575 eigMaxIters = plist.get<
int> (
"eigen-analysis: iterations");
577 eigMaxIters = plist.get (
"chebyshev: eigenvalue max iterations", eigMaxIters);
578 TEUCHOS_TEST_FOR_EXCEPTION(
579 eigMaxIters < 0, std::invalid_argument,
580 "Ifpack2::Chebyshev::setParameters: \"chebyshev: eigenvalue max iterations" 581 "\" parameter (also called \"eigen-analysis: iterations\") must be a " 582 "nonnegative integer. You gave a value of " << eigMaxIters <<
".");
584 zeroStartingSolution = plist.get (
"chebyshev: zero starting solution",
585 zeroStartingSolution);
586 assumeMatrixUnchanged = plist.get (
"chebyshev: assume matrix does not change",
587 assumeMatrixUnchanged);
591 if (plist.isParameter (
"chebyshev: textbook algorithm")) {
592 textbookAlgorithm = plist.get<
bool> (
"chebyshev: textbook algorithm");
594 if (plist.isParameter (
"chebyshev: compute max residual norm")) {
595 computeMaxResNorm = plist.get<
bool> (
"chebyshev: compute max residual norm");
601 TEUCHOS_TEST_FOR_EXCEPTION
602 (plist.isType<
bool> (
"chebyshev: use block mode") &&
603 ! plist.get<
bool> (
"chebyshev: use block mode"),
604 std::invalid_argument,
605 "Ifpack2::Chebyshev requires that if you set \"chebyshev: use " 606 "block mode\" at all, you must set it to false. " 607 "Ifpack2::Chebyshev does not implement Ifpack's block mode.");
608 TEUCHOS_TEST_FOR_EXCEPTION
609 (plist.isType<
bool> (
"chebyshev: solve normal equations") &&
610 ! plist.get<
bool> (
"chebyshev: solve normal equations"),
611 std::invalid_argument,
612 "Ifpack2::Chebyshev does not and will never implement the Ifpack " 613 "parameter \"chebyshev: solve normal equations\". If you want to " 614 "solve the normal equations, construct a Tpetra::Operator that " 615 "implements A^* A, and use Chebyshev to solve A^* A x = A^* b.");
623 std::string eigenAnalysisType (
"power-method");
624 if (plist.isParameter (
"eigen-analysis: type")) {
625 eigenAnalysisType = plist.get<std::string> (
"eigen-analysis: type");
626 TEUCHOS_TEST_FOR_EXCEPTION(
627 eigenAnalysisType !=
"power-method" &&
628 eigenAnalysisType !=
"power method",
629 std::invalid_argument,
630 "Ifpack2::Chebyshev: This class supports the ML parameter \"eigen-" 631 "analysis: type\" for backwards compatibility. However, Ifpack2 " 632 "currently only supports the \"power-method\" option for this " 633 "parameter. This imitates Ifpack, which only implements the power " 634 "method for eigenanalysis.");
638 userInvDiag_ = userInvDiagCopy;
639 userLambdaMax_ = lambdaMax;
640 userLambdaMin_ = lambdaMin;
641 userEigRatio_ = eigRatio;
642 boostFactor_ =
static_cast<MT> (boostFactor);
643 minDiagVal_ = minDiagVal;
644 numIters_ = numIters;
645 eigMaxIters_ = eigMaxIters;
646 zeroStartingSolution_ = zeroStartingSolution;
647 assumeMatrixUnchanged_ = assumeMatrixUnchanged;
648 textbookAlgorithm_ = textbookAlgorithm;
649 computeMaxResNorm_ = computeMaxResNorm;
655 if (A_.is_null () || A_->getComm ().is_null ()) {
661 myRank = A_->getComm ()->getRank ();
665 out_ = Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr));
668 using Teuchos::oblackholestream;
669 RCP<oblackholestream> blackHole (
new oblackholestream ());
670 out_ = Teuchos::getFancyOStream (blackHole);
675 out_ = Teuchos::null;
680 template<
class ScalarType,
class MV>
686 diagOffsets_ = offsets_type ();
687 savedDiagOffsets_ =
false;
689 computedLambdaMax_ = STS::nan ();
690 computedLambdaMin_ = STS::nan ();
694 template<
class ScalarType,
class MV>
697 setMatrix (
const Teuchos::RCP<const row_matrix_type>& A)
699 if (A.getRawPtr () != A_.getRawPtr ()) {
700 if (! assumeMatrixUnchanged_) {
712 if (A.is_null () || A->getComm ().is_null ()) {
718 myRank = A->getComm ()->getRank ();
722 out_ = Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr));
725 Teuchos::RCP<Teuchos::oblackholestream> blackHole (
new Teuchos::oblackholestream ());
726 out_ = Teuchos::getFancyOStream (blackHole);
731 out_ = Teuchos::null;
736 template<
class ScalarType,
class MV>
745 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
746 typename MV::local_ordinal_type,
747 typename MV::global_ordinal_type,
748 typename MV::node_type> crs_matrix_type;
750 TEUCHOS_TEST_FOR_EXCEPTION(
751 A_.is_null (), std::runtime_error,
"Ifpack2::Chebyshev::compute: The input " 752 "matrix A is null. Please call setMatrix() with a nonnull input matrix " 753 "before calling this method.");
768 if (userInvDiag_.is_null ()) {
769 Teuchos::RCP<const crs_matrix_type> A_crsMat =
770 Teuchos::rcp_dynamic_cast<
const crs_matrix_type> (A_);
773 if (! A_crsMat.is_null () && A_crsMat->isStaticGraph ()) {
775 const size_t lclNumRows = A_crsMat->getNodeNumRows ();
776 if (diagOffsets_.extent (0) < lclNumRows) {
777 diagOffsets_ = offsets_type ();
778 diagOffsets_ = offsets_type (
"offsets", lclNumRows);
780 A_crsMat->getCrsGraph ()->getLocalDiagOffsets (diagOffsets_);
781 savedDiagOffsets_ =
true;
782 D_ = makeInverseDiagonal (*A_,
true);
785 D_ = makeInverseDiagonal (*A_);
788 else if (! assumeMatrixUnchanged_) {
789 if (! A_crsMat.is_null () && A_crsMat->isStaticGraph ()) {
792 if (! savedDiagOffsets_) {
793 const size_t lclNumRows = A_crsMat->getNodeNumRows ();
794 if (diagOffsets_.extent (0) < lclNumRows) {
795 diagOffsets_ = offsets_type ();
796 diagOffsets_ = offsets_type (
"offsets", lclNumRows);
798 A_crsMat->getCrsGraph ()->getLocalDiagOffsets (diagOffsets_);
799 savedDiagOffsets_ =
true;
802 D_ = makeInverseDiagonal (*A_,
true);
805 D_ = makeInverseDiagonal (*A_);
810 D_ = makeRangeMapVectorConst (userInvDiag_);
814 const bool computedEigenvalueEstimates =
815 STS::isnaninf (computedLambdaMax_) || STS::isnaninf (computedLambdaMin_);
824 if (! assumeMatrixUnchanged_ ||
825 (! computedEigenvalueEstimates && STS::isnaninf (userLambdaMax_))) {
826 const ST computedLambdaMax = powerMethod (*A_, *D_, eigMaxIters_);
827 TEUCHOS_TEST_FOR_EXCEPTION(
828 STS::isnaninf (computedLambdaMax),
830 "Ifpack2::Chebyshev::compute: Estimation of the max eigenvalue " 831 "of D^{-1} A failed, by producing Inf or NaN. This probably means that " 832 "the matrix contains Inf or NaN values, or that it is badly scaled.");
833 TEUCHOS_TEST_FOR_EXCEPTION(
834 STS::isnaninf (userEigRatio_),
836 "Ifpack2::Chebyshev::compute: userEigRatio_ is Inf or NaN." 837 << endl <<
"This should be impossible." << endl <<
838 "Please report this bug to the Ifpack2 developers.");
844 const ST computedLambdaMin = computedLambdaMax / userEigRatio_;
847 computedLambdaMax_ = computedLambdaMax;
848 computedLambdaMin_ = computedLambdaMin;
850 TEUCHOS_TEST_FOR_EXCEPTION(
851 STS::isnaninf (userLambdaMax_) && STS::isnaninf (computedLambdaMax_),
853 "Ifpack2::Chebyshev::compute: " << endl <<
854 "Both userLambdaMax_ and computedLambdaMax_ are Inf or NaN." 855 << endl <<
"This should be impossible." << endl <<
856 "Please report this bug to the Ifpack2 developers.");
864 lambdaMaxForApply_ = STS::isnaninf (userLambdaMax_) ? computedLambdaMax_ : userLambdaMax_;
877 lambdaMinForApply_ = lambdaMaxForApply_ / userEigRatio_;
878 eigRatioForApply_ = userEigRatio_;
880 if (! textbookAlgorithm_) {
883 const ST one = Teuchos::as<ST> (1);
886 if (STS::magnitude (lambdaMaxForApply_ - one) < Teuchos::as<MT> (1.0e-6)) {
887 lambdaMinForApply_ = one;
888 lambdaMaxForApply_ = lambdaMinForApply_;
889 eigRatioForApply_ = one;
895 template<
class ScalarType,
class MV>
899 return lambdaMaxForApply_;
903 template<
class ScalarType,
class MV>
907 const char prefix[] =
"Ifpack2::Chebyshev::apply: ";
910 *out_ <<
"apply: " << std::endl;
912 TEUCHOS_TEST_FOR_EXCEPTION
913 (A_.is_null (), std::runtime_error, prefix <<
"The input matrix A is null. " 914 " Please call setMatrix() with a nonnull input matrix, and then call " 915 "compute(), before calling this method.");
916 TEUCHOS_TEST_FOR_EXCEPTION
917 (STS::isnaninf (lambdaMaxForApply_), std::runtime_error,
918 prefix <<
"There is no estimate for the max eigenvalue." 919 << std::endl << computeBeforeApplyReminder);
920 TEUCHOS_TEST_FOR_EXCEPTION
921 (STS::isnaninf (lambdaMinForApply_), std::runtime_error,
922 prefix <<
"There is no estimate for the min eigenvalue." 923 << std::endl << computeBeforeApplyReminder);
924 TEUCHOS_TEST_FOR_EXCEPTION
925 (STS::isnaninf (eigRatioForApply_), std::runtime_error,
926 prefix <<
"There is no estimate for the ratio of the max " 927 "eigenvalue to the min eigenvalue." 928 << std::endl << computeBeforeApplyReminder);
929 TEUCHOS_TEST_FOR_EXCEPTION
930 (D_.is_null (), std::runtime_error, prefix <<
"The vector of inverse " 931 "diagonal entries of the matrix has not yet been computed." 932 << std::endl << computeBeforeApplyReminder);
934 if (textbookAlgorithm_) {
935 textbookApplyImpl (*A_, B, X, numIters_, lambdaMaxForApply_,
936 lambdaMinForApply_, eigRatioForApply_, *D_);
939 ifpackApplyImpl (*A_, B, X, numIters_, lambdaMaxForApply_,
940 lambdaMinForApply_, eigRatioForApply_, *D_);
943 if (computeMaxResNorm_ && B.getNumVectors () > 0) {
944 MV R (B.getMap (), B.getNumVectors ());
945 computeResidual (R, B, *A_, X);
946 Teuchos::Array<MT> norms (B.getNumVectors ());
948 return *std::max_element (norms.begin (), norms.end ());
951 return Teuchos::ScalarTraits<MT>::zero ();
955 template<
class ScalarType,
class MV>
960 using Teuchos::rcpFromRef;
961 this->describe (* (Teuchos::getFancyOStream (rcpFromRef (out))),
962 Teuchos::VERB_MEDIUM);
965 template<
class ScalarType,
class MV>
969 const ScalarType& alpha,
974 solve (W, alpha, D_inv, B);
975 Tpetra::deep_copy (X, W);
978 template<
class ScalarType,
class MV>
982 const Teuchos::ETransp mode)
984 Tpetra::Details::residual(A,X,B,R);
987 template <
class ScalarType,
class MV>
989 Chebyshev<ScalarType, MV>::
990 solve (MV& Z,
const V& D_inv,
const MV& R) {
991 Z.elementWiseMultiply (STS::one(), D_inv, R, STS::zero());
994 template<
class ScalarType,
class MV>
996 Chebyshev<ScalarType, MV>::
997 solve (MV& Z,
const ST alpha,
const V& D_inv,
const MV& R) {
998 Z.elementWiseMultiply (alpha, D_inv, R, STS::zero());
1001 template<
class ScalarType,
class MV>
1002 Teuchos::RCP<const typename Chebyshev<ScalarType, MV>::V>
1003 Chebyshev<ScalarType, MV>::
1004 makeInverseDiagonal (
const row_matrix_type& A,
const bool useDiagOffsets)
const 1007 using Teuchos::rcpFromRef;
1008 using Teuchos::rcp_dynamic_cast;
1010 RCP<V> D_rowMap (
new V (A.getGraph ()->getRowMap ()));
1011 if (useDiagOffsets) {
1015 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
1016 typename MV::local_ordinal_type,
1017 typename MV::global_ordinal_type,
1018 typename MV::node_type> crs_matrix_type;
1019 RCP<const crs_matrix_type> A_crsMat =
1020 rcp_dynamic_cast<
const crs_matrix_type> (rcpFromRef (A));
1021 if (! A_crsMat.is_null ()) {
1022 TEUCHOS_TEST_FOR_EXCEPTION(
1023 ! savedDiagOffsets_, std::logic_error,
1024 "Ifpack2::Details::Chebyshev::makeInverseDiagonal: " 1025 "It is not allowed to call this method with useDiagOffsets=true, " 1026 "if you have not previously saved offsets of diagonal entries. " 1027 "This situation should never arise if this class is used properly. " 1028 "Please report this bug to the Ifpack2 developers.");
1029 A_crsMat->getLocalDiagCopy (*D_rowMap, diagOffsets_);
1035 A.getLocalDiagCopy (*D_rowMap);
1037 RCP<V> D_rangeMap = makeRangeMapVector (D_rowMap);
1043 D_rangeMap->sync_host ();
1044 auto D_lcl = D_rangeMap->getLocalViewHost ();
1045 auto D_lcl_1d = Kokkos::subview (D_lcl, Kokkos::ALL (), 0);
1047 typedef typename MV::impl_scalar_type IST;
1048 typedef typename MV::local_ordinal_type LO;
1049 typedef Kokkos::Details::ArithTraits<IST> STS;
1050 typedef Kokkos::Details::ArithTraits<typename STS::mag_type> STM;
1052 const LO lclNumRows =
static_cast<LO
> (D_rangeMap->getLocalLength ());
1053 bool foundNonpositiveValue =
false;
1054 for (LO i = 0; i < lclNumRows; ++i) {
1055 if (STS::real (D_lcl_1d(i)) <= STM::zero ()) {
1056 foundNonpositiveValue =
true;
1061 using Teuchos::outArg;
1062 using Teuchos::REDUCE_MIN;
1063 using Teuchos::reduceAll;
1065 const int lclSuccess = foundNonpositiveValue ? 0 : 1;
1066 int gblSuccess = lclSuccess;
1067 if (! D_rangeMap->getMap ().is_null () && D_rangeMap->getMap ()->getComm ().is_null ()) {
1068 const Teuchos::Comm<int>& comm = * (D_rangeMap->getMap ()->getComm ());
1069 reduceAll<int, int> (comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1071 if (gblSuccess == 1) {
1072 *out_ <<
"makeInverseDiagonal: The matrix's diagonal entries all have " 1073 "positive real part (this is good for Chebyshev)." << std::endl;
1076 *out_ <<
"makeInverseDiagonal: The matrix's diagonal has at least one " 1077 "entry with nonpositive real part, on at least one process in the " 1078 "matrix's communicator. This is bad for Chebyshev." << std::endl;
1084 reciprocal_threshold (*D_rangeMap, minDiagVal_);
1085 return Teuchos::rcp_const_cast<
const V> (D_rangeMap);
1089 template<
class ScalarType,
class MV>
1090 Teuchos::RCP<const typename Chebyshev<ScalarType, MV>::V>
1091 Chebyshev<ScalarType, MV>::
1092 makeRangeMapVectorConst (
const Teuchos::RCP<const V>& D)
const 1096 typedef Tpetra::Export<
typename MV::local_ordinal_type,
1097 typename MV::global_ordinal_type,
1098 typename MV::node_type> export_type;
1102 TEUCHOS_TEST_FOR_EXCEPTION(
1103 A_.is_null (), std::logic_error,
"Ifpack2::Details::Chebyshev::" 1104 "makeRangeMapVector: The input matrix A is null. Please call setMatrix() " 1105 "with a nonnull input matrix before calling this method. This is probably " 1106 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1107 TEUCHOS_TEST_FOR_EXCEPTION(
1108 D.is_null (), std::logic_error,
"Ifpack2::Details::Chebyshev::" 1109 "makeRangeMapVector: The input Vector D is null. This is probably " 1110 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1112 RCP<const map_type> sourceMap = D->getMap ();
1113 RCP<const map_type> rangeMap = A_->getRangeMap ();
1114 RCP<const map_type> rowMap = A_->getRowMap ();
1116 if (rangeMap->isSameAs (*sourceMap)) {
1122 RCP<const export_type> exporter;
1126 if (sourceMap->isSameAs (*rowMap)) {
1128 exporter = A_->getGraph ()->getExporter ();
1131 exporter = rcp (
new export_type (sourceMap, rangeMap));
1134 if (exporter.is_null ()) {
1138 RCP<V> D_out = rcp (
new V (*D, Teuchos::Copy));
1139 D_out->doExport (*D, *exporter, Tpetra::ADD);
1140 return Teuchos::rcp_const_cast<
const V> (D_out);
1146 template<
class ScalarType,
class MV>
1147 Teuchos::RCP<typename Chebyshev<ScalarType, MV>::V>
1148 Chebyshev<ScalarType, MV>::
1149 makeRangeMapVector (
const Teuchos::RCP<V>& D)
const 1151 using Teuchos::rcp_const_cast;
1152 return rcp_const_cast<V> (makeRangeMapVectorConst (rcp_const_cast<V> (D)));
1156 template<
class ScalarType,
class MV>
1158 Chebyshev<ScalarType, MV>::
1159 textbookApplyImpl (
const op_type& A,
1166 const V& D_inv)
const 1169 const ST myLambdaMin = lambdaMax / eigRatio;
1171 const ST zero = Teuchos::as<ST> (0);
1172 const ST one = Teuchos::as<ST> (1);
1173 const ST two = Teuchos::as<ST> (2);
1174 const ST d = (lambdaMax + myLambdaMin) / two;
1175 const ST c = (lambdaMax - myLambdaMin) / two;
1177 if (zeroStartingSolution_ && numIters > 0) {
1181 MV R (B.getMap (), B.getNumVectors (),
false);
1182 MV P (B.getMap (), B.getNumVectors (),
false);
1183 MV Z (B.getMap (), B.getNumVectors (),
false);
1185 for (
int i = 0; i < numIters; ++i) {
1186 computeResidual (R, B, A, X);
1187 solve (Z, D_inv, R);
1195 beta = alpha * (c/two) * (c/two);
1196 alpha = one / (d - beta);
1197 P.update (one, Z, beta);
1199 X.update (alpha, P, one);
1206 template<
class ScalarType,
class MV>
1207 typename Chebyshev<ScalarType, MV>::MT
1208 Chebyshev<ScalarType, MV>::maxNormInf (
const MV& X) {
1209 Teuchos::Array<MT> norms (X.getNumVectors ());
1210 X.normInf (norms());
1211 return *std::max_element (norms.begin (), norms.end ());
1214 template<
class ScalarType,
class MV>
1216 Chebyshev<ScalarType, MV>::
1217 ifpackApplyImpl (
const op_type& A,
1227 #ifdef HAVE_IFPACK2_DEBUG 1228 const bool debug = debug_;
1230 const bool debug =
false;
1234 *out_ <<
" \\|B\\|_{\\infty} = " << maxNormInf (B) << endl;
1235 *out_ <<
" \\|X\\|_{\\infty} = " << maxNormInf (X) << endl;
1238 if (numIters <= 0) {
1241 const ST zero =
static_cast<ST
> (0.0);
1242 const ST one =
static_cast<ST
> (1.0);
1243 const ST two =
static_cast<ST
> (2.0);
1246 if (lambdaMin == one && lambdaMax == lambdaMin) {
1247 solve (X, D_inv, B);
1252 const ST alpha = lambdaMax / eigRatio;
1253 const ST beta = boostFactor_ * lambdaMax;
1254 const ST delta = two / (beta - alpha);
1255 const ST theta = (beta + alpha) / two;
1256 const ST s1 = theta * delta;
1259 *out_ <<
" alpha = " << alpha << endl
1260 <<
" beta = " << beta << endl
1261 <<
" delta = " << delta << endl
1262 <<
" theta = " << theta << endl
1263 <<
" s1 = " << s1 << endl;
1267 Teuchos::RCP<MV> W_ptr = makeTempMultiVector (B);
1271 *out_ <<
" Iteration " << 1 <<
":" << endl
1272 <<
" - \\|D\\|_{\\infty} = " << D_->normInf () << endl;
1276 if (! zeroStartingSolution_) {
1279 if (ck_.is_null ()) {
1280 Teuchos::RCP<const op_type> A_op = A_;
1281 ck_ = Teuchos::rcp (
new ChebyshevKernel<op_type> (A_op));
1285 ck_->compute (W, one/theta, const_cast<V&> (D_inv),
1286 const_cast<MV&> (B), X, zero);
1290 firstIterationWithZeroStartingSolution (W, one/theta, D_inv, B, X);
1294 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf (W) << endl
1295 <<
" - \\|X\\|_{\\infty} = " << maxNormInf (X) << endl;
1298 if (numIters > 1 && ck_.is_null ()) {
1299 Teuchos::RCP<const op_type> A_op = A_;
1300 ck_ = Teuchos::rcp (
new ChebyshevKernel<op_type> (A_op));
1305 ST rhokp1, dtemp1, dtemp2;
1306 for (
int deg = 1; deg < numIters; ++deg) {
1308 *out_ <<
" Iteration " << deg+1 <<
":" << endl
1309 <<
" - \\|D\\|_{\\infty} = " << D_->normInf () << endl
1310 <<
" - \\|B\\|_{\\infty} = " << maxNormInf (B) << endl
1311 <<
" - \\|A\\|_{\\text{frob}} = " << A_->getFrobeniusNorm ()
1312 << endl <<
" - rhok = " << rhok << endl;
1315 rhokp1 = one / (two * s1 - rhok);
1316 dtemp1 = rhokp1 * rhok;
1317 dtemp2 = two * rhokp1 * delta;
1321 *out_ <<
" - dtemp1 = " << dtemp1 << endl
1322 <<
" - dtemp2 = " << dtemp2 << endl;
1327 ck_->compute (W, dtemp2, const_cast<V&> (D_inv),
1328 const_cast<MV&> (B), (X), dtemp1);
1331 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf (W) << endl
1332 <<
" - \\|X\\|_{\\infty} = " << maxNormInf (X) << endl;
1337 template<
class ScalarType,
class MV>
1338 typename Chebyshev<ScalarType, MV>::ST
1339 Chebyshev<ScalarType, MV>::
1340 powerMethodWithInitGuess (
const op_type& A,
1347 *out_ <<
" powerMethodWithInitGuess:" << endl;
1350 const ST zero =
static_cast<ST
> (0.0);
1351 const ST one =
static_cast<ST
> (1.0);
1352 ST lambdaMax = zero;
1353 ST RQ_top, RQ_bottom, norm;
1355 V y (A.getRangeMap ());
1357 TEUCHOS_TEST_FOR_EXCEPTION
1358 (norm == zero, std::runtime_error,
1359 "Ifpack2::Chebyshev::powerMethodWithInitGuess: The initial guess " 1360 "has zero norm. This could be either because Tpetra::Vector::" 1361 "randomize filled the vector with zeros (if that was used to " 1362 "compute the initial guess), or because the norm2 method has a " 1363 "bug. The first is not impossible, but unlikely.");
1366 *out_ <<
" Original norm1(x): " << x.norm1 ()
1367 <<
", norm2(x): " << norm << endl;
1370 x.scale (one / norm);
1373 *out_ <<
" norm1(x.scale(one/norm)): " << x.norm1 () << endl;
1376 for (
int iter = 0; iter < numIters; ++iter) {
1378 *out_ <<
" Iteration " << iter << endl;
1381 solve (y, D_inv, y);
1383 RQ_bottom = x.dot (x);
1385 *out_ <<
" RQ_top: " << RQ_top
1386 <<
", RQ_bottom: " << RQ_bottom << endl;
1388 lambdaMax = RQ_top / RQ_bottom;
1392 *out_ <<
" norm is zero; returning zero" << endl;
1396 x.update (one / norm, y, zero);
1399 *out_ <<
" lambdaMax: " << lambdaMax << endl;
1404 template<
class ScalarType,
class MV>
1406 Chebyshev<ScalarType, MV>::
1407 computeInitialGuessForPowerMethod (V& x,
const bool nonnegativeRealParts)
const 1409 typedef typename MV::device_type::execution_space dev_execution_space;
1410 typedef typename MV::device_type::memory_space dev_memory_space;
1411 typedef typename MV::local_ordinal_type LO;
1415 if (nonnegativeRealParts) {
1416 x.template modify<dev_memory_space> ();
1417 auto x_lcl = x.template getLocalView<dev_memory_space> ();
1418 auto x_lcl_1d = Kokkos::subview (x_lcl, Kokkos::ALL (), 0);
1420 const LO lclNumRows =
static_cast<LO
> (x.getLocalLength ());
1421 Kokkos::RangePolicy<dev_execution_space, LO> range (0, lclNumRows);
1422 PositivizeVector<decltype (x_lcl_1d), LO> functor (x_lcl_1d);
1423 Kokkos::parallel_for (range, functor);
1427 template<
class ScalarType,
class MV>
1428 typename Chebyshev<ScalarType, MV>::ST
1429 Chebyshev<ScalarType, MV>::
1430 powerMethod (
const op_type& A,
const V& D_inv,
const int numIters)
1434 *out_ <<
"powerMethod:" << endl;
1437 const ST zero =
static_cast<ST
> (0.0);
1438 V x (A.getDomainMap ());
1442 computeInitialGuessForPowerMethod (x,
false);
1444 ST lambdaMax = powerMethodWithInitGuess (A, D_inv, numIters, x);
1453 if (STS::real (lambdaMax) < STS::real (zero)) {
1455 *out_ <<
"real(lambdaMax) = " << STS::real (lambdaMax) <<
" < 0; " 1456 "try again with a different random initial guess" << endl;
1465 computeInitialGuessForPowerMethod (x,
true);
1466 lambdaMax = powerMethodWithInitGuess (A, D_inv, numIters, x);
1471 template<
class ScalarType,
class MV>
1472 Teuchos::RCP<const typename Chebyshev<ScalarType, MV>::row_matrix_type>
1477 template<
class ScalarType,
class MV>
1485 template<
class ScalarType,
class MV>
1495 const size_t B_numVecs = B.getNumVectors ();
1496 if (W_.is_null () || W_->getNumVectors () != B_numVecs) {
1497 W_ = Teuchos::rcp (
new MV (B.getMap (), B_numVecs,
true));
1502 template<
class ScalarType,
class MV>
1504 Chebyshev<ScalarType, MV>::
1505 description ()
const {
1506 std::ostringstream oss;
1509 oss <<
"\"Ifpack2::Details::Chebyshev\":" 1511 <<
"degree: " << numIters_
1512 <<
", lambdaMax: " << lambdaMaxForApply_
1513 <<
", alpha: " << eigRatioForApply_
1514 <<
", lambdaMin: " << lambdaMinForApply_
1515 <<
", boost factor: " << boostFactor_
1520 template<
class ScalarType,
class MV>
1524 const Teuchos::EVerbosityLevel verbLevel)
const 1526 using Teuchos::TypeNameTraits;
1529 const Teuchos::EVerbosityLevel vl =
1530 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
1531 if (vl == Teuchos::VERB_NONE) {
1541 Teuchos::OSTab tab0 (out);
1547 if (A_.is_null () || A_->getComm ().is_null ()) {
1551 myRank = A_->getComm ()->getRank ();
1556 out <<
"\"Ifpack2::Details::Chebyshev\":" << endl;
1558 Teuchos::OSTab tab1 (out);
1560 if (vl == Teuchos::VERB_LOW) {
1562 out <<
"degree: " << numIters_ << endl
1563 <<
"lambdaMax: " << lambdaMaxForApply_ << endl
1564 <<
"alpha: " << eigRatioForApply_ << endl
1565 <<
"lambdaMin: " << lambdaMinForApply_ << endl
1566 <<
"boost factor: " << boostFactor_ << endl;
1574 out <<
"Template parameters:" << endl;
1576 Teuchos::OSTab tab2 (out);
1577 out <<
"ScalarType: " << TypeNameTraits<ScalarType>::name () << endl
1578 <<
"MV: " << TypeNameTraits<MV>::name () << endl;
1584 out <<
"Computed parameters:" << endl;
1590 Teuchos::OSTab tab2 (out);
1596 if (D_.is_null ()) {
1598 out <<
"unset" << endl;
1601 else if (vl <= Teuchos::VERB_HIGH) {
1603 out <<
"set" << endl;
1612 D_->describe (out, vl);
1617 out <<
"W_: " << (W_.is_null () ?
"unset" :
"set") << endl
1618 <<
"computedLambdaMax_: " << computedLambdaMax_ << endl
1619 <<
"computedLambdaMin_: " << computedLambdaMin_ << endl
1620 <<
"lambdaMaxForApply_: " << lambdaMaxForApply_ << endl
1621 <<
"lambdaMinForApply_: " << lambdaMinForApply_ << endl
1622 <<
"eigRatioForApply_: " << eigRatioForApply_ << endl;
1627 out <<
"User parameters:" << endl;
1632 Teuchos::OSTab tab2 (out);
1633 out <<
"userInvDiag_: ";
1634 if (userInvDiag_.is_null ()) {
1635 out <<
"unset" << endl;
1637 else if (vl <= Teuchos::VERB_HIGH) {
1638 out <<
"set" << endl;
1644 userInvDiag_->describe (out, vl);
1647 out <<
"userLambdaMax_: " << userLambdaMax_ << endl
1648 <<
"userLambdaMin_: " << userLambdaMin_ << endl
1649 <<
"userEigRatio_: " << userEigRatio_ << endl
1650 <<
"numIters_: " << numIters_ << endl
1651 <<
"eigMaxIters_: " << eigMaxIters_ << endl
1652 <<
"zeroStartingSolution_: " << zeroStartingSolution_ << endl
1653 <<
"assumeMatrixUnchanged_: " << assumeMatrixUnchanged_ << endl
1654 <<
"textbookAlgorithm_: " << textbookAlgorithm_ << endl
1655 <<
"computeMaxResNorm_: " << computeMaxResNorm_ << endl;
1663 #define IFPACK2_DETAILS_CHEBYSHEV_INSTANT(S,LO,GO,N) \ 1664 template class Ifpack2::Details::Chebyshev< S, Tpetra::MultiVector<S, LO, GO, N> >; 1666 #endif // IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP Chebyshev(Teuchos::RCP< const row_matrix_type > A)
Definition: Ifpack2_Details_Chebyshev_def.hpp:279
Ifpack2 implementation details.
Diagonally scaled Chebyshev iteration for Tpetra sparse matrices.
Definition: Ifpack2_Chebyshev_decl.hpp:199
STS::magnitudeType MT
The type of the absolute value of a ScalarType.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:116
scalar_type ST
The type of entries in the matrix and vectors.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:112
Left-scaled Chebyshev iteration.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:106
Declaration of Chebyshev implementation.
Definition: Ifpack2_Container_decl.hpp:565
Teuchos::ScalarTraits< scalar_type > STS
Traits class for ST.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:114
Preconditioners and smoothers for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:73
Tpetra::Vector< typename MV::scalar_type, typename MV::local_ordinal_type, typename MV::global_ordinal_type, typename MV::node_type > V
Specialization of Tpetra::Vector.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:131