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 {
56 typedef typename XV::execution_space execution_space;
57 typedef typename XV::non_const_value_type value_type;
58 typedef SizeType size_type;
59 typedef Kokkos::ArithTraits<value_type> KAT;
60 typedef typename KAT::mag_type mag_type;
63 const value_type minVal_;
64 const mag_type minValMag_;
66 V_ReciprocalThresholdSelfFunctor(
const XV& X,
67 const value_type& min_val)
70 , minValMag_(KAT::abs(min_val)) {}
72 KOKKOS_INLINE_FUNCTION
73 void operator()(
const size_type& i)
const {
74 const mag_type X_i_abs = KAT::abs(X_[i]);
76 if (X_i_abs < minValMag_) {
79 X_[i] = KAT::one() / X_[i];
84 template <
class XV,
class SizeType =
typename XV::
size_type>
85 struct LocalReciprocalThreshold {
88 const typename XV::non_const_value_type& minVal) {
89 typedef typename XV::execution_space execution_space;
90 Kokkos::RangePolicy<execution_space, SizeType> policy(0, X.extent(0));
91 V_ReciprocalThresholdSelfFunctor<XV, SizeType> op(X, minVal);
92 Kokkos::parallel_for(policy, op);
96 template <
class TpetraVectorType,
97 const bool classic = TpetraVectorType::node_type::classic>
98 struct GlobalReciprocalThreshold {};
100 template <
class TpetraVectorType>
101 struct GlobalReciprocalThreshold<TpetraVectorType, true> {
103 compute(TpetraVectorType& V,
104 const typename TpetraVectorType::scalar_type& min_val) {
105 typedef typename TpetraVectorType::scalar_type scalar_type;
106 typedef typename TpetraVectorType::mag_type mag_type;
107 typedef Kokkos::ArithTraits<scalar_type> STS;
109 const scalar_type ONE = STS::one();
110 const mag_type min_val_abs = STS::abs(min_val);
113 const size_t lclNumRows = V.getLocalLength();
115 for (
size_t i = 0; i < lclNumRows; ++i) {
116 const scalar_type V_0i = V_0[i];
117 if (STS::abs(V_0i) < min_val_abs) {
126 template <
class TpetraVectorType>
127 struct GlobalReciprocalThreshold<TpetraVectorType, false> {
129 compute(TpetraVectorType& X,
130 const typename TpetraVectorType::scalar_type& minVal) {
131 typedef typename TpetraVectorType::impl_scalar_type value_type;
133 const value_type minValS =
static_cast<value_type
>(minVal);
134 auto X_0 = Kokkos::subview(X.getLocalViewDevice(Tpetra::Access::ReadWrite),
136 LocalReciprocalThreshold<decltype(X_0)>::compute(X_0, minValS);
141 template <
typename S,
typename L,
typename G,
typename N>
142 void reciprocal_threshold(Tpetra::Vector<S, L, G, N>& V,
const S& minVal) {
143 GlobalReciprocalThreshold<Tpetra::Vector<S, L, G, N>>::compute(V, minVal);
146 template <class ScalarType, const bool lapackSupportsScalarType = LapackSupportsScalar<ScalarType>::value>
147 struct LapackHelper {
151 throw std::runtime_error(
"LAPACK does not support the scalar type.");
156 void computeInitialGuessForCG(
const V& diagonal, V& x) {
157 using device_type =
typename V::node_type::device_type;
158 using range_policy = Kokkos::RangePolicy<typename device_type::execution_space>;
165 size_t N = x.getLocalLength();
166 auto d_view = diagonal.template getLocalView<device_type>(Tpetra::Access::ReadOnly);
167 auto x_view = x.template getLocalView<device_type>(Tpetra::Access::ReadWrite);
172 Kokkos::parallel_for(
173 "computeInitialGuessforCG::zero_bcs", range_policy(0, N), KOKKOS_LAMBDA(
const size_t& i) {
174 if (d_view(i, 0) == ONE)
179 template <
class ScalarType>
180 struct LapackHelper<ScalarType, true> {
185 using MagnitudeType =
typename STS::magnitudeType;
187 const int N = diag.size();
188 ScalarType scalar_dummy;
189 std::vector<MagnitudeType> mag_dummy(4 * N);
193 ScalarType lambdaMax = STS::one();
196 lapack.
PTEQR(char_N, N, diag.getRawPtr(), offdiag.getRawPtr(),
197 &scalar_dummy, 1, &mag_dummy[0], &info);
199 "Ifpack2::Details::LapackHelper::tri_diag_spectral_radius:"
200 "LAPACK's _PTEQR failed with info = "
201 << info <<
" < 0. This suggests there might be a bug in the way Ifpack2 "
202 "is calling LAPACK. Please report this to the Ifpack2 developers.");
204 lambdaMax = Teuchos::as<ScalarType>(diag[0]);
210 template <
class ScalarType,
class MV>
211 void Chebyshev<ScalarType, MV>::checkInputMatrix()
const {
213 !A_.
is_null() && A_->getGlobalNumRows() != A_->getGlobalNumCols(),
214 std::invalid_argument,
215 "Ifpack2::Chebyshev: The input matrix A must be square. "
217 << A_->getGlobalNumRows() <<
" rows and "
218 << A_->getGlobalNumCols() <<
" columns.");
230 !domainMap->isSameAs(*rangeMap), std::invalid_argument,
231 "Ifpack2::Chebyshev: The domain Map and range Map of the matrix must be "
232 "the same (in the sense of isSameAs())."
235 "for this in debug mode.");
239 template <
class ScalarType,
class MV>
240 void Chebyshev<ScalarType, MV>::
241 checkConstructorInput()
const {
245 if (STS::isComplex) {
247 "Ifpack2::Chebyshev: This class' implementation "
248 "of Chebyshev iteration only works for real-valued, symmetric positive "
249 "definite matrices. However, you instantiated this class for ScalarType"
252 "complex-valued type. While this may be algorithmically correct if all "
253 "of the complex numbers in the matrix have zero imaginary part, we "
254 "forbid using complex ScalarType altogether in order to remind you of "
255 "the limitations of our implementation (and of the algorithm itself).");
261 template <
class ScalarType,
class MV>
265 , savedDiagOffsets_(false)
266 , computedLambdaMax_(STS::nan())
267 , computedLambdaMin_(STS::nan())
268 , lambdaMaxForApply_(STS::nan())
269 , lambdaMinForApply_(STS::nan())
270 , eigRatioForApply_(STS::nan())
271 , userLambdaMax_(STS::nan())
272 , userLambdaMin_(STS::nan())
273 , userEigRatio_(Teuchos::
as<
ST>(30))
274 , minDiagVal_(STS::eps())
277 , eigRelTolerance_(Teuchos::ScalarTraits<
MT>::zero())
278 , eigKeepVectors_(false)
279 , eigenAnalysisType_(
"power method")
280 , eigNormalizationFreq_(1)
281 , zeroStartingSolution_(true)
282 , assumeMatrixUnchanged_(false)
283 , chebyshevAlgorithm_(
"first")
284 , computeMaxResNorm_(false)
285 , computeSpectralRadius_(true)
286 , ckUseNativeSpMV_(MV::node_type::is_gpu)
288 checkConstructorInput();
291 template <
class ScalarType,
class MV>
296 , savedDiagOffsets_(false)
297 , computedLambdaMax_(STS::nan())
298 , computedLambdaMin_(STS::nan())
299 , lambdaMaxForApply_(STS::nan())
300 , boostFactor_(static_cast<
MT>(1.1))
301 , lambdaMinForApply_(STS::nan())
302 , eigRatioForApply_(STS::nan())
303 , userLambdaMax_(STS::nan())
304 , userLambdaMin_(STS::nan())
305 , userEigRatio_(Teuchos::
as<
ST>(30))
306 , minDiagVal_(STS::eps())
309 , eigRelTolerance_(Teuchos::ScalarTraits<
MT>::zero())
310 , eigKeepVectors_(false)
311 , eigenAnalysisType_(
"power method")
312 , eigNormalizationFreq_(1)
313 , zeroStartingSolution_(true)
314 , assumeMatrixUnchanged_(false)
315 , chebyshevAlgorithm_(
"first")
316 , computeMaxResNorm_(false)
317 , computeSpectralRadius_(true)
318 , ckUseNativeSpMV_(MV::node_type::is_gpu)
320 checkConstructorInput();
324 template <
class ScalarType,
class MV>
329 using Teuchos::rcp_const_cast;
341 const ST defaultLambdaMax = STS::nan();
342 const ST defaultLambdaMin = STS::nan();
349 const ST defaultEigRatio = Teuchos::as<ST>(30);
350 const MT defaultBoostFactor =
static_cast<MT>(1.1);
351 const ST defaultMinDiagVal = STS::eps();
352 const int defaultNumIters = 1;
353 const int defaultEigMaxIters = 10;
355 const bool defaultEigKeepVectors =
false;
356 const int defaultEigNormalizationFreq = 1;
357 const bool defaultZeroStartingSolution =
true;
358 const bool defaultAssumeMatrixUnchanged =
false;
359 const std::string defaultChebyshevAlgorithm =
"first";
360 const bool defaultComputeMaxResNorm =
false;
361 const bool defaultComputeSpectralRadius =
true;
362 const bool defaultCkUseNativeSpMV = MV::node_type::is_gpu;
363 const bool defaultDebug =
false;
369 RCP<const V> userInvDiagCopy;
370 ST lambdaMax = defaultLambdaMax;
371 ST lambdaMin = defaultLambdaMin;
372 ST eigRatio = defaultEigRatio;
373 MT boostFactor = defaultBoostFactor;
374 ST minDiagVal = defaultMinDiagVal;
375 int numIters = defaultNumIters;
376 int eigMaxIters = defaultEigMaxIters;
377 MT eigRelTolerance = defaultEigRelTolerance;
378 bool eigKeepVectors = defaultEigKeepVectors;
379 int eigNormalizationFreq = defaultEigNormalizationFreq;
380 bool zeroStartingSolution = defaultZeroStartingSolution;
381 bool assumeMatrixUnchanged = defaultAssumeMatrixUnchanged;
382 std::string chebyshevAlgorithm = defaultChebyshevAlgorithm;
383 bool computeMaxResNorm = defaultComputeMaxResNorm;
384 bool computeSpectralRadius = defaultComputeSpectralRadius;
385 bool ckUseNativeSpMV = defaultCkUseNativeSpMV;
386 bool debug = defaultDebug;
393 if (plist.
isType<
bool>(
"debug")) {
394 debug = plist.
get<
bool>(
"debug");
395 }
else if (plist.
isType<
int>(
"debug")) {
396 const int debugInt = plist.
get<
bool>(
"debug");
397 debug = debugInt != 0;
410 const char opInvDiagLabel[] =
"chebyshev: operator inv diagonal";
413 RCP<const V> userInvDiag;
415 if (plist.
isType<
const V*>(opInvDiagLabel)) {
416 const V* rawUserInvDiag =
417 plist.
get<
const V*>(opInvDiagLabel);
419 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);
424 }
else if (plist.
isType<RCP<const V>>(opInvDiagLabel)) {
425 userInvDiag = plist.
get<RCP<const V>>(opInvDiagLabel);
426 }
else if (plist.
isType<RCP<V>>(opInvDiagLabel)) {
427 RCP<V> userInvDiagNonConst =
428 plist.
get<RCP<V>>(opInvDiagLabel);
429 userInvDiag = rcp_const_cast<
const V>(userInvDiagNonConst);
430 }
else if (plist.
isType<
const V>(opInvDiagLabel)) {
431 const V& userInvDiagRef = plist.
get<
const V>(opInvDiagLabel);
433 userInvDiag = userInvDiagCopy;
434 }
else if (plist.
isType<V>(opInvDiagLabel)) {
435 V& userInvDiagNonConstRef = plist.
get<V>(opInvDiagLabel);
436 const V& userInvDiagRef =
const_cast<const V&
>(userInvDiagNonConstRef);
438 userInvDiag = userInvDiagCopy;
448 if (!userInvDiag.is_null() && userInvDiagCopy.is_null()) {
459 if (plist.
isParameter(
"chebyshev: use native spmv"))
460 ckUseNativeSpMV = plist.
get(
"chebyshev: use native spmv", ckUseNativeSpMV);
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");
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");
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);
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 "
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 "
519 const char paramName[] =
"chebyshev: boost factor";
523 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 "Ifpack2::Chebyshev::setParameters: \"chebyshev: boost factor\""
531 "parameter must have type magnitude_type (MT) or double.");
540 plist.
set(paramName, defaultBoostFactor);
543 "Ifpack2::Chebyshev::setParameters: \"" << paramName <<
"\" parameter "
544 "must be >= 1, but you supplied the value "
545 << boostFactor <<
".");
549 minDiagVal = plist.
get(
"chebyshev: min diagonal value", minDiagVal);
551 STS::isnaninf(minDiagVal), std::invalid_argument,
552 "Ifpack2::Chebyshev::setParameters: \"chebyshev: min diagonal value\" "
553 "parameter is NaN or Inf. This parameter is optional, but if you choose "
554 "to supply it, it must have a finite value.");
558 numIters = plist.
get<
int>(
"smoother: sweeps");
561 numIters = plist.
get<
int>(
"relaxation: sweeps");
563 numIters = plist.
get(
"chebyshev: degree", numIters);
565 numIters < 0, std::invalid_argument,
566 "Ifpack2::Chebyshev::setParameters: \"chebyshev: degree\" parameter (also "
567 "called \"smoother: sweeps\" or \"relaxation: sweeps\") must be a "
568 "nonnegative integer. You gave a value of "
572 if (plist.
isParameter(
"eigen-analysis: iterations")) {
573 eigMaxIters = plist.
get<
int>(
"eigen-analysis: iterations");
575 eigMaxIters = plist.
get(
"chebyshev: eigenvalue max iterations", eigMaxIters);
577 eigMaxIters < 0, std::invalid_argument,
578 "Ifpack2::Chebyshev::setParameters: \"chebyshev: eigenvalue max iterations"
579 "\" parameter (also called \"eigen-analysis: iterations\") must be a "
580 "nonnegative integer. You gave a value of "
581 << eigMaxIters <<
".");
583 if (plist.
isType<
double>(
"chebyshev: eigenvalue relative tolerance"))
584 eigRelTolerance = Teuchos::as<MT>(plist.
get<
double>(
"chebyshev: eigenvalue relative tolerance"));
585 else if (plist.
isType<
MT>(
"chebyshev: eigenvalue relative tolerance"))
586 eigRelTolerance = plist.
get<
MT>(
"chebyshev: eigenvalue relative tolerance");
587 else if (plist.
isType<
ST>(
"chebyshev: eigenvalue relative tolerance"))
590 eigKeepVectors = plist.
get(
"chebyshev: eigenvalue keep vectors", eigKeepVectors);
592 eigNormalizationFreq = plist.
get(
"chebyshev: eigenvalue normalization frequency", eigNormalizationFreq);
594 eigNormalizationFreq < 0, std::invalid_argument,
595 "Ifpack2::Chebyshev::setParameters: \"chebyshev: eigenvalue normalization frequency"
596 "\" parameter must be a "
597 "nonnegative integer. You gave a value of "
598 << eigNormalizationFreq <<
".")
600 zeroStartingSolution = plist.
get(
"chebyshev: zero starting solution",
601 zeroStartingSolution);
602 assumeMatrixUnchanged = plist.
get(
"chebyshev: assume matrix does not change",
603 assumeMatrixUnchanged);
608 chebyshevAlgorithm = plist.
get<std::string>(
"chebyshev: algorithm");
610 chebyshevAlgorithm !=
"first" &&
611 chebyshevAlgorithm !=
"textbook" &&
612 chebyshevAlgorithm !=
"fourth" &&
613 chebyshevAlgorithm !=
"opt_fourth",
614 std::invalid_argument,
615 "Ifpack2::Chebyshev: Ifpack2 only supports \"first\", \"textbook\", \"fourth\", and \"opt_fourth\", for \"chebyshev: algorithm\".");
618 #ifdef IFPACK2_ENABLE_DEPRECATED_CODE
622 if (plist.
isParameter(
"chebyshev: textbook algorithm")) {
623 const bool textbookAlgorithm = plist.
get<
bool>(
"chebyshev: textbook algorithm");
624 if (textbookAlgorithm) {
625 chebyshevAlgorithm =
"textbook";
627 chebyshevAlgorithm =
"first";
633 if (plist.
isParameter(
"chebyshev: compute max residual norm")) {
634 computeMaxResNorm = plist.
get<
bool>(
"chebyshev: compute max residual norm");
636 if (plist.
isParameter(
"chebyshev: compute spectral radius")) {
637 computeSpectralRadius = plist.
get<
bool>(
"chebyshev: compute spectral radius");
644 !plist.
get<
bool>(
"chebyshev: use block mode"),
645 std::invalid_argument,
646 "Ifpack2::Chebyshev requires that if you set \"chebyshev: use "
647 "block mode\" at all, you must set it to false. "
648 "Ifpack2::Chebyshev does not implement Ifpack's block mode.");
650 !plist.
get<
bool>(
"chebyshev: solve normal equations"),
651 std::invalid_argument,
652 "Ifpack2::Chebyshev does not and will never implement the Ifpack "
653 "parameter \"chebyshev: solve normal equations\". If you want to "
654 "solve the normal equations, construct a Tpetra::Operator that "
655 "implements A^* A, and use Chebyshev to solve A^* A x = A^* b.");
663 std::string eigenAnalysisType(
"power-method");
665 eigenAnalysisType = plist.
get<std::string>(
"eigen-analysis: type");
667 eigenAnalysisType !=
"power-method" &&
668 eigenAnalysisType !=
"power method" &&
669 eigenAnalysisType !=
"cg",
670 std::invalid_argument,
671 "Ifpack2::Chebyshev: Ifpack2 only supports \"power method\" and \"cg\" for \"eigen-analysis: type\".");
675 userInvDiag_ = userInvDiagCopy;
676 userLambdaMax_ = lambdaMax;
677 userLambdaMin_ = lambdaMin;
678 userEigRatio_ = eigRatio;
679 boostFactor_ =
static_cast<MT>(boostFactor);
680 minDiagVal_ = minDiagVal;
681 numIters_ = numIters;
682 eigMaxIters_ = eigMaxIters;
683 eigRelTolerance_ = eigRelTolerance;
684 eigKeepVectors_ = eigKeepVectors;
685 eigNormalizationFreq_ = eigNormalizationFreq;
686 eigenAnalysisType_ = eigenAnalysisType;
687 zeroStartingSolution_ = zeroStartingSolution;
688 assumeMatrixUnchanged_ = assumeMatrixUnchanged;
689 chebyshevAlgorithm_ = chebyshevAlgorithm;
690 computeMaxResNorm_ = computeMaxResNorm;
691 computeSpectralRadius_ = computeSpectralRadius;
692 ckUseNativeSpMV_ = ckUseNativeSpMV;
703 myRank = A_->getComm()->getRank();
707 out_ = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cerr));
711 out_ = Teuchos::getFancyOStream(blackHole);
715 out_ = Teuchos::null;
719 template <
class ScalarType,
class MV>
723 diagOffsets_ = offsets_type();
724 savedDiagOffsets_ =
false;
726 computedLambdaMax_ = STS::nan();
727 computedLambdaMin_ = STS::nan();
728 eigVector_ = Teuchos::null;
729 eigVector2_ = Teuchos::null;
732 template <
class ScalarType,
class MV>
736 if (!assumeMatrixUnchanged_) {
753 myRank = A->getComm()->getRank();
757 out_ = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cerr));
760 out_ = Teuchos::getFancyOStream(blackHole);
764 out_ = Teuchos::null;
769 template <
class ScalarType,
class MV>
776 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
777 typename MV::local_ordinal_type,
778 typename MV::global_ordinal_type,
779 typename MV::node_type>
783 A_.
is_null(), std::runtime_error,
784 "Ifpack2::Chebyshev::compute: The input "
785 "matrix A is null. Please call setMatrix() with a nonnull input matrix "
786 "before calling this method.");
801 if (userInvDiag_.is_null()) {
803 Teuchos::rcp_dynamic_cast<
const crs_matrix_type>(A_);
805 if (!A_crsMat.
is_null() && A_crsMat->isFillComplete()) {
807 const size_t lclNumRows = A_crsMat->getLocalNumRows();
808 if (diagOffsets_.extent(0) < lclNumRows) {
809 diagOffsets_ = offsets_type();
810 diagOffsets_ = offsets_type(
"offsets", lclNumRows);
812 A_crsMat->getCrsGraph()->getLocalDiagOffsets(diagOffsets_);
813 savedDiagOffsets_ =
true;
814 D_ = makeInverseDiagonal(*A_,
true);
816 D_ = makeInverseDiagonal(*A_);
818 }
else if (!assumeMatrixUnchanged_) {
819 if (!A_crsMat.
is_null() && A_crsMat->isFillComplete()) {
822 if (!savedDiagOffsets_) {
823 const size_t lclNumRows = A_crsMat->getLocalNumRows();
824 if (diagOffsets_.extent(0) < lclNumRows) {
825 diagOffsets_ = offsets_type();
826 diagOffsets_ = offsets_type(
"offsets", lclNumRows);
828 A_crsMat->getCrsGraph()->getLocalDiagOffsets(diagOffsets_);
829 savedDiagOffsets_ =
true;
832 D_ = makeInverseDiagonal(*A_,
true);
834 D_ = makeInverseDiagonal(*A_);
838 D_ = makeRangeMapVectorConst(userInvDiag_);
842 const bool computedEigenvalueEstimates =
843 STS::isnaninf(computedLambdaMax_) || STS::isnaninf(computedLambdaMin_);
853 if (!assumeMatrixUnchanged_ ||
854 (!computedEigenvalueEstimates && STS::isnaninf(userLambdaMax_))) {
855 ST computedLambdaMax;
856 if ((eigenAnalysisType_ ==
"power method") || (eigenAnalysisType_ ==
"power-method")) {
858 if (eigVector_.is_null()) {
862 PowerMethod::computeInitialGuessForPowerMethod(*x,
false);
867 if (eigVector2_.is_null()) {
868 y =
rcp(
new V(A_->getRangeMap()));
875 computedLambdaMax = PowerMethod::powerMethodWithInitGuess(*A_, *D_, eigMaxIters_, x, y,
876 eigRelTolerance_, eigNormalizationFreq_, stream,
877 computeSpectralRadius_);
879 computedLambdaMax = cgMethod(*A_, *D_, eigMaxIters_);
882 STS::isnaninf(computedLambdaMax),
884 "Ifpack2::Chebyshev::compute: Estimation of the max eigenvalue "
885 "of D^{-1} A failed, by producing Inf or NaN. This probably means that "
886 "the matrix contains Inf or NaN values, or that it is badly scaled.");
888 STS::isnaninf(userEigRatio_),
890 "Ifpack2::Chebyshev::compute: userEigRatio_ is Inf or NaN."
892 <<
"This should be impossible." << endl
893 <<
"Please report this bug to the Ifpack2 developers.");
899 const ST computedLambdaMin = computedLambdaMax / userEigRatio_;
902 computedLambdaMax_ = computedLambdaMax;
903 computedLambdaMin_ = computedLambdaMin;
906 STS::isnaninf(userLambdaMax_) && STS::isnaninf(computedLambdaMax_),
908 "Ifpack2::Chebyshev::compute: " << endl
909 <<
"Both userLambdaMax_ and computedLambdaMax_ are Inf or NaN."
911 <<
"This should be impossible." << endl
912 <<
"Please report this bug to the Ifpack2 developers.");
920 lambdaMaxForApply_ = STS::isnaninf(userLambdaMax_) ? computedLambdaMax_ : userLambdaMax_;
933 lambdaMinForApply_ = lambdaMaxForApply_ / userEigRatio_;
934 eigRatioForApply_ = userEigRatio_;
936 if (chebyshevAlgorithm_ ==
"first") {
939 const ST one = Teuchos::as<ST>(1);
942 if (STS::magnitude(lambdaMaxForApply_ - one) < Teuchos::as<MT>(1.0e-6)) {
943 lambdaMinForApply_ = one;
944 lambdaMaxForApply_ = lambdaMinForApply_;
945 eigRatioForApply_ = one;
950 template <
class ScalarType,
class MV>
954 return lambdaMaxForApply_;
957 template <
class ScalarType,
class MV>
960 const char prefix[] =
"Ifpack2::Chebyshev::apply: ";
963 *out_ <<
"apply: " << std::endl;
966 " Please call setMatrix() with a nonnull input matrix, and then call "
967 "compute(), before calling this method.");
969 prefix <<
"There is no estimate for the max eigenvalue."
971 << computeBeforeApplyReminder);
972 TEUCHOS_TEST_FOR_EXCEPTION(STS::isnaninf(lambdaMinForApply_), std::runtime_error,
973 prefix <<
"There is no estimate for the min eigenvalue."
975 << computeBeforeApplyReminder);
976 TEUCHOS_TEST_FOR_EXCEPTION(STS::isnaninf(eigRatioForApply_), std::runtime_error,
977 prefix <<
"There is no estimate for the ratio of the max "
978 "eigenvalue to the min eigenvalue."
980 << computeBeforeApplyReminder);
981 TEUCHOS_TEST_FOR_EXCEPTION(D_.is_null(), std::runtime_error, prefix <<
"The vector of inverse "
982 "diagonal entries of the matrix has not yet been computed."
984 << computeBeforeApplyReminder);
986 if (chebyshevAlgorithm_ ==
"fourth" || chebyshevAlgorithm_ ==
"opt_fourth") {
987 fourthKindApplyImpl(*A_, B, X, numIters_, lambdaMaxForApply_, *D_);
988 }
else if (chebyshevAlgorithm_ ==
"textbook") {
989 textbookApplyImpl(*A_, B, X, numIters_, lambdaMaxForApply_,
990 lambdaMinForApply_, eigRatioForApply_, *D_);
992 ifpackApplyImpl(*A_, B, X, numIters_, lambdaMaxForApply_,
993 lambdaMinForApply_, eigRatioForApply_, *D_);
996 if (computeMaxResNorm_ && B.getNumVectors() > 0) {
997 MV R(B.getMap(), B.getNumVectors());
998 computeResidual(R, B, *A_, X);
1001 return *std::max_element(norms.begin(), norms.end());
1007 template <
class ScalarType,
class MV>
1010 using Teuchos::rcpFromRef;
1011 this->describe(*(Teuchos::getFancyOStream(rcpFromRef(out))),
1015 template <
class ScalarType,
class MV>
1018 const ScalarType& alpha,
1022 solve(W, alpha, D_inv, B);
1023 Tpetra::deep_copy(X, W);
1026 template <
class ScalarType,
class MV>
1030 Tpetra::Details::residual(A, X, B, R);
1033 template <
class ScalarType,
class MV>
1034 void Chebyshev<ScalarType, MV>::
1035 solve(MV& Z,
const V& D_inv,
const MV& R) {
1036 Z.elementWiseMultiply(STS::one(), D_inv, R, STS::zero());
1039 template <
class ScalarType,
class MV>
1040 void Chebyshev<ScalarType, MV>::
1041 solve(MV& Z,
const ST alpha,
const V& D_inv,
const MV& R) {
1042 Z.elementWiseMultiply(alpha, D_inv, R, STS::zero());
1045 template <
class ScalarType,
class MV>
1047 Chebyshev<ScalarType, MV>::
1048 makeInverseDiagonal(
const row_matrix_type& A,
const bool useDiagOffsets)
const {
1050 using Teuchos::rcp_dynamic_cast;
1051 using Teuchos::rcpFromRef;
1054 if (!D_.is_null() &&
1055 D_->getMap()->isSameAs(*(A.getRowMap()))) {
1057 *out_ <<
"Reusing pre-existing vector for diagonal extraction" << std::endl;
1058 D_rowMap = Teuchos::rcp_const_cast<V>(D_);
1062 *out_ <<
"Allocated new vector for diagonal extraction" << std::endl;
1064 if (useDiagOffsets) {
1068 typedef Tpetra::CrsMatrix<
typename MV::scalar_type,
1069 typename MV::local_ordinal_type,
1070 typename MV::global_ordinal_type,
1071 typename MV::node_type>
1073 RCP<const crs_matrix_type> A_crsMat =
1074 rcp_dynamic_cast<
const crs_matrix_type>(rcpFromRef(A));
1075 if (!A_crsMat.is_null()) {
1077 !savedDiagOffsets_, std::logic_error,
1078 "Ifpack2::Details::Chebyshev::makeInverseDiagonal: "
1079 "It is not allowed to call this method with useDiagOffsets=true, "
1080 "if you have not previously saved offsets of diagonal entries. "
1081 "This situation should never arise if this class is used properly. "
1082 "Please report this bug to the Ifpack2 developers.");
1083 A_crsMat->getLocalDiagCopy(*D_rowMap, diagOffsets_);
1088 A.getLocalDiagCopy(*D_rowMap);
1090 RCP<V> D_rangeMap = makeRangeMapVector(D_rowMap);
1096 bool foundNonpositiveValue =
false;
1098 auto D_lcl = D_rangeMap->getLocalViewHost(Tpetra::Access::ReadOnly);
1099 auto D_lcl_1d = Kokkos::subview(D_lcl, Kokkos::ALL(), 0);
1101 typedef typename MV::impl_scalar_type IST;
1102 typedef typename MV::local_ordinal_type LO;
1103 typedef Kokkos::ArithTraits<IST> ATS;
1104 typedef Kokkos::ArithTraits<typename ATS::mag_type> STM;
1106 const LO lclNumRows =
static_cast<LO
>(D_rangeMap->getLocalLength());
1107 for (LO i = 0; i < lclNumRows; ++i) {
1108 if (STS::real(D_lcl_1d(i)) <= STM::zero()) {
1109 foundNonpositiveValue =
true;
1115 using Teuchos::outArg;
1117 using Teuchos::reduceAll;
1119 const int lclSuccess = foundNonpositiveValue ? 0 : 1;
1120 int gblSuccess = lclSuccess;
1121 if (!D_rangeMap->getMap().is_null() && D_rangeMap->getMap()->getComm().is_null()) {
1123 reduceAll<int, int>(comm,
REDUCE_MIN, lclSuccess, outArg(gblSuccess));
1125 if (gblSuccess == 1) {
1126 *out_ <<
"makeInverseDiagonal: The matrix's diagonal entries all have "
1127 "positive real part (this is good for Chebyshev)."
1130 *out_ <<
"makeInverseDiagonal: The matrix's diagonal has at least one "
1131 "entry with nonpositive real part, on at least one process in the "
1132 "matrix's communicator. This is bad for Chebyshev."
1139 reciprocal_threshold(*D_rangeMap, minDiagVal_);
1140 return Teuchos::rcp_const_cast<
const V>(D_rangeMap);
1143 template <
class ScalarType,
class MV>
1145 Chebyshev<ScalarType, MV>::
1149 typedef Tpetra::Export<
typename MV::local_ordinal_type,
1150 typename MV::global_ordinal_type,
1151 typename MV::node_type>
1157 A_.
is_null(), std::logic_error,
1158 "Ifpack2::Details::Chebyshev::"
1159 "makeRangeMapVector: The input matrix A is null. Please call setMatrix() "
1160 "with a nonnull input matrix before calling this method. This is probably "
1161 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1163 D.
is_null(), std::logic_error,
1164 "Ifpack2::Details::Chebyshev::"
1165 "makeRangeMapVector: The input Vector D is null. This is probably "
1166 "a bug in Ifpack2; please report this bug to the Ifpack2 developers.");
1168 RCP<const map_type> sourceMap = D->getMap();
1169 RCP<const map_type> rangeMap = A_->getRangeMap();
1170 RCP<const map_type> rowMap = A_->getRowMap();
1172 if (rangeMap->isSameAs(*sourceMap)) {
1177 RCP<const export_type> exporter;
1181 if (sourceMap->isSameAs(*rowMap)) {
1183 exporter = A_->getGraph()->getExporter();
1185 exporter =
rcp(
new export_type(sourceMap, rangeMap));
1188 if (exporter.is_null()) {
1192 D_out->doExport(*D, *exporter, Tpetra::ADD);
1193 return Teuchos::rcp_const_cast<
const V>(D_out);
1198 template <
class ScalarType,
class MV>
1200 Chebyshev<ScalarType, MV>::
1202 using Teuchos::rcp_const_cast;
1203 return rcp_const_cast<V>(makeRangeMapVectorConst(rcp_const_cast<V>(D)));
1206 template <
class ScalarType,
class MV>
1207 void Chebyshev<ScalarType, MV>::
1208 textbookApplyImpl(
const op_type& A,
1215 const V& D_inv)
const {
1217 const ST myLambdaMin = lambdaMax / eigRatio;
1219 const ST zero = Teuchos::as<ST>(0);
1220 const ST one = Teuchos::as<ST>(1);
1221 const ST two = Teuchos::as<ST>(2);
1222 const ST d = (lambdaMax + myLambdaMin) / two;
1223 const ST c = (lambdaMax - myLambdaMin) / two;
1225 if (zeroStartingSolution_ && numIters > 0) {
1229 MV R(B.getMap(), B.getNumVectors(),
false);
1230 MV P(B.getMap(), B.getNumVectors(),
false);
1231 MV Z(B.getMap(), B.getNumVectors(),
false);
1233 for (
int i = 0; i < numIters; ++i) {
1234 computeResidual(R, B, A, X);
1243 beta = alpha * (c / two) * (c / two);
1244 alpha = one / (d - beta);
1245 P.update(one, Z, beta);
1247 X.update(alpha, P, one);
1254 template <
class ScalarType,
class MV>
1255 void Chebyshev<ScalarType, MV>::
1256 fourthKindApplyImpl(
const op_type& A,
1263 std::vector<ScalarType> betas(numIters, 1.0);
1264 if (chebyshevAlgorithm_ ==
"opt_fourth") {
1265 betas = optimalWeightsImpl<ScalarType>(numIters);
1268 const ST invEig = MT(1) / (lambdaMax * boostFactor_);
1280 if (!zeroStartingSolution_) {
1282 Tpetra::deep_copy(X4, X);
1284 if (ck_.is_null()) {
1286 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1290 ck_->compute(Z, MT(4.0 / 3.0) * invEig, const_cast<V&>(D_inv),
1291 const_cast<MV&>(B), X4, STS::zero());
1294 X.update(betas[0], Z, STS::one());
1297 firstIterationWithZeroStartingSolution(Z, MT(4.0 / 3.0) * invEig, D_inv, B, X4);
1300 X.update(betas[0], Z, STS::zero());
1303 if (numIters > 1 && ck_.is_null()) {
1305 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1308 for (
int i = 1; i < numIters; ++i) {
1309 const ST zScale = (2.0 * i - 1.0) / (2.0 * i + 3.0);
1310 const ST rScale = MT((8.0 * i + 4.0) / (2.0 * i + 3.0)) * invEig;
1314 ck_->compute(Z, rScale, const_cast<V&>(D_inv),
1315 const_cast<MV&>(B), (X4), zScale);
1318 X.update(betas[i], Z, STS::one());
1322 template <
class ScalarType,
class MV>
1323 typename Chebyshev<ScalarType, MV>::MT
1324 Chebyshev<ScalarType, MV>::maxNormInf(
const MV& X) {
1327 return *std::max_element(norms.begin(), norms.end());
1330 template <
class ScalarType,
class MV>
1331 void Chebyshev<ScalarType, MV>::
1332 ifpackApplyImpl(
const op_type& A,
1341 #ifdef HAVE_IFPACK2_DEBUG
1342 const bool debug = debug_;
1344 const bool debug =
false;
1348 *out_ <<
" \\|B\\|_{\\infty} = " << maxNormInf(B) << endl;
1349 *out_ <<
" \\|X\\|_{\\infty} = " << maxNormInf(X) << endl;
1352 if (numIters <= 0) {
1355 const ST zero =
static_cast<ST
>(0.0);
1356 const ST one =
static_cast<ST
>(1.0);
1357 const ST two =
static_cast<ST
>(2.0);
1360 if (lambdaMin == one && lambdaMax == lambdaMin) {
1366 const ST alpha = lambdaMax / eigRatio;
1367 const ST beta = boostFactor_ * lambdaMax;
1368 const ST delta = two / (beta - alpha);
1369 const ST theta = (beta + alpha) / two;
1370 const ST s1 = theta * delta;
1373 *out_ <<
" alpha = " << alpha << endl
1374 <<
" beta = " << beta << endl
1375 <<
" delta = " << delta << endl
1376 <<
" theta = " << theta << endl
1377 <<
" s1 = " << s1 << endl;
1385 *out_ <<
" Iteration " << 1 <<
":" << endl
1386 <<
" - \\|D\\|_{\\infty} = " << D_->normInf() << endl;
1390 if (!zeroStartingSolution_) {
1393 if (ck_.is_null()) {
1395 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1399 ck_->compute(W, one / theta, const_cast<V&>(D_inv),
1400 const_cast<MV&>(B), X, zero);
1403 firstIterationWithZeroStartingSolution(W, one / theta, D_inv, B, X);
1407 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf(W) << endl
1408 <<
" - \\|X\\|_{\\infty} = " << maxNormInf(X) << endl;
1411 if (numIters > 1 && ck_.is_null()) {
1413 ck_ =
Teuchos::rcp(
new ChebyshevKernel<op_type>(A_op, ckUseNativeSpMV_));
1418 ST rhokp1, dtemp1, dtemp2;
1419 for (
int deg = 1; deg < numIters; ++deg) {
1421 *out_ <<
" Iteration " << deg + 1 <<
":" << endl
1422 <<
" - \\|D\\|_{\\infty} = " << D_->normInf() << endl
1423 <<
" - \\|B\\|_{\\infty} = " << maxNormInf(B) << endl
1424 <<
" - \\|A\\|_{\\text{frob}} = " << A_->getFrobeniusNorm()
1426 <<
" - rhok = " << rhok << endl;
1429 rhokp1 = one / (two * s1 - rhok);
1430 dtemp1 = rhokp1 * rhok;
1431 dtemp2 = two * rhokp1 * delta;
1435 *out_ <<
" - dtemp1 = " << dtemp1 << endl
1436 <<
" - dtemp2 = " << dtemp2 << endl;
1441 ck_->compute(W, dtemp2, const_cast<V&>(D_inv),
1442 const_cast<MV&>(B), (X), dtemp1);
1445 *out_ <<
" - \\|W\\|_{\\infty} = " << maxNormInf(W) << endl
1446 <<
" - \\|X\\|_{\\infty} = " << maxNormInf(X) << endl;
1451 template <
class ScalarType,
class MV>
1452 typename Chebyshev<ScalarType, MV>::ST
1453 Chebyshev<ScalarType, MV>::
1454 cgMethodWithInitGuess(
const op_type& A,
1459 using MagnitudeType =
typename STS::magnitudeType;
1461 *out_ <<
" cgMethodWithInitGuess:" << endl;
1464 const ST one = STS::one();
1465 ST beta, betaOld = one, pAp, pApOld = one, alpha, rHz, rHzOld, rHzOld2 = one, lambdaMax;
1470 offdiag.
resize(numIters - 1);
1472 p =
rcp(
new V(A.getRangeMap()));
1473 z =
rcp(
new V(A.getRangeMap()));
1474 Ap =
rcp(
new V(A.getRangeMap()));
1477 solve(*p, D_inv, r);
1480 for (
int iter = 0; iter < numIters; ++iter) {
1482 *out_ <<
" Iteration " << iter << endl;
1487 r.update(-alpha, *Ap, one);
1489 solve(*z, D_inv, r);
1491 beta = rHz / rHzOld;
1492 p->update(one, *z, beta);
1494 diag[iter] = STS::real((betaOld * betaOld * pApOld + pAp) / rHzOld);
1495 offdiag[iter - 1] = -STS::real((betaOld * pApOld / (sqrt(rHzOld * rHzOld2))));
1497 *out_ <<
" diag[" << iter <<
"] = " << diag[iter] << endl;
1498 *out_ <<
" offdiag[" << iter - 1 <<
"] = " << offdiag[iter - 1] << endl;
1499 *out_ <<
" rHz = " << rHz << endl;
1500 *out_ <<
" alpha = " << alpha << endl;
1501 *out_ <<
" beta = " << beta << endl;
1504 diag[iter] = STS::real(pAp / rHzOld);
1506 *out_ <<
" diag[" << iter <<
"] = " << diag[iter] << endl;
1507 *out_ <<
" rHz = " << rHz << endl;
1508 *out_ <<
" alpha = " << alpha << endl;
1509 *out_ <<
" beta = " << beta << endl;
1517 lambdaMax = LapackHelper<ST>::tri_diag_spectral_radius(diag, offdiag);
1522 template <
class ScalarType,
class MV>
1523 typename Chebyshev<ScalarType, MV>::ST
1524 Chebyshev<ScalarType, MV>::
1525 cgMethod(
const op_type& A,
const V& D_inv,
const int numIters) {
1529 *out_ <<
"cgMethod:" << endl;
1533 if (eigVector_.is_null()) {
1534 r =
rcp(
new V(A.getDomainMap()));
1535 if (eigKeepVectors_)
1538 Details::computeInitialGuessForCG(D_inv, *r);
1542 ST lambdaMax = cgMethodWithInitGuess(A, D_inv, numIters, *r);
1547 template <
class ScalarType,
class MV>
1553 template <
class ScalarType,
class MV>
1560 template <
class ScalarType,
class MV>
1568 const size_t B_numVecs = B.getNumVectors();
1569 if (W_.is_null() || W_->getNumVectors() != B_numVecs) {
1570 W_ =
Teuchos::rcp(
new MV(B.getMap(), B_numVecs,
false));
1575 template <
class ScalarType,
class MV>
1577 Chebyshev<ScalarType, MV>::
1578 makeSecondTempMultiVector(
const MV& B) {
1583 const size_t B_numVecs = B.getNumVectors();
1584 if (W2_.is_null() || W2_->getNumVectors() != B_numVecs) {
1585 W2_ =
Teuchos::rcp(
new MV(B.getMap(), B_numVecs,
false));
1590 template <
class ScalarType,
class MV>
1594 std::ostringstream oss;
1597 oss <<
"\"Ifpack2::Details::Chebyshev\":"
1599 <<
"degree: " << numIters_
1600 <<
", lambdaMax: " << lambdaMaxForApply_
1601 <<
", alpha: " << eigRatioForApply_
1602 <<
", lambdaMin: " << lambdaMinForApply_
1603 <<
", boost factor: " << boostFactor_
1604 <<
", algorithm: " << chebyshevAlgorithm_;
1605 if (!userInvDiag_.is_null())
1606 oss <<
", diagonal: user-supplied";
1611 template <
class ScalarType,
class MV>
1639 myRank = A_->getComm()->getRank();
1644 out <<
"\"Ifpack2::Details::Chebyshev\":" << endl;
1650 out <<
"degree: " << numIters_ << endl
1651 <<
"lambdaMax: " << lambdaMaxForApply_ << endl
1652 <<
"alpha: " << eigRatioForApply_ << endl
1653 <<
"lambdaMin: " << lambdaMinForApply_ << endl
1654 <<
"boost factor: " << boostFactor_ << endl;
1662 out <<
"Template parameters:" << endl;
1665 out <<
"ScalarType: " << TypeNameTraits<ScalarType>::name() << endl
1666 <<
"MV: " << TypeNameTraits<MV>::name() << endl;
1672 out <<
"Computed parameters:" << endl;
1686 out <<
"unset" << endl;
1690 out <<
"set" << endl;
1698 D_->describe(out, vl);
1703 out <<
"W_: " << (W_.is_null() ?
"unset" :
"set") << endl
1704 <<
"computedLambdaMax_: " << computedLambdaMax_ << endl
1705 <<
"computedLambdaMin_: " << computedLambdaMin_ << endl
1706 <<
"lambdaMaxForApply_: " << lambdaMaxForApply_ << endl
1707 <<
"lambdaMinForApply_: " << lambdaMinForApply_ << endl
1708 <<
"eigRatioForApply_: " << eigRatioForApply_ << endl;
1713 out <<
"User parameters:" << endl;
1719 out <<
"userInvDiag_: ";
1720 if (userInvDiag_.is_null()) {
1721 out <<
"unset" << endl;
1723 out <<
"set" << endl;
1728 userInvDiag_->describe(out, vl);
1731 out <<
"userLambdaMax_: " << userLambdaMax_ << endl
1732 <<
"userLambdaMin_: " << userLambdaMin_ << endl
1733 <<
"userEigRatio_: " << userEigRatio_ << endl
1734 <<
"numIters_: " << numIters_ << endl
1735 <<
"eigMaxIters_: " << eigMaxIters_ << endl
1736 <<
"eigRelTolerance_: " << eigRelTolerance_ << endl
1737 <<
"eigNormalizationFreq_: " << eigNormalizationFreq_ << endl
1738 <<
"zeroStartingSolution_: " << zeroStartingSolution_ << endl
1739 <<
"assumeMatrixUnchanged_: " << assumeMatrixUnchanged_ << endl
1740 <<
"chebyshevAlgorithm_: " << chebyshevAlgorithm_ << endl
1741 <<
"computeMaxResNorm_: " << computeMaxResNorm_ << endl;
1749 #define IFPACK2_DETAILS_CHEBYSHEV_INSTANT(S, LO, GO, N) \
1750 template class Ifpack2::Details::Chebyshev<S, Tpetra::MultiVector<S, LO, GO, N>>;
1752 #endif // IFPACK2_DETAILS_CHEBYSHEV_DEF_HPP
void setParameters(Teuchos::ParameterList &plist)
Set (or reset) parameters.
Definition: Ifpack2_Details_Chebyshev_def.hpp:326
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:959
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:1613
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:734
#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:1549
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:263
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:1009
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:1593
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:1555
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:770
basic_oblackholestream< char, std::char_traits< char > > oblackholestream