10 #ifndef IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP
11 #define IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP
24 #include "Ifpack2_Details_ChebyshevKernel.hpp"
25 #if KOKKOS_VERSION >= 40799
26 #include "KokkosKernels_ArithTraits.hpp"
28 #include "Kokkos_ArithTraits.hpp"
30 #include "Teuchos_FancyOStream.hpp"
31 #include "Teuchos_oblackholestream.hpp"
32 #include "Tpetra_Details_residual.hpp"
34 #include "Ifpack2_Details_LapackSupportsScalar.hpp"
44 const char computeBeforeApplyReminder[] =
45 "This means one of the following:\n"
46 " - you have not yet called compute() on this instance, or \n"
47 " - you didn't call compute() after calling setParameters().\n\n"
48 "After creating an Ifpack2::Chebyshev instance,\n"
49 "you must _always_ call compute() at least once before calling apply().\n"
50 "After calling compute() once, you do not need to call it again,\n"
51 "unless the matrix has changed or you have changed parameters\n"
52 "(by calling setParameters()).";
58 template <
class XV,
class SizeType =
typename XV::
size_type>
59 struct V_ReciprocalThresholdSelfFunctor {
60 typedef typename XV::execution_space execution_space;
61 typedef typename XV::non_const_value_type value_type;
62 typedef SizeType size_type;
63 #if KOKKOS_VERSION >= 40799
64 typedef KokkosKernels::ArithTraits<value_type> KAT;
66 typedef Kokkos::ArithTraits<value_type> KAT;
68 typedef typename KAT::mag_type mag_type;
71 const value_type minVal_;
72 const mag_type minValMag_;
74 V_ReciprocalThresholdSelfFunctor(
const XV& X,
75 const value_type& min_val)
78 , minValMag_(KAT::abs(min_val)) {}
80 KOKKOS_INLINE_FUNCTION
81 void operator()(
const size_type& i)
const {
82 const mag_type X_i_abs = KAT::abs(X_[i]);
84 if (X_i_abs < minValMag_) {
87 X_[i] = KAT::one() / X_[i];
92 template <
class XV,
class SizeType =
typename XV::
size_type>
93 struct LocalReciprocalThreshold {
96 const typename XV::non_const_value_type& minVal) {
97 typedef typename XV::execution_space execution_space;
98 Kokkos::RangePolicy<execution_space, SizeType> policy(0, X.extent(0));
99 V_ReciprocalThresholdSelfFunctor<XV, SizeType> op(X, minVal);
100 Kokkos::parallel_for(policy, op);
104 template <
class TpetraVectorType,
105 const bool classic = TpetraVectorType::node_type::classic>
106 struct GlobalReciprocalThreshold {};
108 template <
class TpetraVectorType>
109 struct GlobalReciprocalThreshold<TpetraVectorType, true> {
111 compute(TpetraVectorType& V,
112 const typename TpetraVectorType::scalar_type& min_val) {
113 typedef typename TpetraVectorType::scalar_type scalar_type;
114 typedef typename TpetraVectorType::mag_type mag_type;
115 #if KOKKOS_VERSION >= 40799
116 typedef KokkosKernels::ArithTraits<scalar_type> STS;
118 typedef Kokkos::ArithTraits<scalar_type> STS;
121 const scalar_type ONE = STS::one();
122 const mag_type min_val_abs = STS::abs(min_val);
125 const size_t lclNumRows = V.getLocalLength();
127 for (
size_t i = 0; i < lclNumRows; ++i) {
128 const scalar_type V_0i = V_0[i];
129 if (STS::abs(V_0i) < min_val_abs) {
138 template <
class TpetraVectorType>
139 struct GlobalReciprocalThreshold<TpetraVectorType, false> {
141 compute(TpetraVectorType& X,
142 const typename TpetraVectorType::scalar_type& minVal) {
143 typedef typename TpetraVectorType::impl_scalar_type value_type;
145 const value_type minValS =
static_cast<value_type
>(minVal);
146 auto X_0 = Kokkos::subview(X.getLocalViewDevice(Tpetra::Access::ReadWrite),
148 LocalReciprocalThreshold<decltype(X_0)>::compute(X_0, minValS);
153 template <
typename S,
typename L,
typename G,
typename N>
154 void reciprocal_threshold(Tpetra::Vector<S, L, G, N>& V,
const S& minVal) {
155 GlobalReciprocalThreshold<Tpetra::Vector<S, L, G, N>>::compute(V, minVal);
158 template <class ScalarType, const bool lapackSupportsScalarType = LapackSupportsScalar<ScalarType>::value>
159 struct LapackHelper {
163 throw std::runtime_error(
"LAPACK does not support the scalar type.");
168 void computeInitialGuessForCG(
const V& diagonal, V& x) {
169 using device_type =
typename V::node_type::device_type;
170 using range_policy = Kokkos::RangePolicy<typename device_type::execution_space>;
177 size_t N = x.getLocalLength();
178 auto d_view = diagonal.template getLocalView<device_type>(Tpetra::Access::ReadOnly);
179 auto x_view = x.template getLocalView<device_type>(Tpetra::Access::ReadWrite);
184 Kokkos::parallel_for(
185 "computeInitialGuessforCG::zero_bcs", range_policy(0, N), KOKKOS_LAMBDA(
const size_t& i) {
186 if (d_view(i, 0) == ONE)
191 template <
class ScalarType>
192 struct LapackHelper<ScalarType, true> {
197 using MagnitudeType =
typename STS::magnitudeType;
199 const int N = diag.size();
200 ScalarType scalar_dummy;
201 std::vector<MagnitudeType> mag_dummy(4 * N);
205 ScalarType lambdaMax = STS::one();
208 lapack.
PTEQR(char_N, N, diag.getRawPtr(), offdiag.getRawPtr(),
209 &scalar_dummy, 1, &mag_dummy[0], &info);
211 "Ifpack2::Details::LapackHelper::tri_diag_spectral_radius:"
212 "LAPACK's _PTEQR failed with info = "
213 << info <<
" < 0. This suggests there might be a bug in the way Ifpack2 "
214 "is calling LAPACK. Please report this to the Ifpack2 developers.");
216 lambdaMax = Teuchos::as<ScalarType>(diag[0]);
222 template <
class ScalarType,
class MV>
223 void Chebyshev<ScalarType, MV>::checkInputMatrix()
const {
225 !A_.
is_null() && A_->getGlobalNumRows() != A_->getGlobalNumCols(),
226 std::invalid_argument,
227 "Ifpack2::Chebyshev: The input matrix A must be square. "
229 << A_->getGlobalNumRows() <<
" rows and "
230 << A_->getGlobalNumCols() <<
" columns.");
242 !domainMap->isSameAs(*rangeMap), std::invalid_argument,
243 "Ifpack2::Chebyshev: The domain Map and range Map of the matrix must be "
244 "the same (in the sense of isSameAs())."
247 "for this in debug mode.");
251 template <
class ScalarType,
class MV>
252 void Chebyshev<ScalarType, MV>::
253 checkConstructorInput()
const {
257 if (STS::isComplex) {
259 "Ifpack2::Chebyshev: This class' implementation "
260 "of Chebyshev iteration only works for real-valued, symmetric positive "
261 "definite matrices. However, you instantiated this class for ScalarType"
264 "complex-valued type. While this may be algorithmically correct if all "
265 "of the complex numbers in the matrix have zero imaginary part, we "
266 "forbid using complex ScalarType altogether in order to remind you of "
267 "the limitations of our implementation (and of the algorithm itself).");
273 template <
class ScalarType,
class MV>
277 , savedDiagOffsets_(false)
278 , computedLambdaMax_(STS::nan())
279 , computedLambdaMin_(STS::nan())
280 , lambdaMaxForApply_(STS::nan())
281 , lambdaMinForApply_(STS::nan())
282 , eigRatioForApply_(STS::nan())
283 , userLambdaMax_(STS::nan())
284 , userLambdaMin_(STS::nan())
285 , userEigRatio_(Teuchos::
as<
ST>(30))
286 , minDiagVal_(STS::eps())
289 , eigRelTolerance_(Teuchos::ScalarTraits<
MT>::zero())
290 , eigKeepVectors_(false)
291 , eigenAnalysisType_(
"power method")
292 , eigNormalizationFreq_(1)
293 , zeroStartingSolution_(true)
294 , assumeMatrixUnchanged_(false)
295 , chebyshevAlgorithm_(
"first")
296 , computeMaxResNorm_(false)
297 , computeSpectralRadius_(true)
298 , ckUseNativeSpMV_(MV::node_type::is_gpu)
299 , preAllocateTempVector_(true)
301 checkConstructorInput();
304 template <
class ScalarType,
class MV>
309 , savedDiagOffsets_(false)
310 , computedLambdaMax_(STS::nan())
311 , computedLambdaMin_(STS::nan())
312 , lambdaMaxForApply_(STS::nan())
313 , boostFactor_(static_cast<
MT>(1.1))
314 , lambdaMinForApply_(STS::nan())
315 , eigRatioForApply_(STS::nan())
316 , userLambdaMax_(STS::nan())
317 , userLambdaMin_(STS::nan())
318 , userEigRatio_(Teuchos::
as<
ST>(30))
319 , minDiagVal_(STS::eps())
322 , eigRelTolerance_(Teuchos::ScalarTraits<
MT>::zero())
323 , eigKeepVectors_(false)
324 , eigenAnalysisType_(
"power method")
325 , eigNormalizationFreq_(1)
326 , zeroStartingSolution_(true)
327 , assumeMatrixUnchanged_(false)
328 , chebyshevAlgorithm_(
"first")
329 , computeMaxResNorm_(false)
330 , computeSpectralRadius_(true)
331 , ckUseNativeSpMV_(MV::node_type::is_gpu)
332 , preAllocateTempVector_(true)
334 checkConstructorInput();
338 template <
class ScalarType,
class MV>
343 using Teuchos::rcp_const_cast;
355 const ST defaultLambdaMax = STS::nan();
356 const ST defaultLambdaMin = STS::nan();
363 const ST defaultEigRatio = Teuchos::as<ST>(30);
364 const MT defaultBoostFactor =
static_cast<MT>(1.1);
365 const ST defaultMinDiagVal = STS::eps();
366 const int defaultNumIters = 1;
367 const int defaultEigMaxIters = 10;
369 const bool defaultEigKeepVectors =
false;
370 const int defaultEigNormalizationFreq = 1;
371 const bool defaultZeroStartingSolution =
true;
372 const bool defaultAssumeMatrixUnchanged =
false;
373 const std::string defaultChebyshevAlgorithm =
"first";
374 const bool defaultComputeMaxResNorm =
false;
375 const bool defaultComputeSpectralRadius =
true;
376 const bool defaultCkUseNativeSpMV = MV::node_type::is_gpu;
377 const bool defaultPreAllocateTempVector =
true;
378 const bool defaultDebug =
false;
384 RCP<const V> userInvDiagCopy;
385 ST lambdaMax = defaultLambdaMax;
386 ST lambdaMin = defaultLambdaMin;
387 ST eigRatio = defaultEigRatio;
388 MT boostFactor = defaultBoostFactor;
389 ST minDiagVal = defaultMinDiagVal;
390 int numIters = defaultNumIters;
391 int eigMaxIters = defaultEigMaxIters;
392 MT eigRelTolerance = defaultEigRelTolerance;
393 bool eigKeepVectors = defaultEigKeepVectors;
394 int eigNormalizationFreq = defaultEigNormalizationFreq;
395 bool zeroStartingSolution = defaultZeroStartingSolution;
396 bool assumeMatrixUnchanged = defaultAssumeMatrixUnchanged;
397 std::string chebyshevAlgorithm = defaultChebyshevAlgorithm;
398 bool computeMaxResNorm = defaultComputeMaxResNorm;
399 bool computeSpectralRadius = defaultComputeSpectralRadius;
400 bool ckUseNativeSpMV = defaultCkUseNativeSpMV;
401 bool preAllocateTempVector = defaultPreAllocateTempVector;
402 bool debug = defaultDebug;
409 if (plist.
isType<
bool>(
"debug")) {
410 debug = plist.
get<
bool>(
"debug");
411 }
else if (plist.
isType<
int>(
"debug")) {
412 const int debugInt = plist.
get<
bool>(
"debug");
413 debug = debugInt != 0;
426 const char opInvDiagLabel[] =
"chebyshev: operator inv diagonal";
429 RCP<const V> userInvDiag;
431 if (plist.
isType<
const V*>(opInvDiagLabel)) {
432 const V* rawUserInvDiag =
433 plist.
get<
const V*>(opInvDiagLabel);
435 userInvDiag =
rcp(rawUserInvDiag,
false);
436 }
else if (plist.
isType<
const V*>(opInvDiagLabel)) {
437 V* rawUserInvDiag = plist.
get<V*>(opInvDiagLabel);
439 userInvDiag =
rcp(const_cast<const V*>(rawUserInvDiag),
false);
440 }
else if (plist.
isType<RCP<const V>>(opInvDiagLabel)) {
441 userInvDiag = plist.
get<RCP<const V>>(opInvDiagLabel);
442 }
else if (plist.
isType<RCP<V>>(opInvDiagLabel)) {
443 RCP<V> userInvDiagNonConst =
444 plist.
get<RCP<V>>(opInvDiagLabel);
445 userInvDiag = rcp_const_cast<
const V>(userInvDiagNonConst);
446 }
else if (plist.
isType<
const V>(opInvDiagLabel)) {
447 const V& userInvDiagRef = plist.
get<
const V>(opInvDiagLabel);
449 userInvDiag = userInvDiagCopy;
450 }
else if (plist.
isType<V>(opInvDiagLabel)) {
451 V& userInvDiagNonConstRef = plist.
get<V>(opInvDiagLabel);
452 const V& userInvDiagRef =
const_cast<const V&
>(userInvDiagNonConstRef);
454 userInvDiag = userInvDiagCopy;
464 if (!userInvDiag.is_null() && userInvDiagCopy.is_null()) {
475 if (plist.
isParameter(
"chebyshev: use native spmv"))
476 ckUseNativeSpMV = plist.
get(
"chebyshev: use native spmv", ckUseNativeSpMV);
479 if (plist.
isParameter(
"chebyshev: pre-allocate temp vector"))
480 preAllocateTempVector = plist.
get(
"chebyshev: pre-allocate temp vector", preAllocateTempVector);
485 if (plist.
isParameter(
"chebyshev: max eigenvalue")) {
486 if (plist.
isType<
double>(
"chebyshev: max eigenvalue"))
487 lambdaMax = plist.
get<
double>(
"chebyshev: max eigenvalue");
489 lambdaMax = plist.
get<
ST>(
"chebyshev: max eigenvalue");
491 STS::isnaninf(lambdaMax), std::invalid_argument,
492 "Ifpack2::Chebyshev::setParameters: \"chebyshev: max eigenvalue\" "
493 "parameter is NaN or Inf. This parameter is optional, but if you "
494 "choose to supply it, it must have a finite value.");
496 if (plist.
isParameter(
"chebyshev: min eigenvalue")) {
497 if (plist.
isType<
double>(
"chebyshev: min eigenvalue"))
498 lambdaMin = plist.
get<
double>(
"chebyshev: min eigenvalue");
500 lambdaMin = plist.
get<
ST>(
"chebyshev: min eigenvalue");
502 STS::isnaninf(lambdaMin), std::invalid_argument,
503 "Ifpack2::Chebyshev::setParameters: \"chebyshev: min eigenvalue\" "
504 "parameter is NaN or Inf. This parameter is optional, but if you "
505 "choose to supply it, it must have a finite value.");
509 if (plist.
isParameter(
"smoother: Chebyshev alpha")) {
510 if (plist.
isType<
double>(
"smoother: Chebyshev alpha"))
511 eigRatio = plist.
get<
double>(
"smoother: Chebyshev alpha");
513 eigRatio = plist.
get<
ST>(
"smoother: Chebyshev alpha");
516 eigRatio = plist.
get(
"chebyshev: ratio eigenvalue", eigRatio);
518 STS::isnaninf(eigRatio), std::invalid_argument,
519 "Ifpack2::Chebyshev::setParameters: \"chebyshev: ratio eigenvalue\" "
520 "parameter (also called \"smoother: Chebyshev alpha\") is NaN or Inf. "
521 "This parameter is optional, but if you choose to supply it, it must have "
529 STS::real(eigRatio) < STS::real(STS::one()),
530 std::invalid_argument,
531 "Ifpack2::Chebyshev::setParameters: \"chebyshev: ratio eigenvalue\""
532 "parameter (also called \"smoother: Chebyshev alpha\") must be >= 1, "
533 "but you supplied the value "
539 const char paramName[] =
"chebyshev: boost factor";
543 boostFactor = plist.
get<
MT>(paramName);
544 }
else if (!std::is_same<double, MT>::value &&
545 plist.
isType<
double>(paramName)) {
546 const double dblBF = plist.
get<
double>(paramName);
547 boostFactor =
static_cast<MT>(dblBF);
550 "Ifpack2::Chebyshev::setParameters: \"chebyshev: boost factor\""
551 "parameter must have type magnitude_type (MT) or double.");
560 plist.
set(paramName, defaultBoostFactor);
563 "Ifpack2::Chebyshev::setParameters: \"" << paramName <<
"\" parameter "
564 "must be >= 1, but you supplied the value "
565 << boostFactor <<
".");
569 minDiagVal = plist.
get(
"chebyshev: min diagonal value", minDiagVal);
571 STS::isnaninf(minDiagVal), std::invalid_argument,
572 "Ifpack2::Chebyshev::setParameters: \"chebyshev: min diagonal value\" "
573 "parameter is NaN or Inf. This parameter is optional, but if you choose "
574 "to supply it, it must have a finite value.");
578 numIters = plist.
get<
int>(
"smoother: sweeps");
581 numIters = plist.
get<
int>(
"relaxation: sweeps");
583 numIters = plist.
get(
"chebyshev: degree", numIters);
585 numIters < 0, std::invalid_argument,
586 "Ifpack2::Chebyshev::setParameters: \"chebyshev: degree\" parameter (also "
587 "called \"smoother: sweeps\" or \"relaxation: sweeps\") must be a "
588 "nonnegative integer. You gave a value of "
592 if (plist.
isParameter(
"eigen-analysis: iterations")) {
593 eigMaxIters = plist.
get<
int>(
"eigen-analysis: iterations");
595 eigMaxIters = plist.
get(
"chebyshev: eigenvalue max iterations", eigMaxIters);
597 eigMaxIters < 0, std::invalid_argument,
598 "Ifpack2::Chebyshev::setParameters: \"chebyshev: eigenvalue max iterations"
599 "\" parameter (also called \"eigen-analysis: iterations\") must be a "
600 "nonnegative integer. You gave a value of "
601 << eigMaxIters <<
".");
603 if (plist.
isType<
double>(
"chebyshev: eigenvalue relative tolerance"))
604 eigRelTolerance = Teuchos::as<MT>(plist.
get<
double>(
"chebyshev: eigenvalue relative tolerance"));
605 else if (plist.
isType<
MT>(
"chebyshev: eigenvalue relative tolerance"))
606 eigRelTolerance = plist.
get<
MT>(
"chebyshev: eigenvalue relative tolerance");
607 else if (plist.
isType<
ST>(
"chebyshev: eigenvalue relative tolerance"))
610 eigKeepVectors = plist.
get(
"chebyshev: eigenvalue keep vectors", eigKeepVectors);
612 eigNormalizationFreq = plist.
get(
"chebyshev: eigenvalue normalization frequency", eigNormalizationFreq);
614 eigNormalizationFreq < 0, std::invalid_argument,
615 "Ifpack2::Chebyshev::setParameters: \"chebyshev: eigenvalue normalization frequency"
616 "\" parameter must be a "
617 "nonnegative integer. You gave a value of "
618 << eigNormalizationFreq <<
".")
620 zeroStartingSolution = plist.
get(
"chebyshev: zero starting solution",
621 zeroStartingSolution);
622 assumeMatrixUnchanged = plist.
get(
"chebyshev: assume matrix does not change",
623 assumeMatrixUnchanged);
628 chebyshevAlgorithm = plist.
get<std::string>(
"chebyshev: algorithm");
630 chebyshevAlgorithm !=
"first" &&
631 chebyshevAlgorithm !=
"textbook" &&
632 chebyshevAlgorithm !=
"fourth" &&
633 chebyshevAlgorithm !=
"opt_fourth",
634 std::invalid_argument,
635 "Ifpack2::Chebyshev: Ifpack2 only supports \"first\", \"textbook\", \"fourth\", and \"opt_fourth\", for \"chebyshev: algorithm\".");
638 #ifdef IFPACK2_ENABLE_DEPRECATED_CODE
642 if (plist.
isParameter(
"chebyshev: textbook algorithm")) {
643 const bool textbookAlgorithm = plist.
get<
bool>(
"chebyshev: textbook algorithm");
644 if (textbookAlgorithm) {
645 chebyshevAlgorithm =
"textbook";
647 chebyshevAlgorithm =
"first";
653 if (plist.
isParameter(
"chebyshev: compute max residual norm")) {
654 computeMaxResNorm = plist.
get<
bool>(
"chebyshev: compute max residual norm");
656 if (plist.
isParameter(
"chebyshev: compute spectral radius")) {
657 computeSpectralRadius = plist.
get<
bool>(
"chebyshev: compute spectral radius");
664 !plist.
get<
bool>(
"chebyshev: use block mode"),
665 std::invalid_argument,
666 "Ifpack2::Chebyshev requires that if you set \"chebyshev: use "
667 "block mode\" at all, you must set it to false. "
668 "Ifpack2::Chebyshev does not implement Ifpack's block mode.");
670 !plist.
get<
bool>(
"chebyshev: solve normal equations"),
671 std::invalid_argument,
672 "Ifpack2::Chebyshev does not and will never implement the Ifpack "
673 "parameter \"chebyshev: solve normal equations\". If you want to "
674 "solve the normal equations, construct a Tpetra::Operator that "
675 "implements A^* A, and use Chebyshev to solve A^* A x = A^* b.");
683 std::string eigenAnalysisType(
"power-method");
685 eigenAnalysisType = plist.
get<std::string>(
"eigen-analysis: type");
687 eigenAnalysisType !=
"power-method" &&
688 eigenAnalysisType !=
"power method" &&
689 eigenAnalysisType !=
"cg",
690 std::invalid_argument,
691 "Ifpack2::Chebyshev: Ifpack2 only supports \"power method\" and \"cg\" for \"eigen-analysis: type\".");
695 userInvDiag_ = userInvDiagCopy;
696 userLambdaMax_ = lambdaMax;
697 userLambdaMin_ = lambdaMin;
698 userEigRatio_ = eigRatio;
699 boostFactor_ =
static_cast<MT>(boostFactor);
700 minDiagVal_ = minDiagVal;
701 numIters_ = numIters;
702 eigMaxIters_ = eigMaxIters;
703 eigRelTolerance_ = eigRelTolerance;
704 eigKeepVectors_ = eigKeepVectors;
705 eigNormalizationFreq_ = eigNormalizationFreq;
706 eigenAnalysisType_ = eigenAnalysisType;
707 zeroStartingSolution_ = zeroStartingSolution;
708 assumeMatrixUnchanged_ = assumeMatrixUnchanged;
709 chebyshevAlgorithm_ = chebyshevAlgorithm;
710 computeMaxResNorm_ = computeMaxResNorm;
711 computeSpectralRadius_ = computeSpectralRadius;
712 ckUseNativeSpMV_ = ckUseNativeSpMV;
713 preAllocateTempVector_ = preAllocateTempVector;
724 myRank = A_->getComm()->getRank();
728 out_ = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cerr));
732 out_ = Teuchos::getFancyOStream(blackHole);
736 out_ = Teuchos::null;
740 template <
class ScalarType,
class MV>
744 diagOffsets_ = offsets_type();
745 savedDiagOffsets_ =
false;
747 computedLambdaMax_ = STS::nan();
748 computedLambdaMin_ = STS::nan();
749 eigVector_ = Teuchos::null;
750 eigVector2_ = Teuchos::null;
753 template <
class ScalarType,
class MV>
757 if (!assumeMatrixUnchanged_) {
774 myRank = A->getComm()->getRank();
778 out_ = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cerr));
781 out_ = Teuchos::getFancyOStream(blackHole);
785 out_ = Teuchos::null;
790 template <
class ScalarType,
class MV>
797 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
798 typename MV::local_ordinal_type,
799 typename MV::global_ordinal_type,
800 typename MV::node_type>
804 A_.
is_null(), std::runtime_error,
805 "Ifpack2::Chebyshev::compute: The input "
806 "matrix A is null. Please call setMatrix() with a nonnull input matrix "
807 "before calling this method.");
822 if (userInvDiag_.is_null()) {
824 Teuchos::rcp_dynamic_cast<
const crs_matrix_type>(A_);
826 if (!A_crsMat.
is_null() && A_crsMat->isFillComplete()) {
828 const size_t lclNumRows = A_crsMat->getLocalNumRows();
829 if (diagOffsets_.extent(0) < lclNumRows) {
830 diagOffsets_ = offsets_type();
831 diagOffsets_ = offsets_type(
"offsets", lclNumRows);
833 A_crsMat->getCrsGraph()->getLocalDiagOffsets(diagOffsets_);
834 savedDiagOffsets_ =
true;
835 D_ = makeInverseDiagonal(*A_,
true);
837 D_ = makeInverseDiagonal(*A_);
839 }
else if (!assumeMatrixUnchanged_) {
840 if (!A_crsMat.
is_null() && A_crsMat->isFillComplete()) {
843 if (!savedDiagOffsets_) {
844 const size_t lclNumRows = A_crsMat->getLocalNumRows();
845 if (diagOffsets_.extent(0) < lclNumRows) {
846 diagOffsets_ = offsets_type();
847 diagOffsets_ = offsets_type(
"offsets", lclNumRows);
849 A_crsMat->getCrsGraph()->getLocalDiagOffsets(diagOffsets_);
850 savedDiagOffsets_ =
true;
853 D_ = makeInverseDiagonal(*A_,
true);
855 D_ = makeInverseDiagonal(*A_);
859 D_ = makeRangeMapVectorConst(userInvDiag_);
863 const bool computedEigenvalueEstimates =
864 STS::isnaninf(computedLambdaMax_) || STS::isnaninf(computedLambdaMin_);
874 if (!assumeMatrixUnchanged_ ||
875 (!computedEigenvalueEstimates && STS::isnaninf(userLambdaMax_))) {
876 ST computedLambdaMax;
877 if ((eigenAnalysisType_ ==
"power method") || (eigenAnalysisType_ ==
"power-method")) {
879 if (eigVector_.is_null()) {
883 PowerMethod::computeInitialGuessForPowerMethod(*x,
false);
888 if (eigVector2_.is_null()) {
889 y =
rcp(
new V(A_->getRangeMap()));
896 computedLambdaMax = PowerMethod::powerMethodWithInitGuess(*A_, *D_, eigMaxIters_, x, y,
897 eigRelTolerance_, eigNormalizationFreq_, stream,
898 computeSpectralRadius_);
900 computedLambdaMax = cgMethod(*A_, *D_, eigMaxIters_);
903 STS::isnaninf(computedLambdaMax),
905 "Ifpack2::Chebyshev::compute: Estimation of the max eigenvalue "
906 "of D^{-1} A failed, by producing Inf or NaN. This probably means that "
907 "the matrix contains Inf or NaN values, or that it is badly scaled.");
909 STS::isnaninf(userEigRatio_),
911 "Ifpack2::Chebyshev::compute: userEigRatio_ is Inf or NaN."
913 <<
"This should be impossible." << endl
914 <<
"Please report this bug to the Ifpack2 developers.");
920 const ST computedLambdaMin = computedLambdaMax / userEigRatio_;
923 computedLambdaMax_ = computedLambdaMax;
924 computedLambdaMin_ = computedLambdaMin;
927 STS::isnaninf(userLambdaMax_) && STS::isnaninf(computedLambdaMax_),
929 "Ifpack2::Chebyshev::compute: " << endl
930 <<
"Both userLambdaMax_ and computedLambdaMax_ are Inf or NaN."
932 <<
"This should be impossible." << endl
933 <<
"Please report this bug to the Ifpack2 developers.");
941 lambdaMaxForApply_ = STS::isnaninf(userLambdaMax_) ? computedLambdaMax_ : userLambdaMax_;
954 lambdaMinForApply_ = lambdaMaxForApply_ / userEigRatio_;
955 eigRatioForApply_ = userEigRatio_;
957 if (chebyshevAlgorithm_ ==
"first") {
960 const ST one = Teuchos::as<ST>(1);
963 if (STS::magnitude(lambdaMaxForApply_ - one) < Teuchos::as<MT>(1.0e-6)) {
964 lambdaMinForApply_ = one;
965 lambdaMaxForApply_ = lambdaMinForApply_;
966 eigRatioForApply_ = one;
971 if (preAllocateTempVector_ && !D_.is_null()) {
972 makeTempMultiVector(*D_);
973 if (chebyshevAlgorithm_ ==
"fourth" || chebyshevAlgorithm_ ==
"opt_fourth") {
974 makeSecondTempMultiVector(*D_);
978 if (chebyshevAlgorithm_ ==
"textbook") {
984 if (ckUseNativeSpMV_) {
985 ck_->setAuxiliaryVectors(1);
990 template <
class ScalarType,
class MV>
994 return lambdaMaxForApply_;
997 template <
class ScalarType,
class MV>
1000 const char prefix[] =
"Ifpack2::Chebyshev::apply: ";
1003 *out_ <<
"apply: " << std::endl;
1006 " Please call setMatrix() with a nonnull input matrix, and then call "
1007 "compute(), before calling this method.");
1009 prefix <<
"There is no estimate for the max eigenvalue."
1011 << computeBeforeApplyReminder);
1012 TEUCHOS_TEST_FOR_EXCEPTION(STS::isnaninf(lambdaMinForApply_), std::runtime_error,
1013 prefix <<
"There is no estimate for the min eigenvalue."
1015 << computeBeforeApplyReminder);
1016 TEUCHOS_TEST_FOR_EXCEPTION(STS::isnaninf(eigRatioForApply_), std::runtime_error,
1017 prefix <<
"There is no estimate for the ratio of the max "
1018 "eigenvalue to the min eigenvalue."
1020 << computeBeforeApplyReminder);
1021 TEUCHOS_TEST_FOR_EXCEPTION(D_.is_null(), std::runtime_error, prefix <<
"The vector of inverse "
1022 "diagonal entries of the matrix has not yet been computed."
1024 << computeBeforeApplyReminder);
1026 if (chebyshevAlgorithm_ ==
"fourth" || chebyshevAlgorithm_ ==
"opt_fourth") {
1027 fourthKindApplyImpl(*A_, B, X, numIters_, lambdaMaxForApply_, *D_);
1028 }
else if (chebyshevAlgorithm_ ==
"textbook") {
1029 textbookApplyImpl(*A_, B, X, numIters_, lambdaMaxForApply_,
1030 lambdaMinForApply_, eigRatioForApply_, *D_);
1032 ifpackApplyImpl(*A_, B, X, numIters_, lambdaMaxForApply_,
1033 lambdaMinForApply_, eigRatioForApply_, *D_);
1036 if (computeMaxResNorm_ && B.getNumVectors() > 0) {
1037 MV R(B.getMap(), B.getNumVectors());
1038 computeResidual(R, B, *A_, X);
1041 return *std::max_element(norms.begin(), norms.end());
1047 template <
class ScalarType,
class MV>
1050 using Teuchos::rcpFromRef;
1051 this->describe(*(Teuchos::getFancyOStream(rcpFromRef(out))),
1055 template <
class ScalarType,
class MV>
1058 const ScalarType& alpha,
1062 solve(W, alpha, D_inv, B);
1063 Tpetra::deep_copy(X, W);
1066 template <
class ScalarType,
class MV>
1070 Tpetra::Details::residual(A, X, B, R);
1073 template <
class ScalarType,
class MV>
1074 void Chebyshev<ScalarType, MV>::
1075 solve(MV& Z,
const V& D_inv,
const MV& R) {
1076 Z.elementWiseMultiply(STS::one(), D_inv, R, STS::zero());
1079 template <
class ScalarType,
class MV>
1080 void Chebyshev<ScalarType, MV>::
1081 solve(MV& Z,
const ST alpha,
const V& D_inv,
const MV& R) {
1082 Z.elementWiseMultiply(alpha, D_inv, R, STS::zero());
1085 template <
class ScalarType,
class MV>
1087 Chebyshev<ScalarType, MV>::
1088 makeInverseDiagonal(
const row_matrix_type& A,
const bool useDiagOffsets)
const {
1090 using Teuchos::rcp_dynamic_cast;
1091 using Teuchos::rcpFromRef;
1094 if (!D_.is_null() &&
1095 D_->getMap()->isSameAs(*(A.getRowMap()))) {
1097 *out_ <<
"Reusing pre-existing vector for diagonal extraction" << std::endl;
1098 D_rowMap = Teuchos::rcp_const_cast<V>(D_);
1102 *out_ <<
"Allocated new vector for diagonal extraction" << std::endl;
1104 if (useDiagOffsets) {
1108 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
1109 typename MV::local_ordinal_type,
1110 typename MV::global_ordinal_type,
1111 typename MV::node_type>
1113 RCP<const crs_matrix_type> A_crsMat =
1114 rcp_dynamic_cast<
const crs_matrix_type>(rcpFromRef(A));
1115 if (!A_crsMat.is_null()) {
1117 !savedDiagOffsets_, std::logic_error,
1118 "Ifpack2::Details::Chebyshev::makeInverseDiagonal: "
1119 "It is not allowed to call this method with useDiagOffsets=true, "
1120 "if you have not previously saved offsets of diagonal entries. "
1121 "This situation should never arise if this class is used properly. "
1122 "Please report this bug to the Ifpack2 developers.");
1123 A_crsMat->getLocalDiagCopy(*D_rowMap, diagOffsets_);
1128 A.getLocalDiagCopy(*D_rowMap);
1130 RCP<V> D_rangeMap = makeRangeMapVector(D_rowMap);
1136 bool foundNonpositiveValue =
false;
1138 auto D_lcl = D_rangeMap->getLocalViewHost(Tpetra::Access::ReadOnly);
1139 auto D_lcl_1d = Kokkos::subview(D_lcl, Kokkos::ALL(), 0);
1141 typedef typename MV::impl_scalar_type IST;
1142 typedef typename MV::local_ordinal_type LO;
1143 #if KOKKOS_VERSION >= 40799
1144 typedef KokkosKernels::ArithTraits<IST> ATS;
1146 typedef Kokkos::ArithTraits<IST> ATS;
1148 #if KOKKOS_VERSION >= 40799
1149 typedef KokkosKernels::ArithTraits<typename ATS::mag_type> STM;
1151 typedef Kokkos::ArithTraits<typename ATS::mag_type> STM;
1154 const LO lclNumRows =
static_cast<LO
>(D_rangeMap->getLocalLength());
1155 for (LO i = 0; i < lclNumRows; ++i) {
1156 if (STS::real(D_lcl_1d(i)) <= STM::zero()) {
1157 foundNonpositiveValue =
true;
1163 using Teuchos::outArg;
1165 using Teuchos::reduceAll;
1167 const int lclSuccess = foundNonpositiveValue ? 0 : 1;
1168 int gblSuccess = lclSuccess;
1169 if (!D_rangeMap->getMap().is_null() && D_rangeMap->getMap()->getComm().is_null()) {
1171 reduceAll<int, int>(comm,
REDUCE_MIN, lclSuccess, outArg(gblSuccess));
1173 if (gblSuccess == 1) {
1174 *out_ <<
"makeInverseDiagonal: The matrix's diagonal entries all have "
1175 "positive real part (this is good for Chebyshev)."
1178 *out_ <<
"makeInverseDiagonal: The matrix's diagonal has at least one "
1179 "entry with nonpositive real part, on at least one process in the "
1180 "matrix's communicator. This is bad for Chebyshev."
1187 reciprocal_threshold(*D_rangeMap, minDiagVal_);
1188 return Teuchos::rcp_const_cast<
const V>(D_rangeMap);
1191 template <
class ScalarType,
class MV>
1193 Chebyshev<ScalarType, MV>::
1197 typedef Tpetra::Export<
typename MV::local_ordinal_type,
1198 typename MV::global_ordinal_type,
1199 typename MV::node_type>
1205 A_.
is_null(), std::logic_error,
1206 "Ifpack2::Details::Chebyshev::"
1207 "makeRangeMapVector: The input matrix A is null. Please call setMatrix() "
1208 "with a nonnull input matrix before calling this method. This is probably "
1209 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1211 D.
is_null(), std::logic_error,
1212 "Ifpack2::Details::Chebyshev::"
1213 "makeRangeMapVector: The input Vector D is null. This is probably "
1214 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1216 RCP<const map_type> sourceMap = D->getMap();
1217 RCP<const map_type> rangeMap = A_->getRangeMap();
1218 RCP<const map_type> rowMap = A_->getRowMap();
1220 if (rangeMap->isSameAs(*sourceMap)) {
1225 RCP<const export_type> exporter;
1229 if (sourceMap->isSameAs(*rowMap)) {
1231 exporter = A_->getGraph()->getExporter();
1233 exporter =
rcp(
new export_type(sourceMap, rangeMap));
1236 if (exporter.is_null()) {
1240 D_out->doExport(*D, *exporter, Tpetra::ADD);
1241 return Teuchos::rcp_const_cast<
const V>(D_out);
1246 template <
class ScalarType,
class MV>
1248 Chebyshev<ScalarType, MV>::
1250 using Teuchos::rcp_const_cast;
1251 return rcp_const_cast<V>(makeRangeMapVectorConst(rcp_const_cast<V>(D)));
1254 template <
class ScalarType,
class MV>
1255 void Chebyshev<ScalarType, MV>::
1256 textbookApplyImpl(
const op_type& A,
1263 const V& D_inv)
const {
1265 const ST myLambdaMin = lambdaMax / eigRatio;
1267 const ST zero = Teuchos::as<ST>(0);
1268 const ST one = Teuchos::as<ST>(1);
1269 const ST two = Teuchos::as<ST>(2);
1270 const ST d = (lambdaMax + myLambdaMin) / two;
1271 const ST c = (lambdaMax - myLambdaMin) / two;
1273 if (zeroStartingSolution_ && numIters > 0) {
1277 MV R(B.getMap(), B.getNumVectors(),
false);
1278 MV P(B.getMap(), B.getNumVectors(),
false);
1279 MV Z(B.getMap(), B.getNumVectors(),
false);
1281 for (
int i = 0; i < numIters; ++i) {
1282 computeResidual(R, B, A, X);
1291 beta = alpha * (c / two) * (c / two);
1292 alpha = one / (d - beta);
1293 P.update(one, Z, beta);
1295 X.update(alpha, P, one);
1302 template <
class ScalarType,
class MV>
1303 void Chebyshev<ScalarType, MV>::
1304 fourthKindApplyImpl(
const op_type& A,
1311 std::vector<ScalarType> betas(numIters, 1.0);
1312 if (chebyshevAlgorithm_ ==
"opt_fourth") {
1313 betas = optimalWeightsImpl<ScalarType>(numIters);
1316 const ST invEig = MT(1) / (lambdaMax * boostFactor_);
1328 if (!zeroStartingSolution_) {
1330 Tpetra::deep_copy(X4, X);
1332 if (ck_.is_null()) {
1334 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1338 ck_->compute(Z, MT(4.0 / 3.0) * invEig, const_cast<V&>(D_inv),
1339 const_cast<MV&>(B), X4, STS::zero());
1342 X.update(betas[0], Z, STS::one());
1345 firstIterationWithZeroStartingSolution(Z, MT(4.0 / 3.0) * invEig, D_inv, B, X4);
1348 X.update(betas[0], Z, STS::zero());
1351 if (numIters > 1 && ck_.is_null()) {
1353 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1356 for (
int i = 1; i < numIters; ++i) {
1357 const ST zScale = (2.0 * i - 1.0) / (2.0 * i + 3.0);
1358 const ST rScale = MT((8.0 * i + 4.0) / (2.0 * i + 3.0)) * invEig;
1362 ck_->compute(Z, rScale, const_cast<V&>(D_inv),
1363 const_cast<MV&>(B), (X4), zScale);
1366 X.update(betas[i], Z, STS::one());
1370 template <
class ScalarType,
class MV>
1371 typename Chebyshev<ScalarType, MV>::MT
1372 Chebyshev<ScalarType, MV>::maxNormInf(
const MV& X) {
1375 return *std::max_element(norms.begin(), norms.end());
1378 template <
class ScalarType,
class MV>
1379 void Chebyshev<ScalarType, MV>::
1380 ifpackApplyImpl(
const op_type& A,
1389 #ifdef HAVE_IFPACK2_DEBUG
1390 const bool debug = debug_;
1392 const bool debug =
false;
1396 *out_ <<
" \\|B\\|_{\\infty} = " << maxNormInf(B) << endl;
1397 *out_ <<
" \\|X\\|_{\\infty} = " << maxNormInf(X) << endl;
1400 if (numIters <= 0) {
1403 const ST zero =
static_cast<ST
>(0.0);
1404 const ST one =
static_cast<ST
>(1.0);
1405 const ST two =
static_cast<ST
>(2.0);
1408 if (lambdaMin == one && lambdaMax == lambdaMin) {
1414 const ST alpha = lambdaMax / eigRatio;
1415 const ST beta = boostFactor_ * lambdaMax;
1416 const ST delta = two / (beta - alpha);
1417 const ST theta = (beta + alpha) / two;
1418 const ST s1 = theta * delta;
1421 *out_ <<
" alpha = " << alpha << endl
1422 <<
" beta = " << beta << endl
1423 <<
" delta = " << delta << endl
1424 <<
" theta = " << theta << endl
1425 <<
" s1 = " << s1 << endl;
1433 *out_ <<
" Iteration " << 1 <<
":" << endl
1434 <<
" - \\|D\\|_{\\infty} = " << D_->normInf() << endl;
1438 if (!zeroStartingSolution_) {
1441 if (ck_.is_null()) {
1443 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1447 ck_->compute(W, one / theta, const_cast<V&>(D_inv),
1448 const_cast<MV&>(B), X, zero);
1451 firstIterationWithZeroStartingSolution(W, one / theta, D_inv, B, X);
1455 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf(W) << endl
1456 <<
" - \\|X\\|_{\\infty} = " << maxNormInf(X) << endl;
1459 if (numIters > 1 && ck_.is_null()) {
1461 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1466 ST rhokp1, dtemp1, dtemp2;
1467 for (
int deg = 1; deg < numIters; ++deg) {
1469 *out_ <<
" Iteration " << deg + 1 <<
":" << endl
1470 <<
" - \\|D\\|_{\\infty} = " << D_->normInf() << endl
1471 <<
" - \\|B\\|_{\\infty} = " << maxNormInf(B) << endl
1472 <<
" - \\|A\\|_{\\text{frob}} = " << A_->getFrobeniusNorm()
1474 <<
" - rhok = " << rhok << endl;
1477 rhokp1 = one / (two * s1 - rhok);
1478 dtemp1 = rhokp1 * rhok;
1479 dtemp2 = two * rhokp1 * delta;
1483 *out_ <<
" - dtemp1 = " << dtemp1 << endl
1484 <<
" - dtemp2 = " << dtemp2 << endl;
1489 ck_->compute(W, dtemp2, const_cast<V&>(D_inv),
1490 const_cast<MV&>(B), (X), dtemp1);
1493 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf(W) << endl
1494 <<
" - \\|X\\|_{\\infty} = " << maxNormInf(X) << endl;
1499 template <
class ScalarType,
class MV>
1500 typename Chebyshev<ScalarType, MV>::ST
1501 Chebyshev<ScalarType, MV>::
1502 cgMethodWithInitGuess(
const op_type& A,
1507 using MagnitudeType =
typename STS::magnitudeType;
1509 *out_ <<
" cgMethodWithInitGuess:" << endl;
1512 const ST one = STS::one();
1513 ST beta, betaOld = one, pAp, pApOld = one, alpha, rHz, rHzOld, rHzOld2 = one, lambdaMax;
1518 offdiag.
resize(numIters - 1);
1520 p =
rcp(
new V(A.getRangeMap()));
1521 z =
rcp(
new V(A.getRangeMap()));
1522 Ap =
rcp(
new V(A.getRangeMap()));
1525 solve(*p, D_inv, r);
1528 for (
int iter = 0; iter < numIters; ++iter) {
1530 *out_ <<
" Iteration " << iter << endl;
1535 r.update(-alpha, *Ap, one);
1537 solve(*z, D_inv, r);
1539 beta = rHz / rHzOld;
1540 p->update(one, *z, beta);
1542 diag[iter] = STS::real((betaOld * betaOld * pApOld + pAp) / rHzOld);
1543 offdiag[iter - 1] = -STS::real((betaOld * pApOld / (sqrt(rHzOld * rHzOld2))));
1545 *out_ <<
" diag[" << iter <<
"] = " << diag[iter] << endl;
1546 *out_ <<
" offdiag[" << iter - 1 <<
"] = " << offdiag[iter - 1] << endl;
1547 *out_ <<
" rHz = " << rHz << endl;
1548 *out_ <<
" alpha = " << alpha << endl;
1549 *out_ <<
" beta = " << beta << endl;
1552 diag[iter] = STS::real(pAp / rHzOld);
1554 *out_ <<
" diag[" << iter <<
"] = " << diag[iter] << endl;
1555 *out_ <<
" rHz = " << rHz << endl;
1556 *out_ <<
" alpha = " << alpha << endl;
1557 *out_ <<
" beta = " << beta << endl;
1565 lambdaMax = LapackHelper<ST>::tri_diag_spectral_radius(diag, offdiag);
1570 template <
class ScalarType,
class MV>
1571 typename Chebyshev<ScalarType, MV>::ST
1572 Chebyshev<ScalarType, MV>::
1573 cgMethod(
const op_type& A,
const V& D_inv,
const int numIters) {
1577 *out_ <<
"cgMethod:" << endl;
1581 if (eigVector_.is_null()) {
1582 r =
rcp(
new V(A.getDomainMap()));
1583 if (eigKeepVectors_)
1586 Details::computeInitialGuessForCG(D_inv, *r);
1590 ST lambdaMax = cgMethodWithInitGuess(A, D_inv, numIters, *r);
1595 template <
class ScalarType,
class MV>
1601 template <
class ScalarType,
class MV>
1608 template <
class ScalarType,
class MV>
1616 const size_t B_numVecs = B.getNumVectors();
1617 if (W_.is_null() || W_->getNumVectors() != B_numVecs) {
1618 W_ =
Teuchos::rcp(
new MV(B.getMap(), B_numVecs,
false));
1623 template <
class ScalarType,
class MV>
1625 Chebyshev<ScalarType, MV>::
1626 makeSecondTempMultiVector(
const MV& B) {
1631 const size_t B_numVecs = B.getNumVectors();
1632 if (W2_.is_null() || W2_->getNumVectors() != B_numVecs) {
1633 W2_ =
Teuchos::rcp(
new MV(B.getMap(), B_numVecs,
false));
1638 template <
class ScalarType,
class MV>
1642 std::ostringstream oss;
1645 oss <<
"\"Ifpack2::Details::Chebyshev\":"
1647 <<
"degree: " << numIters_
1648 <<
", lambdaMax: " << lambdaMaxForApply_
1649 <<
", alpha: " << eigRatioForApply_
1650 <<
", lambdaMin: " << lambdaMinForApply_
1651 <<
", boost factor: " << boostFactor_
1652 <<
", algorithm: " << chebyshevAlgorithm_;
1653 if (!userInvDiag_.is_null())
1654 oss <<
", diagonal: user-supplied";
1659 template <
class ScalarType,
class MV>
1687 myRank = A_->getComm()->getRank();
1692 out <<
"\"Ifpack2::Details::Chebyshev\":" << endl;
1698 out <<
"degree: " << numIters_ << endl
1699 <<
"lambdaMax: " << lambdaMaxForApply_ << endl
1700 <<
"alpha: " << eigRatioForApply_ << endl
1701 <<
"lambdaMin: " << lambdaMinForApply_ << endl
1702 <<
"boost factor: " << boostFactor_ << endl;
1710 out <<
"Template parameters:" << endl;
1713 out <<
"ScalarType: " << TypeNameTraits<ScalarType>::name() << endl
1714 <<
"MV: " << TypeNameTraits<MV>::name() << endl;
1720 out <<
"Computed parameters:" << endl;
1734 out <<
"unset" << endl;
1738 out <<
"set" << endl;
1746 D_->describe(out, vl);
1751 out <<
"W_: " << (W_.is_null() ?
"unset" :
"set") << endl
1752 <<
"computedLambdaMax_: " << computedLambdaMax_ << endl
1753 <<
"computedLambdaMin_: " << computedLambdaMin_ << endl
1754 <<
"lambdaMaxForApply_: " << lambdaMaxForApply_ << endl
1755 <<
"lambdaMinForApply_: " << lambdaMinForApply_ << endl
1756 <<
"eigRatioForApply_: " << eigRatioForApply_ << endl;
1761 out <<
"User parameters:" << endl;
1767 out <<
"userInvDiag_: ";
1768 if (userInvDiag_.is_null()) {
1769 out <<
"unset" << endl;
1771 out <<
"set" << endl;
1776 userInvDiag_->describe(out, vl);
1779 out <<
"userLambdaMax_: " << userLambdaMax_ << endl
1780 <<
"userLambdaMin_: " << userLambdaMin_ << endl
1781 <<
"userEigRatio_: " << userEigRatio_ << endl
1782 <<
"numIters_: " << numIters_ << endl
1783 <<
"eigMaxIters_: " << eigMaxIters_ << endl
1784 <<
"eigRelTolerance_: " << eigRelTolerance_ << endl
1785 <<
"eigNormalizationFreq_: " << eigNormalizationFreq_ << endl
1786 <<
"zeroStartingSolution_: " << zeroStartingSolution_ << endl
1787 <<
"assumeMatrixUnchanged_: " << assumeMatrixUnchanged_ << endl
1788 <<
"chebyshevAlgorithm_: " << chebyshevAlgorithm_ << endl
1789 <<
"computeMaxResNorm_: " << computeMaxResNorm_ << endl;
1797 #define IFPACK2_DETAILS_CHEBYSHEV_INSTANT(S, LO, GO, N) \
1798 template class Ifpack2::Details::Chebyshev<S, Tpetra::MultiVector<S, LO, GO, N>>;
1800 #endif // IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP
void setParameters(Teuchos::ParameterList &plist)
Set (or reset) parameters.
Definition: Ifpack2_Details_Chebyshev_def.hpp:340
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:999
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:1661
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:755
Compute scaled damped residual for Chebyshev.
Definition: Ifpack2_Details_ChebyshevKernel_decl.hpp:45
#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:1597
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:275
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:1049
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:1641
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:1603
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:791
basic_oblackholestream< char, std::char_traits< char > > oblackholestream