10 #ifndef IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP
11 #define IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP
24 #include "Ifpack2_Details_ChebyshevKernel.hpp"
25 #include "Kokkos_ArithTraits.hpp"
26 #include "Teuchos_FancyOStream.hpp"
27 #include "Teuchos_oblackholestream.hpp"
28 #include "Tpetra_Details_residual.hpp"
30 #include "Ifpack2_Details_LapackSupportsScalar.hpp"
40 const char computeBeforeApplyReminder[] =
41 "This means one of the following:\n"
42 " - you have not yet called compute() on this instance, or \n"
43 " - you didn't call compute() after calling setParameters().\n\n"
44 "After creating an Ifpack2::Chebyshev instance,\n"
45 "you must _always_ call compute() at least once before calling apply().\n"
46 "After calling compute() once, you do not need to call it again,\n"
47 "unless the matrix has changed or you have changed parameters\n"
48 "(by calling setParameters()).";
54 template<
class XV,
class SizeType =
typename XV::
size_type>
55 struct V_ReciprocalThresholdSelfFunctor
57 typedef typename XV::execution_space execution_space;
58 typedef typename XV::non_const_value_type value_type;
59 typedef SizeType size_type;
60 typedef Kokkos::ArithTraits<value_type> KAT;
61 typedef typename KAT::mag_type mag_type;
64 const value_type minVal_;
65 const mag_type minValMag_;
67 V_ReciprocalThresholdSelfFunctor (
const XV& X,
68 const value_type& min_val) :
71 minValMag_ (KAT::abs (min_val))
74 KOKKOS_INLINE_FUNCTION
75 void operator() (
const size_type& i)
const
77 const mag_type X_i_abs = KAT::abs (X_[i]);
79 if (X_i_abs < minValMag_) {
83 X_[i] = KAT::one () / X_[i];
88 template<
class XV,
class SizeType =
typename XV::
size_type>
89 struct LocalReciprocalThreshold {
92 const typename XV::non_const_value_type& minVal)
94 typedef typename XV::execution_space execution_space;
95 Kokkos::RangePolicy<execution_space, SizeType> policy (0, X.extent (0));
96 V_ReciprocalThresholdSelfFunctor<XV, SizeType> op (X, minVal);
97 Kokkos::parallel_for (policy, op);
101 template <
class TpetraVectorType,
102 const bool classic = TpetraVectorType::node_type::classic>
103 struct GlobalReciprocalThreshold {};
105 template <
class TpetraVectorType>
106 struct GlobalReciprocalThreshold<TpetraVectorType, true> {
108 compute (TpetraVectorType& V,
109 const typename TpetraVectorType::scalar_type& min_val)
111 typedef typename TpetraVectorType::scalar_type scalar_type;
112 typedef typename TpetraVectorType::mag_type mag_type;
113 typedef Kokkos::ArithTraits<scalar_type> STS;
115 const scalar_type ONE = STS::one ();
116 const mag_type min_val_abs = STS::abs (min_val);
119 const size_t lclNumRows = V.getLocalLength ();
121 for (
size_t i = 0; i < lclNumRows; ++i) {
122 const scalar_type V_0i = V_0[i];
123 if (STS::abs (V_0i) < min_val_abs) {
132 template <
class TpetraVectorType>
133 struct GlobalReciprocalThreshold<TpetraVectorType, false> {
135 compute (TpetraVectorType& X,
136 const typename TpetraVectorType::scalar_type& minVal)
138 typedef typename TpetraVectorType::impl_scalar_type value_type;
140 const value_type minValS =
static_cast<value_type
> (minVal);
141 auto X_0 = Kokkos::subview (X.getLocalViewDevice (Tpetra::Access::ReadWrite),
143 LocalReciprocalThreshold<decltype (X_0) >::compute (X_0, minValS);
148 template <
typename S,
typename L,
typename G,
typename N>
150 reciprocal_threshold (Tpetra::Vector<S,L,G,N>& V,
const S& minVal)
152 GlobalReciprocalThreshold<Tpetra::Vector<S,L,G,N> >::compute (V, minVal);
156 template<class ScalarType, const bool lapackSupportsScalarType = LapackSupportsScalar<ScalarType>::value>
162 throw std::runtime_error(
"LAPACK does not support the scalar type.");
169 computeInitialGuessForCG (
const V& diagonal, V& x) {
170 using device_type =
typename V::node_type::device_type;
171 using range_policy = Kokkos::RangePolicy<typename device_type::execution_space>;
179 size_t N = x.getLocalLength();
180 auto d_view = diagonal.template getLocalView<device_type>(Tpetra::Access::ReadOnly);
181 auto x_view = x.template getLocalView<device_type>(Tpetra::Access::ReadWrite);
186 Kokkos::parallel_for(
"computeInitialGuessforCG::zero_bcs", range_policy(0,N), KOKKOS_LAMBDA(
const size_t & i) {
187 if(d_view(i,0) == ONE)
196 template<
class ScalarType>
197 struct LapackHelper<ScalarType,true> {
203 using MagnitudeType =
typename STS::magnitudeType;
205 const int N = diag.size ();
206 ScalarType scalar_dummy;
207 std::vector<MagnitudeType> mag_dummy(4*N);
211 ScalarType lambdaMax = STS::one();
214 lapack.
PTEQR (char_N, N, diag.getRawPtr (), offdiag.getRawPtr (),
215 &scalar_dummy, 1, &mag_dummy[0], &info);
217 (info < 0, std::logic_error,
"Ifpack2::Details::LapackHelper::tri_diag_spectral_radius:"
218 "LAPACK's _PTEQR failed with info = "
219 << info <<
" < 0. This suggests there might be a bug in the way Ifpack2 "
220 "is calling LAPACK. Please report this to the Ifpack2 developers.");
222 lambdaMax = Teuchos::as<ScalarType> (diag[0]);
229 template<
class ScalarType,
class MV>
230 void Chebyshev<ScalarType, MV>::checkInputMatrix ()
const
233 ! A_.
is_null () && A_->getGlobalNumRows () != A_->getGlobalNumCols (),
234 std::invalid_argument,
235 "Ifpack2::Chebyshev: The input matrix A must be square. "
236 "A has " << A_->getGlobalNumRows () <<
" rows and "
237 << A_->getGlobalNumCols () <<
" columns.");
241 if (debug_ && ! A_.
is_null ()) {
249 ! domainMap->isSameAs (*rangeMap), std::invalid_argument,
250 "Ifpack2::Chebyshev: The domain Map and range Map of the matrix must be "
251 "the same (in the sense of isSameAs())." << std::endl <<
"We only check "
252 "for this in debug mode.");
257 template<
class ScalarType,
class MV>
259 Chebyshev<ScalarType, MV>::
260 checkConstructorInput ()
const
265 if (STS::isComplex) {
267 (
true, std::logic_error,
"Ifpack2::Chebyshev: This class' implementation "
268 "of Chebyshev iteration only works for real-valued, symmetric positive "
269 "definite matrices. However, you instantiated this class for ScalarType"
271 "complex-valued type. While this may be algorithmically correct if all "
272 "of the complex numbers in the matrix have zero imaginary part, we "
273 "forbid using complex ScalarType altogether in order to remind you of "
274 "the limitations of our implementation (and of the algorithm itself).");
281 template<
class ScalarType,
class MV>
285 savedDiagOffsets_ (false),
286 computedLambdaMax_ (STS::nan ()),
287 computedLambdaMin_ (STS::nan ()),
288 lambdaMaxForApply_ (STS::nan ()),
289 lambdaMinForApply_ (STS::nan ()),
290 eigRatioForApply_ (STS::nan ()),
291 userLambdaMax_ (STS::nan ()),
292 userLambdaMin_ (STS::nan ()),
293 userEigRatio_ (Teuchos::
as<
ST> (30)),
294 minDiagVal_ (STS::eps ()),
297 eigRelTolerance_(Teuchos::ScalarTraits<
MT>::zero ()),
298 eigKeepVectors_(false),
299 eigenAnalysisType_(
"power method"),
300 eigNormalizationFreq_(1),
301 zeroStartingSolution_ (true),
302 assumeMatrixUnchanged_ (false),
303 chebyshevAlgorithm_(
"first"),
304 computeMaxResNorm_ (false),
305 computeSpectralRadius_(true),
306 ckUseNativeSpMV_(false),
309 checkConstructorInput ();
312 template<
class ScalarType,
class MV>
317 savedDiagOffsets_ (false),
318 computedLambdaMax_ (STS::nan ()),
319 computedLambdaMin_ (STS::nan ()),
320 lambdaMaxForApply_ (STS::nan ()),
321 boostFactor_ (static_cast<
MT> (1.1)),
322 lambdaMinForApply_ (STS::nan ()),
323 eigRatioForApply_ (STS::nan ()),
324 userLambdaMax_ (STS::nan ()),
325 userLambdaMin_ (STS::nan ()),
326 userEigRatio_ (Teuchos::
as<
ST> (30)),
327 minDiagVal_ (STS::eps ()),
330 eigRelTolerance_(Teuchos::ScalarTraits<
MT>::zero ()),
331 eigKeepVectors_(false),
332 eigenAnalysisType_(
"power method"),
333 eigNormalizationFreq_(1),
334 zeroStartingSolution_ (true),
335 assumeMatrixUnchanged_ (false),
336 chebyshevAlgorithm_(
"first"),
337 computeMaxResNorm_ (false),
338 computeSpectralRadius_(true),
339 ckUseNativeSpMV_(false),
342 checkConstructorInput ();
346 template<
class ScalarType,
class MV>
353 using Teuchos::rcp_const_cast;
365 const ST defaultLambdaMax = STS::nan ();
366 const ST defaultLambdaMin = STS::nan ();
373 const ST defaultEigRatio = Teuchos::as<ST> (30);
374 const MT defaultBoostFactor =
static_cast<MT> (1.1);
375 const ST defaultMinDiagVal = STS::eps ();
376 const int defaultNumIters = 1;
377 const int defaultEigMaxIters = 10;
379 const bool defaultEigKeepVectors =
false;
380 const int defaultEigNormalizationFreq = 1;
381 const bool defaultZeroStartingSolution =
true;
382 const bool defaultAssumeMatrixUnchanged =
false;
383 const std::string defaultChebyshevAlgorithm =
"first";
384 const bool defaultComputeMaxResNorm =
false;
385 const bool defaultComputeSpectralRadius =
true;
386 const bool defaultCkUseNativeSpMV =
false;
387 const bool defaultDebug =
false;
393 RCP<const V> userInvDiagCopy;
394 ST lambdaMax = defaultLambdaMax;
395 ST lambdaMin = defaultLambdaMin;
396 ST eigRatio = defaultEigRatio;
397 MT boostFactor = defaultBoostFactor;
398 ST minDiagVal = defaultMinDiagVal;
399 int numIters = defaultNumIters;
400 int eigMaxIters = defaultEigMaxIters;
401 MT eigRelTolerance = defaultEigRelTolerance;
402 bool eigKeepVectors = defaultEigKeepVectors;
403 int eigNormalizationFreq = defaultEigNormalizationFreq;
404 bool zeroStartingSolution = defaultZeroStartingSolution;
405 bool assumeMatrixUnchanged = defaultAssumeMatrixUnchanged;
406 std::string chebyshevAlgorithm = defaultChebyshevAlgorithm;
407 bool computeMaxResNorm = defaultComputeMaxResNorm;
408 bool computeSpectralRadius = defaultComputeSpectralRadius;
409 bool ckUseNativeSpMV = defaultCkUseNativeSpMV;
410 bool debug = defaultDebug;
417 if (plist.
isType<
bool> (
"debug")) {
418 debug = plist.
get<
bool> (
"debug");
420 else if (plist.
isType<
int> (
"debug")) {
421 const int debugInt = plist.
get<
bool> (
"debug");
422 debug = debugInt != 0;
435 const char opInvDiagLabel[] =
"chebyshev: operator inv diagonal";
438 RCP<const V> userInvDiag;
440 if (plist.
isType<
const V*> (opInvDiagLabel)) {
441 const V* rawUserInvDiag =
442 plist.
get<
const V*> (opInvDiagLabel);
444 userInvDiag =
rcp (rawUserInvDiag,
false);
446 else if (plist.
isType<
const V*> (opInvDiagLabel)) {
447 V* rawUserInvDiag = plist.
get<V*> (opInvDiagLabel);
449 userInvDiag =
rcp (const_cast<const V*> (rawUserInvDiag),
false);
451 else if (plist.
isType<RCP<const V>> (opInvDiagLabel)) {
452 userInvDiag = plist.
get<RCP<const V> > (opInvDiagLabel);
454 else if (plist.
isType<RCP<V>> (opInvDiagLabel)) {
455 RCP<V> userInvDiagNonConst =
456 plist.
get<RCP<V> > (opInvDiagLabel);
457 userInvDiag = rcp_const_cast<
const V> (userInvDiagNonConst);
459 else if (plist.
isType<
const V> (opInvDiagLabel)) {
460 const V& userInvDiagRef = plist.
get<
const V> (opInvDiagLabel);
462 userInvDiag = userInvDiagCopy;
464 else if (plist.
isType<V> (opInvDiagLabel)) {
465 V& userInvDiagNonConstRef = plist.
get<V> (opInvDiagLabel);
466 const V& userInvDiagRef =
const_cast<const V&
> (userInvDiagNonConstRef);
468 userInvDiag = userInvDiagCopy;
478 if (! userInvDiag.is_null () && userInvDiagCopy.is_null ()) {
489 if (plist.
isParameter (
"chebyshev: use native spmv"))
490 ckUseNativeSpMV = plist.
get(
"chebyshev: use native spmv", ckUseNativeSpMV);
495 if (plist.
isParameter (
"chebyshev: max eigenvalue")) {
496 if (plist.
isType<
double>(
"chebyshev: max eigenvalue"))
497 lambdaMax = plist.
get<
double> (
"chebyshev: max eigenvalue");
499 lambdaMax = plist.
get<
ST> (
"chebyshev: max eigenvalue");
501 STS::isnaninf (lambdaMax), std::invalid_argument,
502 "Ifpack2::Chebyshev::setParameters: \"chebyshev: max eigenvalue\" "
503 "parameter is NaN or Inf. This parameter is optional, but if you "
504 "choose to supply it, it must have a finite value.");
506 if (plist.
isParameter (
"chebyshev: min eigenvalue")) {
507 if (plist.
isType<
double>(
"chebyshev: min eigenvalue"))
508 lambdaMin = plist.
get<
double> (
"chebyshev: min eigenvalue");
510 lambdaMin = plist.
get<
ST> (
"chebyshev: min eigenvalue");
512 STS::isnaninf (lambdaMin), std::invalid_argument,
513 "Ifpack2::Chebyshev::setParameters: \"chebyshev: min eigenvalue\" "
514 "parameter is NaN or Inf. This parameter is optional, but if you "
515 "choose to supply it, it must have a finite value.");
519 if (plist.
isParameter (
"smoother: Chebyshev alpha")) {
520 if (plist.
isType<
double>(
"smoother: Chebyshev alpha"))
521 eigRatio = plist.
get<
double> (
"smoother: Chebyshev alpha");
523 eigRatio = plist.
get<
ST> (
"smoother: Chebyshev alpha");
526 eigRatio = plist.
get (
"chebyshev: ratio eigenvalue", eigRatio);
528 STS::isnaninf (eigRatio), std::invalid_argument,
529 "Ifpack2::Chebyshev::setParameters: \"chebyshev: ratio eigenvalue\" "
530 "parameter (also called \"smoother: Chebyshev alpha\") is NaN or Inf. "
531 "This parameter is optional, but if you choose to supply it, it must have "
539 STS::real (eigRatio) < STS::real (STS::one ()),
540 std::invalid_argument,
541 "Ifpack2::Chebyshev::setParameters: \"chebyshev: ratio eigenvalue\""
542 "parameter (also called \"smoother: Chebyshev alpha\") must be >= 1, "
543 "but you supplied the value " << eigRatio <<
".");
548 const char paramName[] =
"chebyshev: boost factor";
552 boostFactor = plist.
get<
MT> (paramName);
554 else if (! std::is_same<double, MT>::value &&
555 plist.
isType<
double> (paramName)) {
556 const double dblBF = plist.
get<
double> (paramName);
557 boostFactor =
static_cast<MT> (dblBF);
561 (
true, std::invalid_argument,
562 "Ifpack2::Chebyshev::setParameters: \"chebyshev: boost factor\""
563 "parameter must have type magnitude_type (MT) or double.");
573 plist.
set (paramName, defaultBoostFactor);
577 "Ifpack2::Chebyshev::setParameters: \"" << paramName <<
"\" parameter "
578 "must be >= 1, but you supplied the value " << boostFactor <<
".");
582 minDiagVal = plist.
get (
"chebyshev: min diagonal value", minDiagVal);
584 STS::isnaninf (minDiagVal), std::invalid_argument,
585 "Ifpack2::Chebyshev::setParameters: \"chebyshev: min diagonal value\" "
586 "parameter is NaN or Inf. This parameter is optional, but if you choose "
587 "to supply it, it must have a finite value.");
591 numIters = plist.
get<
int> (
"smoother: sweeps");
594 numIters = plist.
get<
int> (
"relaxation: sweeps");
596 numIters = plist.
get (
"chebyshev: degree", numIters);
598 numIters < 0, std::invalid_argument,
599 "Ifpack2::Chebyshev::setParameters: \"chebyshev: degree\" parameter (also "
600 "called \"smoother: sweeps\" or \"relaxation: sweeps\") must be a "
601 "nonnegative integer. You gave a value of " << numIters <<
".");
604 if (plist.
isParameter (
"eigen-analysis: iterations")) {
605 eigMaxIters = plist.
get<
int> (
"eigen-analysis: iterations");
607 eigMaxIters = plist.
get (
"chebyshev: eigenvalue max iterations", eigMaxIters);
609 eigMaxIters < 0, std::invalid_argument,
610 "Ifpack2::Chebyshev::setParameters: \"chebyshev: eigenvalue max iterations"
611 "\" parameter (also called \"eigen-analysis: iterations\") must be a "
612 "nonnegative integer. You gave a value of " << eigMaxIters <<
".");
614 if (plist.
isType<
double>(
"chebyshev: eigenvalue relative tolerance"))
615 eigRelTolerance = Teuchos::as<MT>(plist.
get<
double> (
"chebyshev: eigenvalue relative tolerance"));
616 else if (plist.
isType<
MT>(
"chebyshev: eigenvalue relative tolerance"))
617 eigRelTolerance = plist.
get<
MT> (
"chebyshev: eigenvalue relative tolerance");
618 else if (plist.
isType<
ST>(
"chebyshev: eigenvalue relative tolerance"))
621 eigKeepVectors = plist.
get (
"chebyshev: eigenvalue keep vectors", eigKeepVectors);
623 eigNormalizationFreq = plist.
get (
"chebyshev: eigenvalue normalization frequency", eigNormalizationFreq);
625 eigNormalizationFreq < 0, std::invalid_argument,
626 "Ifpack2::Chebyshev::setParameters: \"chebyshev: eigenvalue normalization frequency"
627 "\" parameter must be a "
628 "nonnegative integer. You gave a value of " << eigNormalizationFreq <<
".")
630 zeroStartingSolution = plist.
get (
"chebyshev: zero starting solution",
631 zeroStartingSolution);
632 assumeMatrixUnchanged = plist.
get (
"chebyshev: assume matrix does not change",
633 assumeMatrixUnchanged);
638 chebyshevAlgorithm = plist.
get<std::string> (
"chebyshev: algorithm");
640 chebyshevAlgorithm !=
"first" &&
641 chebyshevAlgorithm !=
"textbook" &&
642 chebyshevAlgorithm !=
"fourth" &&
643 chebyshevAlgorithm !=
"opt_fourth",
644 std::invalid_argument,
645 "Ifpack2::Chebyshev: Ifpack2 only supports \"first\", \"textbook\", \"fourth\", and \"opt_fourth\", for \"chebyshev: algorithm\".");
648 #ifdef IFPACK2_ENABLE_DEPRECATED_CODE
652 if (plist.
isParameter (
"chebyshev: textbook algorithm")) {
653 const bool textbookAlgorithm = plist.
get<
bool> (
"chebyshev: textbook algorithm");
654 if(textbookAlgorithm){
655 chebyshevAlgorithm =
"textbook";
657 chebyshevAlgorithm =
"first";
663 if (plist.
isParameter (
"chebyshev: compute max residual norm")) {
664 computeMaxResNorm = plist.
get<
bool> (
"chebyshev: compute max residual norm");
666 if (plist.
isParameter (
"chebyshev: compute spectral radius")) {
667 computeSpectralRadius = plist.
get<
bool> (
"chebyshev: compute spectral radius");
676 (plist.
isType<
bool> (
"chebyshev: use block mode") &&
677 ! plist.
get<
bool> (
"chebyshev: use block mode"),
678 std::invalid_argument,
679 "Ifpack2::Chebyshev requires that if you set \"chebyshev: use "
680 "block mode\" at all, you must set it to false. "
681 "Ifpack2::Chebyshev does not implement Ifpack's block mode.");
683 (plist.
isType<
bool> (
"chebyshev: solve normal equations") &&
684 ! plist.
get<
bool> (
"chebyshev: solve normal equations"),
685 std::invalid_argument,
686 "Ifpack2::Chebyshev does not and will never implement the Ifpack "
687 "parameter \"chebyshev: solve normal equations\". If you want to "
688 "solve the normal equations, construct a Tpetra::Operator that "
689 "implements A^* A, and use Chebyshev to solve A^* A x = A^* b.");
697 std::string eigenAnalysisType (
"power-method");
699 eigenAnalysisType = plist.
get<std::string> (
"eigen-analysis: type");
701 eigenAnalysisType !=
"power-method" &&
702 eigenAnalysisType !=
"power method" &&
703 eigenAnalysisType !=
"cg",
704 std::invalid_argument,
705 "Ifpack2::Chebyshev: Ifpack2 only supports \"power method\" and \"cg\" for \"eigen-analysis: type\".");
709 userInvDiag_ = userInvDiagCopy;
710 userLambdaMax_ = lambdaMax;
711 userLambdaMin_ = lambdaMin;
712 userEigRatio_ = eigRatio;
713 boostFactor_ =
static_cast<MT> (boostFactor);
714 minDiagVal_ = minDiagVal;
715 numIters_ = numIters;
716 eigMaxIters_ = eigMaxIters;
717 eigRelTolerance_ = eigRelTolerance;
718 eigKeepVectors_ = eigKeepVectors;
719 eigNormalizationFreq_ = eigNormalizationFreq;
720 eigenAnalysisType_ = eigenAnalysisType;
721 zeroStartingSolution_ = zeroStartingSolution;
722 assumeMatrixUnchanged_ = assumeMatrixUnchanged;
723 chebyshevAlgorithm_ = chebyshevAlgorithm;
724 computeMaxResNorm_ = computeMaxResNorm;
725 computeSpectralRadius_ = computeSpectralRadius;
726 ckUseNativeSpMV_ = ckUseNativeSpMV;
738 myRank = A_->getComm ()->getRank ();
742 out_ = Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr));
747 out_ = Teuchos::getFancyOStream (blackHole);
752 out_ = Teuchos::null;
757 template<
class ScalarType,
class MV>
763 diagOffsets_ = offsets_type ();
764 savedDiagOffsets_ =
false;
766 computedLambdaMax_ = STS::nan ();
767 computedLambdaMin_ = STS::nan ();
768 eigVector_ = Teuchos::null;
769 eigVector2_ = Teuchos::null;
773 template<
class ScalarType,
class MV>
779 if (! assumeMatrixUnchanged_) {
797 myRank = A->getComm ()->getRank ();
801 out_ = Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr));
805 out_ = Teuchos::getFancyOStream (blackHole);
810 out_ = Teuchos::null;
815 template<
class ScalarType,
class MV>
824 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
825 typename MV::local_ordinal_type,
826 typename MV::global_ordinal_type,
827 typename MV::node_type> crs_matrix_type;
830 A_.
is_null (), std::runtime_error,
"Ifpack2::Chebyshev::compute: The input "
831 "matrix A is null. Please call setMatrix() with a nonnull input matrix "
832 "before calling this method.");
847 if (userInvDiag_.is_null ()) {
849 Teuchos::rcp_dynamic_cast<
const crs_matrix_type> (A_);
851 if (! A_crsMat.
is_null () && A_crsMat->isFillComplete ()) {
853 const size_t lclNumRows = A_crsMat->getLocalNumRows ();
854 if (diagOffsets_.extent (0) < lclNumRows) {
855 diagOffsets_ = offsets_type ();
856 diagOffsets_ = offsets_type (
"offsets", lclNumRows);
858 A_crsMat->getCrsGraph ()->getLocalDiagOffsets (diagOffsets_);
859 savedDiagOffsets_ =
true;
860 D_ = makeInverseDiagonal (*A_,
true);
863 D_ = makeInverseDiagonal (*A_);
866 else if (! assumeMatrixUnchanged_) {
867 if (! A_crsMat.
is_null () && A_crsMat->isFillComplete ()) {
870 if (! savedDiagOffsets_) {
871 const size_t lclNumRows = A_crsMat->getLocalNumRows ();
872 if (diagOffsets_.extent (0) < lclNumRows) {
873 diagOffsets_ = offsets_type ();
874 diagOffsets_ = offsets_type (
"offsets", lclNumRows);
876 A_crsMat->getCrsGraph ()->getLocalDiagOffsets (diagOffsets_);
877 savedDiagOffsets_ =
true;
880 D_ = makeInverseDiagonal (*A_,
true);
883 D_ = makeInverseDiagonal (*A_);
888 D_ = makeRangeMapVectorConst (userInvDiag_);
892 const bool computedEigenvalueEstimates =
893 STS::isnaninf (computedLambdaMax_) || STS::isnaninf (computedLambdaMin_);
903 if (! assumeMatrixUnchanged_ ||
904 (! computedEigenvalueEstimates && STS::isnaninf (userLambdaMax_))) {
905 ST computedLambdaMax;
906 if ((eigenAnalysisType_ ==
"power method") || (eigenAnalysisType_ ==
"power-method")) {
908 if (eigVector_.is_null()) {
912 PowerMethod::computeInitialGuessForPowerMethod (*x,
false);
917 if (eigVector2_.is_null()) {
918 y =
rcp(
new V(A_->getRangeMap ()));
925 computedLambdaMax = PowerMethod::powerMethodWithInitGuess (*A_, *D_, eigMaxIters_, x, y,
926 eigRelTolerance_, eigNormalizationFreq_, stream,
927 computeSpectralRadius_);
930 computedLambdaMax = cgMethod (*A_, *D_, eigMaxIters_);
933 STS::isnaninf (computedLambdaMax),
935 "Ifpack2::Chebyshev::compute: Estimation of the max eigenvalue "
936 "of D^{-1} A failed, by producing Inf or NaN. This probably means that "
937 "the matrix contains Inf or NaN values, or that it is badly scaled.");
939 STS::isnaninf (userEigRatio_),
941 "Ifpack2::Chebyshev::compute: userEigRatio_ is Inf or NaN."
942 << endl <<
"This should be impossible." << endl <<
943 "Please report this bug to the Ifpack2 developers.");
949 const ST computedLambdaMin = computedLambdaMax / userEigRatio_;
952 computedLambdaMax_ = computedLambdaMax;
953 computedLambdaMin_ = computedLambdaMin;
956 STS::isnaninf (userLambdaMax_) && STS::isnaninf (computedLambdaMax_),
958 "Ifpack2::Chebyshev::compute: " << endl <<
959 "Both userLambdaMax_ and computedLambdaMax_ are Inf or NaN."
960 << endl <<
"This should be impossible." << endl <<
961 "Please report this bug to the Ifpack2 developers.");
969 lambdaMaxForApply_ = STS::isnaninf (userLambdaMax_) ? computedLambdaMax_ : userLambdaMax_;
982 lambdaMinForApply_ = lambdaMaxForApply_ / userEigRatio_;
983 eigRatioForApply_ = userEigRatio_;
985 if (chebyshevAlgorithm_ ==
"first") {
988 const ST one = Teuchos::as<ST> (1);
991 if (STS::magnitude (lambdaMaxForApply_ - one) < Teuchos::as<MT> (1.0e-6)) {
992 lambdaMinForApply_ = one;
993 lambdaMaxForApply_ = lambdaMinForApply_;
994 eigRatioForApply_ = one;
1000 template<
class ScalarType,
class MV>
1004 return lambdaMaxForApply_;
1008 template<
class ScalarType,
class MV>
1012 const char prefix[] =
"Ifpack2::Chebyshev::apply: ";
1015 *out_ <<
"apply: " << std::endl;
1018 (A_.
is_null (), std::runtime_error, prefix <<
"The input matrix A is null. "
1019 " Please call setMatrix() with a nonnull input matrix, and then call "
1020 "compute(), before calling this method.");
1022 (STS::isnaninf (lambdaMaxForApply_), std::runtime_error,
1023 prefix <<
"There is no estimate for the max eigenvalue."
1024 << std::endl << computeBeforeApplyReminder);
1025 TEUCHOS_TEST_FOR_EXCEPTION
1026 (STS::isnaninf (lambdaMinForApply_), std::runtime_error,
1027 prefix <<
"There is no estimate for the min eigenvalue."
1028 << std::endl << computeBeforeApplyReminder);
1029 TEUCHOS_TEST_FOR_EXCEPTION
1030 (STS::isnaninf (eigRatioForApply_), std::runtime_error,
1031 prefix <<
"There is no estimate for the ratio of the max "
1032 "eigenvalue to the min eigenvalue."
1033 << std::endl << computeBeforeApplyReminder);
1034 TEUCHOS_TEST_FOR_EXCEPTION
1035 (D_.is_null (), std::runtime_error, prefix <<
"The vector of inverse "
1036 "diagonal entries of the matrix has not yet been computed."
1037 << std::endl << computeBeforeApplyReminder);
1039 if (chebyshevAlgorithm_ ==
"fourth" || chebyshevAlgorithm_ ==
"opt_fourth") {
1040 fourthKindApplyImpl (*A_, B, X, numIters_, lambdaMaxForApply_, *D_);
1042 else if (chebyshevAlgorithm_ ==
"textbook") {
1043 textbookApplyImpl (*A_, B, X, numIters_, lambdaMaxForApply_,
1044 lambdaMinForApply_, eigRatioForApply_, *D_);
1047 ifpackApplyImpl (*A_, B, X, numIters_, lambdaMaxForApply_,
1048 lambdaMinForApply_, eigRatioForApply_, *D_);
1051 if (computeMaxResNorm_ && B.getNumVectors () > 0) {
1052 MV R (B.getMap (), B.getNumVectors ());
1053 computeResidual (R, B, *A_, X);
1056 return *std::max_element (norms.begin (), norms.end ());
1063 template<
class ScalarType,
class MV>
1068 using Teuchos::rcpFromRef;
1069 this->describe (* (Teuchos::getFancyOStream (rcpFromRef (out))),
1073 template<
class ScalarType,
class MV>
1077 const ScalarType& alpha,
1082 solve (W, alpha, D_inv, B);
1083 Tpetra::deep_copy (X, W);
1086 template<
class ScalarType,
class MV>
1092 Tpetra::Details::residual(A,X,B,R);
1095 template <
class ScalarType,
class MV>
1097 Chebyshev<ScalarType, MV>::
1098 solve (MV& Z,
const V& D_inv,
const MV& R) {
1099 Z.elementWiseMultiply (STS::one(), D_inv, R, STS::zero());
1102 template<
class ScalarType,
class MV>
1104 Chebyshev<ScalarType, MV>::
1105 solve (MV& Z,
const ST alpha,
const V& D_inv,
const MV& R) {
1106 Z.elementWiseMultiply (alpha, D_inv, R, STS::zero());
1109 template<
class ScalarType,
class MV>
1111 Chebyshev<ScalarType, MV>::
1112 makeInverseDiagonal (
const row_matrix_type& A,
const bool useDiagOffsets)
const
1115 using Teuchos::rcpFromRef;
1116 using Teuchos::rcp_dynamic_cast;
1119 if (!D_.is_null() &&
1120 D_->getMap()->isSameAs(*(A.getRowMap ()))) {
1122 *out_ <<
"Reusing pre-existing vector for diagonal extraction" << std::endl;
1123 D_rowMap = Teuchos::rcp_const_cast<V>(D_);
1125 D_rowMap =
Teuchos::rcp(
new V (A.getRowMap (),
false));
1127 *out_ <<
"Allocated new vector for diagonal extraction" << std::endl;
1129 if (useDiagOffsets) {
1133 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
1134 typename MV::local_ordinal_type,
1135 typename MV::global_ordinal_type,
1136 typename MV::node_type> crs_matrix_type;
1137 RCP<const crs_matrix_type> A_crsMat =
1138 rcp_dynamic_cast<
const crs_matrix_type> (rcpFromRef (A));
1139 if (! A_crsMat.is_null ()) {
1141 ! savedDiagOffsets_, std::logic_error,
1142 "Ifpack2::Details::Chebyshev::makeInverseDiagonal: "
1143 "It is not allowed to call this method with useDiagOffsets=true, "
1144 "if you have not previously saved offsets of diagonal entries. "
1145 "This situation should never arise if this class is used properly. "
1146 "Please report this bug to the Ifpack2 developers.");
1147 A_crsMat->getLocalDiagCopy (*D_rowMap, diagOffsets_);
1153 A.getLocalDiagCopy (*D_rowMap);
1155 RCP<V> D_rangeMap = makeRangeMapVector (D_rowMap);
1161 bool foundNonpositiveValue =
false;
1163 auto D_lcl = D_rangeMap->getLocalViewHost (Tpetra::Access::ReadOnly);
1164 auto D_lcl_1d = Kokkos::subview (D_lcl, Kokkos::ALL (), 0);
1166 typedef typename MV::impl_scalar_type IST;
1167 typedef typename MV::local_ordinal_type LO;
1168 typedef Kokkos::ArithTraits<IST> ATS;
1169 typedef Kokkos::ArithTraits<typename ATS::mag_type> STM;
1171 const LO lclNumRows =
static_cast<LO
> (D_rangeMap->getLocalLength ());
1172 for (LO i = 0; i < lclNumRows; ++i) {
1173 if (STS::real (D_lcl_1d(i)) <= STM::zero ()) {
1174 foundNonpositiveValue =
true;
1180 using Teuchos::outArg;
1182 using Teuchos::reduceAll;
1184 const int lclSuccess = foundNonpositiveValue ? 0 : 1;
1185 int gblSuccess = lclSuccess;
1186 if (! D_rangeMap->getMap ().is_null () && D_rangeMap->getMap ()->getComm ().is_null ()) {
1188 reduceAll<int, int> (comm,
REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1190 if (gblSuccess == 1) {
1191 *out_ <<
"makeInverseDiagonal: The matrix's diagonal entries all have "
1192 "positive real part (this is good for Chebyshev)." << std::endl;
1195 *out_ <<
"makeInverseDiagonal: The matrix's diagonal has at least one "
1196 "entry with nonpositive real part, on at least one process in the "
1197 "matrix's communicator. This is bad for Chebyshev." << std::endl;
1203 reciprocal_threshold (*D_rangeMap, minDiagVal_);
1204 return Teuchos::rcp_const_cast<
const V> (D_rangeMap);
1208 template<
class ScalarType,
class MV>
1210 Chebyshev<ScalarType, MV>::
1215 typedef Tpetra::Export<
typename MV::local_ordinal_type,
1216 typename MV::global_ordinal_type,
1217 typename MV::node_type> export_type;
1222 A_.
is_null (), std::logic_error,
"Ifpack2::Details::Chebyshev::"
1223 "makeRangeMapVector: The input matrix A is null. Please call setMatrix() "
1224 "with a nonnull input matrix before calling this method. This is probably "
1225 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1227 D.
is_null (), std::logic_error,
"Ifpack2::Details::Chebyshev::"
1228 "makeRangeMapVector: The input Vector D is null. This is probably "
1229 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1231 RCP<const map_type> sourceMap = D->getMap ();
1232 RCP<const map_type> rangeMap = A_->getRangeMap ();
1233 RCP<const map_type> rowMap = A_->getRowMap ();
1235 if (rangeMap->isSameAs (*sourceMap)) {
1241 RCP<const export_type> exporter;
1245 if (sourceMap->isSameAs (*rowMap)) {
1247 exporter = A_->getGraph ()->getExporter ();
1250 exporter =
rcp (
new export_type (sourceMap, rangeMap));
1253 if (exporter.is_null ()) {
1258 D_out->doExport (*D, *exporter, Tpetra::ADD);
1259 return Teuchos::rcp_const_cast<
const V> (D_out);
1265 template<
class ScalarType,
class MV>
1267 Chebyshev<ScalarType, MV>::
1270 using Teuchos::rcp_const_cast;
1271 return rcp_const_cast<V> (makeRangeMapVectorConst (rcp_const_cast<V> (D)));
1275 template<
class ScalarType,
class MV>
1277 Chebyshev<ScalarType, MV>::
1278 textbookApplyImpl (
const op_type& A,
1285 const V& D_inv)
const
1288 const ST myLambdaMin = lambdaMax / eigRatio;
1290 const ST zero = Teuchos::as<ST> (0);
1291 const ST one = Teuchos::as<ST> (1);
1292 const ST two = Teuchos::as<ST> (2);
1293 const ST d = (lambdaMax + myLambdaMin) / two;
1294 const ST c = (lambdaMax - myLambdaMin) / two;
1296 if (zeroStartingSolution_ && numIters > 0) {
1300 MV R (B.getMap (), B.getNumVectors (),
false);
1301 MV P (B.getMap (), B.getNumVectors (),
false);
1302 MV Z (B.getMap (), B.getNumVectors (),
false);
1304 for (
int i = 0; i < numIters; ++i) {
1305 computeResidual (R, B, A, X);
1306 solve (Z, D_inv, R);
1314 beta = alpha * (c/two) * (c/two);
1315 alpha = one / (d - beta);
1316 P.update (one, Z, beta);
1318 X.update (alpha, P, one);
1325 template<
class ScalarType,
class MV>
1327 Chebyshev<ScalarType, MV>::
1328 fourthKindApplyImpl (
const op_type& A,
1336 std::vector<ScalarType> betas(numIters, 1.0);
1337 if(chebyshevAlgorithm_ ==
"opt_fourth"){
1338 betas = optimalWeightsImpl<ScalarType>(numIters);
1341 const ST invEig = MT(1) / (lambdaMax * boostFactor_);
1353 if (! zeroStartingSolution_) {
1356 Tpetra::deep_copy (X4, X);
1358 if (ck_.is_null ()) {
1360 ck_ =
Teuchos::rcp (
new ChebyshevKernel<op_type> (A_op, ckUseNativeSpMV_));
1364 ck_->compute (Z, MT(4.0/3.0) * invEig, const_cast<V&> (D_inv),
1365 const_cast<MV&> (B), X4, STS::zero());
1368 X.update (betas[0], Z, STS::one());
1372 firstIterationWithZeroStartingSolution (Z, MT(4.0/3.0) * invEig, D_inv, B, X4);
1375 X.update (betas[0], Z, STS::zero());
1378 if (numIters > 1 && ck_.is_null ()) {
1380 ck_ =
Teuchos::rcp (
new ChebyshevKernel<op_type> (A_op, ckUseNativeSpMV_));
1383 for (
int i = 1; i < numIters; ++i) {
1384 const ST zScale = (2.0 * i - 1.0) / (2.0 * i + 3.0);
1385 const ST rScale = MT((8.0 * i + 4.0) / (2.0 * i + 3.0)) * invEig;
1389 ck_->compute (Z, rScale, const_cast<V&> (D_inv),
1390 const_cast<MV&> (B), (X4), zScale);
1393 X.update (betas[i], Z, STS::one());
1397 template<
class ScalarType,
class MV>
1398 typename Chebyshev<ScalarType, MV>::MT
1399 Chebyshev<ScalarType, MV>::maxNormInf (
const MV& X) {
1401 X.normInf (norms());
1402 return *std::max_element (norms.begin (), norms.end ());
1405 template<
class ScalarType,
class MV>
1407 Chebyshev<ScalarType, MV>::
1408 ifpackApplyImpl (
const op_type& A,
1418 #ifdef HAVE_IFPACK2_DEBUG
1419 const bool debug = debug_;
1421 const bool debug =
false;
1425 *out_ <<
" \\|B\\|_{\\infty} = " << maxNormInf (B) << endl;
1426 *out_ <<
" \\|X\\|_{\\infty} = " << maxNormInf (X) << endl;
1429 if (numIters <= 0) {
1432 const ST zero =
static_cast<ST
> (0.0);
1433 const ST one =
static_cast<ST
> (1.0);
1434 const ST two =
static_cast<ST
> (2.0);
1437 if (lambdaMin == one && lambdaMax == lambdaMin) {
1438 solve (X, D_inv, B);
1443 const ST alpha = lambdaMax / eigRatio;
1444 const ST beta = boostFactor_ * lambdaMax;
1445 const ST delta = two / (beta - alpha);
1446 const ST theta = (beta + alpha) / two;
1447 const ST s1 = theta * delta;
1450 *out_ <<
" alpha = " << alpha << endl
1451 <<
" beta = " << beta << endl
1452 <<
" delta = " << delta << endl
1453 <<
" theta = " << theta << endl
1454 <<
" s1 = " << s1 << endl;
1462 *out_ <<
" Iteration " << 1 <<
":" << endl
1463 <<
" - \\|D\\|_{\\infty} = " << D_->normInf () << endl;
1467 if (! zeroStartingSolution_) {
1470 if (ck_.is_null ()) {
1472 ck_ =
Teuchos::rcp (
new ChebyshevKernel<op_type> (A_op, ckUseNativeSpMV_));
1476 ck_->compute (W, one/theta, const_cast<V&> (D_inv),
1477 const_cast<MV&> (B), X, zero);
1481 firstIterationWithZeroStartingSolution (W, one/theta, D_inv, B, X);
1485 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf (W) << endl
1486 <<
" - \\|X\\|_{\\infty} = " << maxNormInf (X) << endl;
1489 if (numIters > 1 && ck_.is_null ()) {
1491 ck_ =
Teuchos::rcp (
new ChebyshevKernel<op_type> (A_op, ckUseNativeSpMV_));
1496 ST rhokp1, dtemp1, dtemp2;
1497 for (
int deg = 1; deg < numIters; ++deg) {
1499 *out_ <<
" Iteration " << deg+1 <<
":" << endl
1500 <<
" - \\|D\\|_{\\infty} = " << D_->normInf () << endl
1501 <<
" - \\|B\\|_{\\infty} = " << maxNormInf (B) << endl
1502 <<
" - \\|A\\|_{\\text{frob}} = " << A_->getFrobeniusNorm ()
1503 << endl <<
" - rhok = " << rhok << endl;
1506 rhokp1 = one / (two * s1 - rhok);
1507 dtemp1 = rhokp1 * rhok;
1508 dtemp2 = two * rhokp1 * delta;
1512 *out_ <<
" - dtemp1 = " << dtemp1 << endl
1513 <<
" - dtemp2 = " << dtemp2 << endl;
1518 ck_->compute (W, dtemp2, const_cast<V&> (D_inv),
1519 const_cast<MV&> (B), (X), dtemp1);
1522 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf (W) << endl
1523 <<
" - \\|X\\|_{\\infty} = " << maxNormInf (X) << endl;
1531 template<
class ScalarType,
class MV>
1532 typename Chebyshev<ScalarType, MV>::ST
1533 Chebyshev<ScalarType, MV>::
1534 cgMethodWithInitGuess (
const op_type& A,
1540 using MagnitudeType =
typename STS::magnitudeType;
1542 *out_ <<
" cgMethodWithInitGuess:" << endl;
1547 const ST one = STS::one();
1548 ST beta, betaOld = one, pAp, pApOld = one, alpha, rHz, rHzOld, rHzOld2 = one, lambdaMax;
1553 offdiag.
resize(numIters-1);
1555 p =
rcp(
new V(A.getRangeMap ()));
1556 z =
rcp(
new V(A.getRangeMap ()));
1557 Ap =
rcp(
new V(A.getRangeMap ()));
1560 solve (*p, D_inv, r);
1563 for (
int iter = 0; iter < numIters; ++iter) {
1565 *out_ <<
" Iteration " << iter << endl;
1570 r.update (-alpha, *Ap, one);
1572 solve (*z, D_inv, r);
1574 beta = rHz / rHzOld;
1575 p->update (one, *z, beta);
1577 diag[iter] = STS::real((betaOld*betaOld * pApOld + pAp) / rHzOld);
1578 offdiag[iter-1] = -STS::real((betaOld * pApOld / (sqrt(rHzOld * rHzOld2))));
1580 *out_ <<
" diag[" << iter <<
"] = " << diag[iter] << endl;
1581 *out_ <<
" offdiag["<< iter-1 <<
"] = " << offdiag[iter-1] << endl;
1582 *out_ <<
" rHz = "<<rHz <<endl;
1583 *out_ <<
" alpha = "<<alpha<<endl;
1584 *out_ <<
" beta = "<<beta<<endl;
1587 diag[iter] = STS::real(pAp/rHzOld);
1589 *out_ <<
" diag[" << iter <<
"] = " << diag[iter] << endl;
1590 *out_ <<
" rHz = "<<rHz <<endl;
1591 *out_ <<
" alpha = "<<alpha<<endl;
1592 *out_ <<
" beta = "<<beta<<endl;
1600 lambdaMax = LapackHelper<ST>::tri_diag_spectral_radius(diag, offdiag);
1606 template<
class ScalarType,
class MV>
1607 typename Chebyshev<ScalarType, MV>::ST
1608 Chebyshev<ScalarType, MV>::
1609 cgMethod (
const op_type& A,
const V& D_inv,
const int numIters)
1614 *out_ <<
"cgMethod:" << endl;
1618 if (eigVector_.is_null()) {
1619 r =
rcp(
new V(A.getDomainMap ()));
1620 if (eigKeepVectors_)
1623 Details::computeInitialGuessForCG (D_inv,*r);
1627 ST lambdaMax = cgMethodWithInitGuess (A, D_inv, numIters, *r);
1632 template<
class ScalarType,
class MV>
1638 template<
class ScalarType,
class MV>
1646 template<
class ScalarType,
class MV>
1655 const size_t B_numVecs = B.getNumVectors ();
1656 if (W_.is_null () || W_->getNumVectors () != B_numVecs) {
1657 W_ =
Teuchos::rcp (
new MV (B.getMap (), B_numVecs,
false));
1662 template<
class ScalarType,
class MV>
1664 Chebyshev<ScalarType, MV>::
1665 makeSecondTempMultiVector (
const MV& B)
1671 const size_t B_numVecs = B.getNumVectors ();
1672 if (W2_.is_null () || W2_->getNumVectors () != B_numVecs) {
1673 W2_ =
Teuchos::rcp (
new MV (B.getMap (), B_numVecs,
false));
1679 template<
class ScalarType,
class MV>
1683 std::ostringstream oss;
1686 oss <<
"\"Ifpack2::Details::Chebyshev\":"
1688 <<
"degree: " << numIters_
1689 <<
", lambdaMax: " << lambdaMaxForApply_
1690 <<
", alpha: " << eigRatioForApply_
1691 <<
", lambdaMin: " << lambdaMinForApply_
1692 <<
", boost factor: " << boostFactor_
1693 <<
", algorithm: " << chebyshevAlgorithm_;
1694 if (!userInvDiag_.is_null())
1695 oss <<
", diagonal: user-supplied";
1700 template<
class ScalarType,
class MV>
1731 myRank = A_->getComm ()->getRank ();
1736 out <<
"\"Ifpack2::Details::Chebyshev\":" << endl;
1742 out <<
"degree: " << numIters_ << endl
1743 <<
"lambdaMax: " << lambdaMaxForApply_ << endl
1744 <<
"alpha: " << eigRatioForApply_ << endl
1745 <<
"lambdaMin: " << lambdaMinForApply_ << endl
1746 <<
"boost factor: " << boostFactor_ << endl;
1754 out <<
"Template parameters:" << endl;
1757 out <<
"ScalarType: " << TypeNameTraits<ScalarType>::name () << endl
1758 <<
"MV: " << TypeNameTraits<MV>::name () << endl;
1764 out <<
"Computed parameters:" << endl;
1776 if (D_.is_null ()) {
1778 out <<
"unset" << endl;
1783 out <<
"set" << endl;
1792 D_->describe (out, vl);
1797 out <<
"W_: " << (W_.is_null () ?
"unset" :
"set") << endl
1798 <<
"computedLambdaMax_: " << computedLambdaMax_ << endl
1799 <<
"computedLambdaMin_: " << computedLambdaMin_ << endl
1800 <<
"lambdaMaxForApply_: " << lambdaMaxForApply_ << endl
1801 <<
"lambdaMinForApply_: " << lambdaMinForApply_ << endl
1802 <<
"eigRatioForApply_: " << eigRatioForApply_ << endl;
1807 out <<
"User parameters:" << endl;
1813 out <<
"userInvDiag_: ";
1814 if (userInvDiag_.is_null ()) {
1815 out <<
"unset" << endl;
1818 out <<
"set" << endl;
1824 userInvDiag_->describe (out, vl);
1827 out <<
"userLambdaMax_: " << userLambdaMax_ << endl
1828 <<
"userLambdaMin_: " << userLambdaMin_ << endl
1829 <<
"userEigRatio_: " << userEigRatio_ << endl
1830 <<
"numIters_: " << numIters_ << endl
1831 <<
"eigMaxIters_: " << eigMaxIters_ << endl
1832 <<
"eigRelTolerance_: " << eigRelTolerance_ << endl
1833 <<
"eigNormalizationFreq_: " << eigNormalizationFreq_ << endl
1834 <<
"zeroStartingSolution_: " << zeroStartingSolution_ << endl
1835 <<
"assumeMatrixUnchanged_: " << assumeMatrixUnchanged_ << endl
1836 <<
"chebyshevAlgorithm_: " << chebyshevAlgorithm_ << endl
1837 <<
"computeMaxResNorm_: " << computeMaxResNorm_ << endl;
1845 #define IFPACK2_DETAILS_CHEBYSHEV_INSTANT(S,LO,GO,N) \
1846 template class Ifpack2::Details::Chebyshev< S, Tpetra::MultiVector<S, LO, GO, N> >;
1848 #endif // IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP
void setParameters(Teuchos::ParameterList &plist)
Set (or reset) parameters.
Definition: Ifpack2_Details_Chebyshev_def.hpp:349
Definition of power methods.
MT apply(const MV &B, MV &X)
Solve Ax=b for x with Chebyshev iteration with left diagonal scaling.
Definition: Ifpack2_Details_Chebyshev_def.hpp:1010
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print a description of the Chebyshev solver to out.
Definition: Ifpack2_Details_Chebyshev_def.hpp:1703
T & get(const std::string &name, T def_value)
void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Set the matrix.
Definition: Ifpack2_Details_Chebyshev_def.hpp:776
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< const row_matrix_type > getMatrix() const
Get the matrix given to the constructor.
Definition: Ifpack2_Details_Chebyshev_def.hpp:1634
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void PTEQR(const char &COMPZ, const OrdinalType &n, MagnitudeType *D, MagnitudeType *E, ScalarType *Z, const OrdinalType &ldz, MagnitudeType *WORK, OrdinalType *info) const
Chebyshev(Teuchos::RCP< const row_matrix_type > A)
Definition: Ifpack2_Details_Chebyshev_def.hpp:283
void resize(const size_type n, const T &val=T())
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Diagonally scaled Chebyshev iteration for Tpetra sparse matrices.
Definition: Ifpack2_Chebyshev_decl.hpp:165
void print(std::ostream &out)
Print instance data to the given output stream.
Definition: Ifpack2_Details_Chebyshev_def.hpp:1066
STS::magnitudeType MT
The type of the absolute value of a ScalarType.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:85
ScalarType ST
The type of entries in the matrix and vectors.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:81
Left-scaled Chebyshev iteration.
Definition: Ifpack2_Details_Chebyshev_decl.hpp:75
Declaration of Chebyshev implementation.
std::string description() const
A single-line description of the Chebyshev solver.
Definition: Ifpack2_Details_Chebyshev_def.hpp:1682
TypeTo as(const TypeFrom &t)
bool isType(const std::string &name) const
Definition of Chebyshev implementation.
bool hasTransposeApply() const
Whether it's possible to apply the transpose of this operator.
Definition: Ifpack2_Details_Chebyshev_def.hpp:1641
void compute()
(Re)compute the left scaling D_inv, and estimate min and max eigenvalues of D_inv * A...
Definition: Ifpack2_Details_Chebyshev_def.hpp:817
basic_oblackholestream< char, std::char_traits< char > > oblackholestream