10 #ifndef IFPACK2_RELAXATION_DEF_HPP
11 #define IFPACK2_RELAXATION_DEF_HPP
13 #include "Teuchos_StandardParameterEntryValidators.hpp"
15 #include "Tpetra_CrsMatrix.hpp"
16 #include "Tpetra_BlockCrsMatrix.hpp"
17 #include "Tpetra_BlockView.hpp"
19 #include "Ifpack2_Details_getCrsMatrix.hpp"
20 #include "MatrixMarket_Tpetra.hpp"
21 #include "Tpetra_Details_residual.hpp"
25 #include "KokkosSparse_gauss_seidel.hpp"
32 NonnegativeIntValidator() {}
42 const std::string& paramName,
43 const std::string& sublistName)
const {
49 anyVal.
type() !=
typeid(int),
51 "Parameter \"" << paramName <<
"\" in sublist \"" << sublistName
52 <<
"\" has the wrong type." << endl
53 <<
"Parameter: " << paramName
55 <<
"Type specified: " << entryName << endl
56 <<
"Type required: int" << endl);
58 const int val = Teuchos::any_cast<
int>(anyVal);
61 "Parameter \"" << paramName <<
"\" in sublist \"" << sublistName
62 <<
"\" is negative." << endl
63 <<
"Parameter: " << paramName
65 <<
"Value specified: " << val << endl
66 <<
"Required range: [0, INT_MAX]" << endl);
71 return "NonnegativeIntValidator";
76 printDoc(
const std::string& docString,
77 std::ostream& out)
const {
79 out <<
"#\tValidator Used: " << std::endl;
80 out <<
"#\t\tNonnegativeIntValidator" << std::endl;
87 template <class Scalar, const bool isOrdinal = Teuchos::ScalarTraits<Scalar>::isOrdinal>
91 static const Scalar eps();
95 template <
class Scalar>
96 class SmallTraits<Scalar, true> {
98 static const Scalar eps() {
104 template <
class Scalar>
105 class SmallTraits<Scalar, false> {
107 static const Scalar eps() {
113 template <
class Scalar,
115 struct RealTraits {};
117 template <
class Scalar>
118 struct RealTraits<Scalar, false> {
119 using val_type = Scalar;
120 using mag_type = Scalar;
121 static KOKKOS_INLINE_FUNCTION mag_type real(
const val_type& z) {
126 template <
class Scalar>
127 struct RealTraits<Scalar, true> {
128 using val_type = Scalar;
130 static KOKKOS_INLINE_FUNCTION mag_type real(
const val_type& z) {
131 return Kokkos::ArithTraits<val_type>::real(z);
135 template <
class Scalar>
136 KOKKOS_INLINE_FUNCTION
typename RealTraits<Scalar>::mag_type
137 getRealValue(
const Scalar& z) {
138 return RealTraits<Scalar>::real(z);
145 template <
class MatrixType>
146 void Relaxation<MatrixType>::
147 updateCachedMultiVector(
const Teuchos::RCP<
const Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>>& map,
148 size_t numVecs)
const {
151 if (cachedMV_.is_null() ||
152 map.get() != cachedMV_->getMap().get() ||
153 cachedMV_->getNumVectors() != numVecs) {
154 using MV = Tpetra::MultiVector<scalar_type, local_ordinal_type,
155 global_ordinal_type, node_type>;
160 template <
class MatrixType>
164 Importer_ = Teuchos::null;
165 pointImporter_ = Teuchos::null;
166 Diagonal_ = Teuchos::null;
167 isInitialized_ =
false;
169 diagOffsets_ = Kokkos::View<size_t*, device_type>();
170 savedDiagOffsets_ =
false;
171 hasBlockCrsMatrix_ =
false;
172 serialGaussSeidel_ = Teuchos::null;
174 IsParallel_ = (A->getRowMap()->getComm()->getSize() > 1);
180 template <
class MatrixType>
184 , IsParallel_((A.
is_null() || A->getRowMap().
is_null() || A->getRowMap()->getComm().
is_null()) ? false :
185 A->getRowMap()->getComm()->getSize() > 1) {
186 this->setObjectLabel(
"Ifpack2::Relaxation");
189 template <
class MatrixType>
194 using Teuchos::parameterList;
197 using Teuchos::rcp_const_cast;
198 using Teuchos::rcp_implicit_cast;
199 using Teuchos::setStringToIntegralParameter;
202 if (validParams_.is_null()) {
203 RCP<ParameterList> pl = parameterList(
"Ifpack2::Relaxation");
207 Array<std::string> precTypes(8);
208 precTypes[0] =
"Jacobi";
209 precTypes[1] =
"Gauss-Seidel";
210 precTypes[2] =
"Symmetric Gauss-Seidel";
211 precTypes[3] =
"MT Gauss-Seidel";
212 precTypes[4] =
"MT Symmetric Gauss-Seidel";
213 precTypes[5] =
"Richardson";
214 precTypes[6] =
"Two-stage Gauss-Seidel";
215 precTypes[7] =
"Two-stage Symmetric Gauss-Seidel";
216 Array<Details::RelaxationType> precTypeEnums(8);
217 precTypeEnums[0] = Details::JACOBI;
218 precTypeEnums[1] = Details::GS;
219 precTypeEnums[2] = Details::SGS;
220 precTypeEnums[3] = Details::MTGS;
221 precTypeEnums[4] = Details::MTSGS;
222 precTypeEnums[5] = Details::RICHARDSON;
223 precTypeEnums[6] = Details::GS2;
224 precTypeEnums[7] = Details::SGS2;
225 const std::string defaultPrecType(
"Jacobi");
226 setStringToIntegralParameter<Details::RelaxationType>(
"relaxation: type",
227 defaultPrecType,
"Relaxation method", precTypes(), precTypeEnums(),
230 const int numSweeps = 1;
231 RCP<PEV> numSweepsValidator =
232 rcp_implicit_cast<PEV>(
rcp(
new NonnegativeIntValidator));
233 pl->set(
"relaxation: sweeps", numSweeps,
"Number of relaxation sweeps",
234 rcp_const_cast<const PEV>(numSweepsValidator));
237 const int numOuterSweeps = 1;
238 RCP<PEV> numOuterSweepsValidator =
239 rcp_implicit_cast<PEV>(
rcp(
new NonnegativeIntValidator));
240 pl->set(
"relaxation: outer sweeps", numOuterSweeps,
"Number of outer local relaxation sweeps for two-stage GS",
241 rcp_const_cast<const PEV>(numOuterSweepsValidator));
243 const int numInnerSweeps = 1;
244 RCP<PEV> numInnerSweepsValidator =
245 rcp_implicit_cast<PEV>(
rcp(
new NonnegativeIntValidator));
246 pl->set(
"relaxation: inner sweeps", numInnerSweeps,
"Number of inner local relaxation sweeps for two-stage GS",
247 rcp_const_cast<const PEV>(numInnerSweepsValidator));
250 pl->set(
"relaxation: inner damping factor", innerDampingFactor,
"Damping factor for the inner sweep of two-stage GS");
252 const bool innerSpTrsv =
false;
253 pl->set(
"relaxation: inner sparse-triangular solve", innerSpTrsv,
"Specify whether to use sptrsv instead of JR iterations for two-stage GS");
255 const bool compactForm =
false;
256 pl->set(
"relaxation: compact form", compactForm,
"Specify whether to use compact form of recurrence for two-stage GS");
259 pl->set(
"relaxation: damping factor", dampingFactor);
261 const bool zeroStartingSolution =
true;
262 pl->set(
"relaxation: zero starting solution", zeroStartingSolution);
264 const bool doBackwardGS =
false;
265 pl->set(
"relaxation: backward mode", doBackwardGS);
267 const bool doL1Method =
false;
268 pl->set(
"relaxation: use l1", doL1Method);
270 const magnitude_type l1eta = (STM::one() + STM::one() + STM::one()) /
271 (STM::one() + STM::one());
272 pl->set(
"relaxation: l1 eta", l1eta);
275 pl->set(
"relaxation: min diagonal value", minDiagonalValue);
277 const bool fixTinyDiagEntries =
false;
278 pl->set(
"relaxation: fix tiny diagonal entries", fixTinyDiagEntries);
280 const bool checkDiagEntries =
false;
281 pl->set(
"relaxation: check diagonal entries", checkDiagEntries);
284 pl->set(
"relaxation: local smoothing indices", localSmoothingIndices);
286 const bool is_matrix_structurally_symmetric =
false;
287 pl->set(
"relaxation: symmetric matrix structure", is_matrix_structurally_symmetric);
289 const bool ifpack2_dump_matrix =
false;
290 pl->set(
"relaxation: ifpack2 dump matrix", ifpack2_dump_matrix);
292 const int cluster_size = 1;
293 pl->set(
"relaxation: mtgs cluster size", cluster_size);
295 pl->set(
"relaxation: mtgs coloring algorithm",
"Default");
297 const int long_row_threshold = 0;
298 pl->set(
"relaxation: long row threshold", long_row_threshold);
300 const bool timer_for_apply =
true;
301 pl->set(
"timer for apply", timer_for_apply);
303 validParams_ = rcp_const_cast<
const ParameterList>(pl);
308 template <
class MatrixType>
310 using Teuchos::getIntegralValue;
311 using Teuchos::getStringValue;
314 typedef scalar_type ST;
316 if (pl.
isType<
double>(
"relaxation: damping factor")) {
319 ST df = pl.
get<
double>(
"relaxation: damping factor");
320 pl.
remove(
"relaxation: damping factor");
321 pl.
set(
"relaxation: damping factor", df);
326 const Details::RelaxationType precType =
327 getIntegralValue<Details::RelaxationType>(pl,
"relaxation: type");
328 const std::string precTypeStr = getStringValue<Details::RelaxationType>(pl,
"relaxation: type");
330 pl.set<std::string>(
"relaxation: type", precTypeStr);
331 pl.get<std::string>(
"relaxation: type");
332 const int numSweeps = pl.get<
int>(
"relaxation: sweeps");
333 const ST dampingFactor = pl.get<ST>(
"relaxation: damping factor");
334 const bool zeroStartSol = pl.get<
bool>(
"relaxation: zero starting solution");
335 const bool doBackwardGS = pl.get<
bool>(
"relaxation: backward mode");
336 const bool doL1Method = pl.get<
bool>(
"relaxation: use l1");
337 const magnitude_type l1Eta = pl.get<magnitude_type>(
"relaxation: l1 eta");
338 const ST minDiagonalValue = pl.get<ST>(
"relaxation: min diagonal value");
339 const bool fixTinyDiagEntries = pl.get<
bool>(
"relaxation: fix tiny diagonal entries");
340 const bool checkDiagEntries = pl.get<
bool>(
"relaxation: check diagonal entries");
341 const bool is_matrix_structurally_symmetric = pl.get<
bool>(
"relaxation: symmetric matrix structure");
342 const bool ifpack2_dump_matrix = pl.get<
bool>(
"relaxation: ifpack2 dump matrix");
343 const bool timer_for_apply = pl.get<
bool>(
"timer for apply");
344 int cluster_size = 1;
345 if (pl.isParameter(
"relaxation: mtgs cluster size"))
346 cluster_size = pl.get<
int>(
"relaxation: mtgs cluster size");
347 int long_row_threshold = 0;
348 if (pl.isParameter(
"relaxation: long row threshold"))
349 long_row_threshold = pl.get<
int>(
"relaxation: long row threshold");
350 std::string color_algo_name = pl.get<std::string>(
"relaxation: mtgs coloring algorithm");
352 for (
char& c : color_algo_name)
354 if (color_algo_name ==
"default")
355 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_DEFAULT;
356 else if (color_algo_name ==
"serial")
357 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_SERIAL;
358 else if (color_algo_name ==
"vb")
359 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VB;
360 else if (color_algo_name ==
"vbbit")
361 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBBIT;
362 else if (color_algo_name ==
"vbcs")
363 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBCS;
364 else if (color_algo_name ==
"vbd")
365 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBD;
366 else if (color_algo_name ==
"vbdbit")
367 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_VBDBIT;
368 else if (color_algo_name ==
"eb")
369 this->mtColoringAlgorithm_ = KokkosGraph::COLORING_EB;
371 std::ostringstream msg;
372 msg <<
"Ifpack2::Relaxation: 'relaxation: mtgs coloring algorithm' = '" << color_algo_name <<
"' is not valid.\n";
373 msg <<
"Choices (not case sensitive) are: Default, Serial, VB, VBBIT, VBCS, VBD, VBDBIT, EB.";
375 true, std::invalid_argument, msg.str());
381 if (!std::is_same<double, ST>::value && pl.isType<
double>(
"relaxation: inner damping factor")) {
384 ST df = pl.
get<
double>(
"relaxation: inner damping factor");
385 pl.remove(
"relaxation: inner damping factor");
386 pl.set(
"relaxation: inner damping factor", df);
389 if (long_row_threshold > 0) {
391 cluster_size != 1, std::invalid_argument,
392 "Ifpack2::Relaxation: "
393 "Requested long row MTGS/MTSGS algorithm and cluster GS/SGS, but those are not compatible.");
395 precType != Details::RelaxationType::MTGS && precType != Details::RelaxationType::MTSGS,
396 std::invalid_argument,
397 "Ifpack2::Relaxation: "
398 "Requested long row MTGS/MTSGS algorithm, but this is only compatible with preconditioner types "
399 "'MT Gauss-Seidel' and 'MT Symmetric Gauss-Seidel'.");
402 const ST innerDampingFactor = pl.get<ST>(
"relaxation: inner damping factor");
403 const int numInnerSweeps = pl.get<
int>(
"relaxation: inner sweeps");
404 const int numOuterSweeps = pl.get<
int>(
"relaxation: outer sweeps");
405 const bool innerSpTrsv = pl.get<
bool>(
"relaxation: inner sparse-triangular solve");
406 const bool compactForm = pl.get<
bool>(
"relaxation: compact form");
409 PrecType_ = precType;
410 NumSweeps_ = numSweeps;
411 DampingFactor_ = dampingFactor;
412 ZeroStartingSolution_ = zeroStartSol;
413 DoBackwardGS_ = doBackwardGS;
414 DoL1Method_ = doL1Method;
416 MinDiagonalValue_ = minDiagonalValue;
417 fixTinyDiagEntries_ = fixTinyDiagEntries;
418 checkDiagEntries_ = checkDiagEntries;
419 clusterSize_ = cluster_size;
420 longRowThreshold_ = long_row_threshold;
421 is_matrix_structurally_symmetric_ = is_matrix_structurally_symmetric;
422 ifpack2_dump_matrix_ = ifpack2_dump_matrix;
423 localSmoothingIndices_ = localSmoothingIndices;
425 NumInnerSweeps_ = numInnerSweeps;
426 NumOuterSweeps_ = numOuterSweeps;
427 InnerSpTrsv_ = innerSpTrsv;
428 InnerDampingFactor_ = innerDampingFactor;
429 CompactForm_ = compactForm;
430 TimerForApply_ = timer_for_apply;
433 template <
class MatrixType>
437 this->setParametersImpl(const_cast<Teuchos::ParameterList&>(pl));
440 template <
class MatrixType>
444 A_.
is_null(), std::runtime_error,
445 "Ifpack2::Relaxation::getComm: "
446 "The input matrix A is null. Please call setMatrix() with a nonnull "
447 "input matrix before calling this method.");
448 return A_->getRowMap()->getComm();
451 template <
class MatrixType>
457 template <
class MatrixType>
458 Teuchos::RCP<
const Tpetra::Map<
typename MatrixType::local_ordinal_type,
459 typename MatrixType::global_ordinal_type,
460 typename MatrixType::node_type>>
463 A_.
is_null(), std::runtime_error,
464 "Ifpack2::Relaxation::getDomainMap: "
465 "The input matrix A is null. Please call setMatrix() with a nonnull "
466 "input matrix before calling this method.");
467 return A_->getDomainMap();
470 template <
class MatrixType>
471 Teuchos::RCP<
const Tpetra::Map<
typename MatrixType::local_ordinal_type,
472 typename MatrixType::global_ordinal_type,
473 typename MatrixType::node_type>>
476 A_.
is_null(), std::runtime_error,
477 "Ifpack2::Relaxation::getRangeMap: "
478 "The input matrix A is null. Please call setMatrix() with a nonnull "
479 "input matrix before calling this method.");
480 return A_->getRangeMap();
483 template <
class MatrixType>
488 template <
class MatrixType>
490 return (NumInitialize_);
493 template <
class MatrixType>
495 return (NumCompute_);
498 template <
class MatrixType>
503 template <
class MatrixType>
505 return (InitializeTime_);
508 template <
class MatrixType>
510 return (ComputeTime_);
513 template <
class MatrixType>
518 template <
class MatrixType>
520 return (ComputeFlops_);
523 template <
class MatrixType>
525 return (ApplyFlops_);
528 template <
class MatrixType>
531 A_.
is_null(), std::runtime_error,
532 "Ifpack2::Relaxation::getNodeSmootherComplexity: "
533 "The input matrix A is null. Please call setMatrix() with a nonnull "
534 "input matrix, then call compute(), before calling this method.");
536 return A_->getLocalNumRows() + A_->getLocalNumEntries();
539 template <
class MatrixType>
541 apply(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
542 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
549 using Teuchos::rcpFromRef;
554 A_.
is_null(), std::runtime_error,
555 "Ifpack2::Relaxation::apply: "
556 "The input matrix A is null. Please call setMatrix() with a nonnull "
557 "input matrix, then call compute(), before calling this method.");
561 "Ifpack2::Relaxation::apply: You must call compute() on this Ifpack2 "
562 "preconditioner instance before you may call apply(). You may call "
563 "isComputed() to find out if compute() has been called already.");
564 TEUCHOS_TEST_FOR_EXCEPTION(
565 X.getNumVectors() != Y.getNumVectors(),
567 "Ifpack2::Relaxation::apply: X and Y have different numbers of columns. "
569 << X.getNumVectors() <<
" columns, but Y has "
570 << Y.getNumVectors() <<
" columns.");
571 TEUCHOS_TEST_FOR_EXCEPTION(
572 beta != STS::zero(), std::logic_error,
573 "Ifpack2::Relaxation::apply: beta = " << beta <<
" != 0 case not "
577 const std::string timerName(
"Ifpack2::Relaxation::apply");
578 if (TimerForApply_) {
594 if (alpha == STS::zero()) {
596 Y.putScalar(STS::zero());
605 Xcopy = rcpFromRef(X);
613 case Ifpack2::Details::JACOBI:
614 ApplyInverseJacobi(*Xcopy, Y);
616 case Ifpack2::Details::GS:
617 ApplyInverseSerialGS(*Xcopy, Y, DoBackwardGS_ ? Tpetra::Backward : Tpetra::Forward);
619 case Ifpack2::Details::SGS:
620 ApplyInverseSerialGS(*Xcopy, Y, Tpetra::Symmetric);
622 case Ifpack2::Details::MTGS:
623 case Ifpack2::Details::GS2:
624 ApplyInverseMTGS_CrsMatrix(*Xcopy, Y, DoBackwardGS_ ? Tpetra::Backward : Tpetra::Forward);
626 case Ifpack2::Details::MTSGS:
627 case Ifpack2::Details::SGS2:
628 ApplyInverseMTGS_CrsMatrix(*Xcopy, Y, Tpetra::Symmetric);
630 case Ifpack2::Details::RICHARDSON:
631 ApplyInverseRichardson(*Xcopy, Y);
635 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
636 "Ifpack2::Relaxation::apply: Invalid preconditioner type enum value "
637 << PrecType_ <<
". Please report this bug to the Ifpack2 developers.");
639 if (alpha != STS::one()) {
641 const double numGlobalRows = as<double>(A_->getGlobalNumRows());
642 const double numVectors = as<double>(Y.getNumVectors());
643 ApplyFlops_ += numGlobalRows * numVectors;
647 ApplyTime_ += (time.
wallTime() - startTime);
651 template <
class MatrixType>
653 applyMat(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
654 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
657 A_.
is_null(), std::runtime_error,
658 "Ifpack2::Relaxation::applyMat: "
659 "The input matrix A is null. Please call setMatrix() with a nonnull "
660 "input matrix, then call compute(), before calling this method.");
662 !isComputed(), std::runtime_error,
663 "Ifpack2::Relaxation::applyMat: "
664 "isComputed() must be true before you may call applyMat(). "
665 "Please call compute() before calling this method.");
666 TEUCHOS_TEST_FOR_EXCEPTION(
667 X.getNumVectors() != Y.getNumVectors(), std::invalid_argument,
668 "Ifpack2::Relaxation::applyMat: X.getNumVectors() = " << X.getNumVectors()
669 <<
" != Y.getNumVectors() = " << Y.getNumVectors() <<
".");
670 A_->apply(X, Y, mode);
673 template <
class MatrixType>
675 const char methodName[] =
"Ifpack2::Relaxation::initialize";
678 "input matrix A is null. Please call setMatrix() with "
679 "a nonnull input matrix before calling this method.");
684 double startTime = timer->wallTime();
688 isInitialized_ =
false;
691 auto rowMap = A_->getRowMap();
692 auto comm = rowMap.
is_null() ? Teuchos::null : rowMap->getComm();
693 IsParallel_ = !comm.is_null() && comm->getSize() > 1;
703 Importer_ = IsParallel_ ? A_->getGraph()->getImporter() : Teuchos::null;
707 Teuchos::rcp_dynamic_cast<
const block_crs_matrix_type>(A_);
708 hasBlockCrsMatrix_ = !A_bcrs.
is_null();
711 serialGaussSeidel_ = Teuchos::null;
713 if (PrecType_ == Details::MTGS || PrecType_ == Details::MTSGS ||
714 PrecType_ == Details::GS2 || PrecType_ == Details::SGS2) {
715 auto crsMat = Details::getCrsMatrix(A_);
717 "Multithreaded Gauss-Seidel methods currently only work "
718 "when the input matrix is a Tpetra::CrsMatrix.");
723 if (ifpack2_dump_matrix_) {
724 static int sequence_number = 0;
725 const std::string file_name =
"Ifpack2_MT_GS_" +
726 std::to_string(sequence_number++) +
".mtx";
727 using writer_type = Tpetra::MatrixMarket::Writer<crs_matrix_type>;
728 writer_type::writeSparseFile(file_name, crsMat);
731 this->mtKernelHandle_ =
Teuchos::rcp(
new mt_kernel_handle_type());
732 if (mtKernelHandle_->get_gs_handle() ==
nullptr) {
733 if (PrecType_ == Details::GS2 || PrecType_ == Details::SGS2)
734 mtKernelHandle_->create_gs_handle(KokkosSparse::GS_TWOSTAGE);
735 else if (this->clusterSize_ == 1) {
736 mtKernelHandle_->create_gs_handle(KokkosSparse::GS_DEFAULT, this->mtColoringAlgorithm_);
737 mtKernelHandle_->get_point_gs_handle()->set_long_row_threshold(longRowThreshold_);
739 mtKernelHandle_->create_gs_handle(KokkosSparse::CLUSTER_DEFAULT, this->clusterSize_, this->mtColoringAlgorithm_);
741 local_matrix_device_type kcsr = crsMat->getLocalMatrixDevice();
742 if (PrecType_ == Details::GS2 || PrecType_ == Details::SGS2) {
744 mtKernelHandle_->set_gs_set_num_inner_sweeps(NumInnerSweeps_);
745 mtKernelHandle_->set_gs_set_num_outer_sweeps(NumOuterSweeps_);
746 mtKernelHandle_->set_gs_set_inner_damp_factor(InnerDampingFactor_);
747 mtKernelHandle_->set_gs_twostage(!InnerSpTrsv_, A_->getLocalNumRows());
748 mtKernelHandle_->set_gs_twostage_compact_form(CompactForm_);
751 KokkosSparse::gauss_seidel_symbolic(
752 mtKernelHandle_.getRawPtr(),
753 A_->getLocalNumRows(),
754 A_->getLocalNumCols(),
757 is_matrix_structurally_symmetric_);
761 InitializeTime_ += (timer->wallTime() - startTime);
763 isInitialized_ =
true;
767 template <
typename BlockDiagView>
768 struct InvertDiagBlocks {
769 typedef typename BlockDiagView::size_type Size;
772 typedef Kokkos::MemoryTraits<Kokkos::Unmanaged> Unmanaged;
773 template <
typename View>
774 using UnmanagedView = Kokkos::View<
typename View::data_type,
typename View::array_layout,
775 typename View::device_type, Unmanaged>;
777 typedef typename BlockDiagView::non_const_value_type Scalar;
778 typedef typename BlockDiagView::device_type Device;
779 typedef Kokkos::View<Scalar**, Kokkos::LayoutRight, Device> RWrk;
780 typedef Kokkos::View<int**, Kokkos::LayoutRight, Device> IWrk;
782 UnmanagedView<BlockDiagView> block_diag_;
786 UnmanagedView<RWrk> rwrk_;
788 UnmanagedView<IWrk> iwrk_;
791 InvertDiagBlocks(BlockDiagView& block_diag)
792 : block_diag_(block_diag) {
793 const auto blksz = block_diag.extent(1);
794 Kokkos::resize(rwrk_buf_, block_diag_.extent(0), blksz);
796 Kokkos::resize(iwrk_buf_, block_diag_.extent(0), blksz);
800 KOKKOS_INLINE_FUNCTION
801 void operator()(
const Size i,
int& jinfo)
const {
802 auto D_cur = Kokkos::subview(block_diag_, i, Kokkos::ALL(), Kokkos::ALL());
803 auto ipiv = Kokkos::subview(iwrk_, i, Kokkos::ALL());
804 auto work = Kokkos::subview(rwrk_, i, Kokkos::ALL());
806 Tpetra::GETF2(D_cur, ipiv, info);
811 Tpetra::GETRI(D_cur, ipiv, work, info);
817 template <
class MatrixType>
818 void Relaxation<MatrixType>::computeBlockCrs() {
827 using Teuchos::rcp_dynamic_cast;
831 using Teuchos::reduceAll;
832 typedef local_ordinal_type LO;
834 const std::string timerName(
"Ifpack2::Relaxation::computeBlockCrs");
839 double startTime = timer->
wallTime();
844 A_.
is_null(), std::runtime_error,
845 "Ifpack2::Relaxation::"
846 "computeBlockCrs: The input matrix A is null. Please call setMatrix() "
847 "with a nonnull input matrix, then call initialize(), before calling "
849 auto blockCrsA = rcp_dynamic_cast<
const block_crs_matrix_type>(A_);
851 blockCrsA.is_null(), std::logic_error,
852 "Ifpack2::Relaxation::"
853 "computeBlockCrs: A_ is not a BlockCrsMatrix, but it should be if we "
854 "got this far. Please report this bug to the Ifpack2 developers.");
856 const scalar_type one = STS::one();
861 const LO lclNumMeshRows =
862 blockCrsA->getCrsGraph().getLocalNumRows();
863 const LO blockSize = blockCrsA->getBlockSize();
865 if (!savedDiagOffsets_) {
866 blockDiag_ = block_diag_type();
867 blockDiag_ = block_diag_type(
"Ifpack2::Relaxation::blockDiag_",
868 lclNumMeshRows, blockSize, blockSize);
869 if (Teuchos::as<LO>(diagOffsets_.extent(0)) < lclNumMeshRows) {
872 diagOffsets_ = Kokkos::View<size_t*, device_type>();
873 diagOffsets_ = Kokkos::View<size_t*, device_type>(
"offsets", lclNumMeshRows);
875 blockCrsA->getCrsGraph().getLocalDiagOffsets(diagOffsets_);
877 static_cast<size_t>(blockDiag_.extent(0)),
878 std::logic_error,
"diagOffsets_.extent(0) = " << diagOffsets_.extent(0) <<
" != blockDiag_.extent(0) = " << blockDiag_.extent(0) <<
". Please report this bug to the Ifpack2 developers.");
879 savedDiagOffsets_ =
true;
881 blockCrsA->getLocalDiagCopy(blockDiag_, diagOffsets_);
888 unmanaged_block_diag_type blockDiag = blockDiag_;
890 if (DoL1Method_ && IsParallel_) {
891 const scalar_type two = one + one;
892 const size_t maxLength = A_->getLocalMaxNumRowEntries();
893 nonconst_local_inds_host_view_type indices(
"indices", maxLength);
894 nonconst_values_host_view_type values_(
"values", maxLength * blockSize * blockSize);
895 size_t numEntries = 0;
897 for (LO i = 0; i < lclNumMeshRows; ++i) {
899 blockCrsA->getLocalRowCopy(i, indices, values_, numEntries);
900 scalar_type* values =
reinterpret_cast<scalar_type*
>(values_.data());
902 auto diagBlock = Kokkos::subview(blockDiag, i, ALL(), ALL());
903 for (LO subRow = 0; subRow < blockSize; ++subRow) {
904 magnitude_type diagonal_boost = STM::zero();
905 for (
size_t k = 0; k < numEntries; ++k) {
906 if (indices[k] >= lclNumMeshRows) {
907 const size_t offset = blockSize * blockSize * k + subRow * blockSize;
908 for (LO subCol = 0; subCol < blockSize; ++subCol) {
909 diagonal_boost += STS::magnitude(values[offset + subCol] / two);
913 if (STS::magnitude(diagBlock(subRow, subRow)) < L1Eta_ * diagonal_boost) {
914 diagBlock(subRow, subRow) += diagonal_boost;
922 Impl::InvertDiagBlocks<unmanaged_block_diag_type> idb(blockDiag);
923 typedef typename unmanaged_block_diag_type::execution_space exec_space;
924 typedef Kokkos::RangePolicy<exec_space, LO> range_type;
926 Kokkos::parallel_reduce(range_type(0, lclNumMeshRows), idb, info);
936 #ifdef HAVE_IFPACK2_DEBUG
937 const int numResults = 2;
939 int lclResults[2], gblResults[2];
940 lclResults[0] = info;
941 lclResults[1] = -info;
944 reduceAll<int, int>(*(A_->getGraph()->getComm()), REDUCE_MIN,
945 numResults, lclResults, gblResults);
947 "Ifpack2::Relaxation::compute: When processing the input "
948 "Tpetra::BlockCrsMatrix, one or more diagonal block LU factorizations "
949 "failed on one or more (MPI) processes.");
950 #endif // HAVE_IFPACK2_DEBUG
951 serialGaussSeidel_ =
rcp(
new SerialGaussSeidel(blockCrsA, blockDiag_, localSmoothingIndices_, DampingFactor_));
954 ComputeTime_ += (timer->
wallTime() - startTime);
959 template <
class MatrixType>
971 using Teuchos::reduceAll;
975 using IST =
typename vector_type::impl_scalar_type;
976 using KAT = Kokkos::ArithTraits<IST>;
978 const char methodName[] =
"Ifpack2::Relaxation::compute";
979 const scalar_type zero = STS::zero();
980 const scalar_type one = STS::one();
983 "The input matrix A is null. Please call setMatrix() with a nonnull "
984 "input matrix, then call initialize(), before calling this method.");
987 if (!isInitialized()) {
991 if (hasBlockCrsMatrix_) {
998 double startTime = timer->
wallTime();
1010 IST oneOverMinDiagVal = KAT::one() /
static_cast<IST
>(SmallTraits<scalar_type>::eps());
1011 if (MinDiagonalValue_ != zero)
1012 oneOverMinDiagVal = KAT::one() /
static_cast<IST
>(MinDiagonalValue_);
1015 const magnitude_type minDiagValMag = STS::magnitude(MinDiagonalValue_);
1017 const LO numMyRows =
static_cast<LO
>(A_->getLocalNumRows());
1020 "Please report this bug to the Ifpack2 developers.");
1021 IsComputed_ =
false;
1023 if (Diagonal_.is_null()) {
1026 Diagonal_ =
rcp(
new vector_type(A_->getRowMap(),
false));
1029 if (checkDiagEntries_) {
1035 size_t numSmallDiagEntries = 0;
1036 size_t numZeroDiagEntries = 0;
1037 size_t numNegDiagEntries = 0;
1044 A_->getLocalDiagCopy(*Diagonal_);
1045 std::unique_ptr<vector_type> origDiag;
1046 origDiag = std::unique_ptr<vector_type>(
new vector_type(*Diagonal_,
Teuchos::Copy));
1047 auto diag2d = Diagonal_->getLocalViewHost(Tpetra::Access::ReadWrite);
1048 auto diag = Kokkos::subview(diag2d, Kokkos::ALL(), 0);
1055 if (numMyRows != 0) {
1057 minMagDiagEntryMag = d_0_mag;
1058 maxMagDiagEntryMag = d_0_mag;
1067 for (LO i = 0; i < numMyRows; ++i) {
1068 const IST d_i = diag(i);
1072 const auto d_i_real = getRealValue(d_i);
1076 if (d_i_real < STM::zero()) {
1077 ++numNegDiagEntries;
1079 if (d_i_mag < minMagDiagEntryMag) {
1080 minMagDiagEntryMag = d_i_mag;
1082 if (d_i_mag > maxMagDiagEntryMag) {
1083 maxMagDiagEntryMag = d_i_mag;
1086 if (fixTinyDiagEntries_) {
1088 if (d_i_mag <= minDiagValMag) {
1089 ++numSmallDiagEntries;
1090 if (d_i_mag == STM::zero()) {
1091 ++numZeroDiagEntries;
1093 diag(i) = oneOverMinDiagVal;
1095 diag(i) = KAT::one() / d_i;
1099 if (d_i_mag <= minDiagValMag) {
1100 ++numSmallDiagEntries;
1101 if (d_i_mag == STM::zero()) {
1102 ++numZeroDiagEntries;
1105 diag(i) = KAT::one() / d_i;
1123 const Comm<int>& comm = *(A_->getRowMap()->getComm());
1126 Array<magnitude_type> localVals(2);
1127 localVals[0] = minMagDiagEntryMag;
1129 localVals[1] = -maxMagDiagEntryMag;
1130 Array<magnitude_type> globalVals(2);
1131 reduceAll<int, magnitude_type>(comm, REDUCE_MIN, 2,
1132 localVals.getRawPtr(),
1133 globalVals.getRawPtr());
1134 globalMinMagDiagEntryMag_ = globalVals[0];
1135 globalMaxMagDiagEntryMag_ = -globalVals[1];
1137 Array<size_t> localCounts(3);
1138 localCounts[0] = numSmallDiagEntries;
1139 localCounts[1] = numZeroDiagEntries;
1140 localCounts[2] = numNegDiagEntries;
1141 Array<size_t> globalCounts(3);
1142 reduceAll<int, size_t>(comm, REDUCE_SUM, 3,
1143 localCounts.getRawPtr(),
1144 globalCounts.getRawPtr());
1145 globalNumSmallDiagEntries_ = globalCounts[0];
1146 globalNumZeroDiagEntries_ = globalCounts[1];
1147 globalNumNegDiagEntries_ = globalCounts[2];
1151 vector_type diff(A_->getRowMap());
1152 diff.reciprocal(*origDiag);
1153 diff.update(-one, *Diagonal_, one);
1154 globalDiagNormDiff_ = diff.norm2();
1161 bool debugAgainstSlowPath =
false;
1163 auto crsMat = Details::getCrsMatrix(A_);
1165 if (crsMat.get() && crsMat->isFillComplete()) {
1170 if (invDiagKernel_.is_null())
1173 invDiagKernel_->setMatrix(crsMat);
1174 invDiagKernel_->compute(*Diagonal_,
1175 DoL1Method_ && IsParallel_, L1Eta_,
1176 fixTinyDiagEntries_, minDiagValMag);
1177 savedDiagOffsets_ =
true;
1181 #ifdef HAVE_IFPACK2_DEBUG
1182 debugAgainstSlowPath =
true;
1186 if (crsMat.is_null() || !crsMat->isFillComplete() || debugAgainstSlowPath) {
1194 if (debugAgainstSlowPath)
1195 Diagonal =
rcp(
new vector_type(A_->getRowMap()));
1197 Diagonal = Diagonal_;
1199 A_->getLocalDiagCopy(*Diagonal);
1209 if (DoL1Method_ && IsParallel_) {
1211 auto diag = Diagonal->getLocalViewHost(Tpetra::Access::ReadWrite);
1213 const size_t maxLength = A_row.getLocalMaxNumRowEntries();
1214 nonconst_local_inds_host_view_type indices(
"indices", maxLength);
1215 nonconst_values_host_view_type values(
"values", maxLength);
1218 for (LO i = 0; i < numMyRows; ++i) {
1219 A_row.getLocalRowCopy(i, indices, values, numEntries);
1221 for (
size_t k = 0; k < numEntries; ++k) {
1222 if (indices[k] >= numMyRows) {
1223 diagonal_boost += STS::magnitude(values[k] / two);
1226 if (KAT::magnitude(diag(i, 0)) < L1Eta_ * diagonal_boost) {
1227 diag(i, 0) += diagonal_boost;
1235 if (fixTinyDiagEntries_) {
1239 auto localDiag = Diagonal->getLocalViewDevice(Tpetra::Access::ReadWrite);
1240 Kokkos::parallel_for(
1241 Kokkos::RangePolicy<MyExecSpace>(0, localDiag.extent(0)),
1242 KOKKOS_LAMBDA(local_ordinal_type i) {
1243 auto d_i = localDiag(i, 0);
1246 if (d_i_mag <= minDiagValMag) {
1247 d_i = oneOverMinDiagVal;
1251 d_i = IST(KAT::one() / d_i);
1253 localDiag(i, 0) = d_i;
1256 Diagonal->reciprocal(*Diagonal);
1259 if (debugAgainstSlowPath) {
1261 Diagonal->update(STS::one(), *Diagonal_, -STS::one());
1266 <<
"\"fast-path\" diagonal computation failed. "
1267 "\\|D1 - D2\\|_inf = "
1275 if (STS::isComplex) {
1276 ComputeFlops_ += 4.0 * numMyRows;
1278 ComputeFlops_ += numMyRows;
1281 if (PrecType_ == Ifpack2::Details::MTGS ||
1282 PrecType_ == Ifpack2::Details::MTSGS ||
1283 PrecType_ == Ifpack2::Details::GS2 ||
1284 PrecType_ == Ifpack2::Details::SGS2) {
1286 using scalar_view_t =
typename local_matrix_device_type::values_type;
1289 "Multithreaded Gauss-Seidel methods currently only work "
1290 "when the input matrix is a Tpetra::CrsMatrix.");
1291 local_matrix_device_type kcsr = crsMat->getLocalMatrixDevice();
1295 auto diagView_2d = Diagonal_->getLocalViewDevice(Tpetra::Access::ReadWrite);
1296 scalar_view_t diagView_1d = Kokkos::subview(diagView_2d, Kokkos::ALL(), 0);
1297 KokkosSparse::gauss_seidel_numeric(
1298 mtKernelHandle_.getRawPtr(),
1299 A_->getLocalNumRows(),
1300 A_->getLocalNumCols(),
1305 is_matrix_structurally_symmetric_);
1306 }
else if (PrecType_ == Ifpack2::Details::GS || PrecType_ == Ifpack2::Details::SGS) {
1308 serialGaussSeidel_ =
rcp(
new SerialGaussSeidel(crsMat, Diagonal_, localSmoothingIndices_, DampingFactor_));
1310 serialGaussSeidel_ =
rcp(
new SerialGaussSeidel(A_, Diagonal_, localSmoothingIndices_, DampingFactor_));
1314 ComputeTime_ += (timer->
wallTime() - startTime);
1319 template <
class MatrixType>
1321 ApplyInverseRichardson(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1322 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y)
const {
1324 const double numGlobalRows = as<double>(A_->getGlobalNumRows());
1325 const double numVectors = as<double>(X.getNumVectors());
1326 if (ZeroStartingSolution_) {
1330 Y.scale(DampingFactor_, X);
1336 double flopUpdate = 0.0;
1337 if (DampingFactor_ == STS::one()) {
1339 flopUpdate = numGlobalRows * numVectors;
1343 flopUpdate = numGlobalRows * numVectors;
1345 ApplyFlops_ += flopUpdate;
1346 if (NumSweeps_ == 1) {
1352 const int startSweep = ZeroStartingSolution_ ? 1 : 0;
1355 updateCachedMultiVector(Y.getMap(), as<size_t>(numVectors));
1357 for (
int j = startSweep; j < NumSweeps_; ++j) {
1359 Tpetra::Details::residual(*A_, Y, X, *cachedMV_);
1360 Y.update(DampingFactor_, *cachedMV_, STS::one());
1374 const double numGlobalNonzeros = as<double>(A_->getGlobalNumEntries());
1375 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1376 ApplyFlops_ += as<double>(NumSweeps_ - startSweep) * numVectors *
1377 (2.0 * numGlobalNonzeros + dampingFlops);
1380 template <
class MatrixType>
1381 void Relaxation<MatrixType>::
1382 ApplyInverseJacobi(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1383 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y)
const {
1385 if (hasBlockCrsMatrix_) {
1386 ApplyInverseJacobi_BlockCrsMatrix(X, Y);
1390 const double numGlobalRows = as<double>(A_->getGlobalNumRows());
1391 const double numVectors = as<double>(X.getNumVectors());
1392 if (ZeroStartingSolution_) {
1397 Y.elementWiseMultiply(DampingFactor_, *Diagonal_, X, STS::zero());
1403 double flopUpdate = 0.0;
1404 if (DampingFactor_ == STS::one()) {
1406 flopUpdate = numGlobalRows * numVectors;
1410 flopUpdate = 2.0 * numGlobalRows * numVectors;
1412 ApplyFlops_ += flopUpdate;
1413 if (NumSweeps_ == 1) {
1419 const int startSweep = ZeroStartingSolution_ ? 1 : 0;
1422 updateCachedMultiVector(Y.getMap(), as<size_t>(numVectors));
1424 for (
int j = startSweep; j < NumSweeps_; ++j) {
1426 Tpetra::Details::residual(*A_, Y, X, *cachedMV_);
1427 Y.elementWiseMultiply(DampingFactor_, *Diagonal_, *cachedMV_, STS::one());
1441 const double numGlobalNonzeros = as<double>(A_->getGlobalNumEntries());
1442 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1443 ApplyFlops_ += as<double>(NumSweeps_ - startSweep) * numVectors *
1444 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1447 template <
class MatrixType>
1448 void Relaxation<MatrixType>::
1449 ApplyInverseJacobi_BlockCrsMatrix(
const Tpetra::MultiVector<scalar_type,
1451 global_ordinal_type,
1453 Tpetra::MultiVector<scalar_type,
1455 global_ordinal_type,
1456 node_type>& Y)
const {
1457 using Tpetra::BlockMultiVector;
1458 using BMV = BlockMultiVector<scalar_type, local_ordinal_type,
1459 global_ordinal_type, node_type>;
1461 const block_crs_matrix_type* blockMatConst =
1462 dynamic_cast<const block_crs_matrix_type*
>(A_.
getRawPtr());
1464 "This method should "
1465 "never be called if the matrix A_ is not a BlockCrsMatrix. "
1466 "Please report this bug to the Ifpack2 developers.");
1471 block_crs_matrix_type* blockMat =
1472 const_cast<block_crs_matrix_type*
>(blockMatConst);
1474 auto meshRowMap = blockMat->getRowMap();
1475 auto meshColMap = blockMat->getColMap();
1476 const local_ordinal_type blockSize = blockMat->getBlockSize();
1478 BMV X_blk(X, *meshColMap, blockSize);
1479 BMV Y_blk(Y, *meshRowMap, blockSize);
1481 if (ZeroStartingSolution_) {
1485 Y_blk.blockWiseMultiply(DampingFactor_, blockDiag_, X_blk);
1486 if (NumSweeps_ == 1) {
1491 auto pointRowMap = Y.getMap();
1492 const size_t numVecs = X.getNumVectors();
1496 BMV A_times_Y(*meshRowMap, *pointRowMap, blockSize, numVecs);
1500 const int startSweep = ZeroStartingSolution_ ? 1 : 0;
1502 for (
int j = startSweep; j < NumSweeps_; ++j) {
1503 blockMat->applyBlock(Y_blk, A_times_Y);
1505 Y_blk.blockJacobiUpdate(DampingFactor_, blockDiag_,
1506 X_blk, A_times_Y, STS::one());
1510 template <
class MatrixType>
1511 void Relaxation<MatrixType>::
1512 ApplyInverseSerialGS(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1513 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
1514 Tpetra::ESweepDirection direction)
const {
1515 using this_type = Relaxation<MatrixType>;
1525 auto blockCrsMat = Teuchos::rcp_dynamic_cast<
const block_crs_matrix_type>(A_);
1526 auto crsMat = Details::getCrsMatrix(A_);
1527 if (blockCrsMat.get()) {
1528 const_cast<this_type&
>(*this).ApplyInverseSerialGS_BlockCrsMatrix(*blockCrsMat, X, Y, direction);
1529 }
else if (crsMat.get()) {
1530 ApplyInverseSerialGS_CrsMatrix(*crsMat, X, Y, direction);
1532 ApplyInverseSerialGS_RowMatrix(X, Y, direction);
1536 template <
class MatrixType>
1537 void Relaxation<MatrixType>::
1538 ApplyInverseSerialGS_RowMatrix(
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1539 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
1540 Tpetra::ESweepDirection direction)
const {
1547 using Teuchos::rcpFromRef;
1548 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> MV;
1553 if (ZeroStartingSolution_) {
1554 Y.putScalar(STS::zero());
1557 size_t NumVectors = X.getNumVectors();
1561 if (Importer_.is_null()) {
1562 updateCachedMultiVector(Y.getMap(), NumVectors);
1564 updateCachedMultiVector(Importer_->getTargetMap(), NumVectors);
1571 for (
int j = 0; j < NumSweeps_; ++j) {
1574 if (Importer_.is_null()) {
1580 Y2->doImport(Y, *Importer_, Tpetra::INSERT);
1583 serialGaussSeidel_->apply(*Y2, X, direction);
1587 Tpetra::deep_copy(Y, *Y2);
1592 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1593 const double numVectors = as<double>(X.getNumVectors());
1594 const double numGlobalRows = as<double>(A_->getGlobalNumRows());
1595 const double numGlobalNonzeros = as<double>(A_->getGlobalNumEntries());
1596 ApplyFlops_ += 2.0 * NumSweeps_ * numVectors *
1597 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1600 template <
class MatrixType>
1601 void Relaxation<MatrixType>::
1602 ApplyInverseSerialGS_CrsMatrix(
const crs_matrix_type& A,
1603 const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& B,
1604 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1605 Tpetra::ESweepDirection direction)
const {
1606 using Teuchos::null;
1609 using Teuchos::rcp_const_cast;
1610 using Teuchos::rcpFromRef;
1611 typedef scalar_type Scalar;
1612 const char prefix[] =
"Ifpack2::Relaxation::SerialGS: ";
1616 !A.isFillComplete(), std::runtime_error,
1617 prefix <<
"The matrix is not fill complete.");
1619 NumSweeps_ < 0, std::invalid_argument,
1620 prefix <<
"The number of sweeps must be nonnegative, "
1621 "but you provided numSweeps = "
1622 << NumSweeps_ <<
" < 0.");
1624 if (NumSweeps_ == 0) {
1628 RCP<const import_type> importer = A.getGraph()->getImporter();
1630 RCP<const map_type> domainMap = A.getDomainMap();
1631 RCP<const map_type> rangeMap = A.getRangeMap();
1632 RCP<const map_type> rowMap = A.getGraph()->getRowMap();
1633 RCP<const map_type> colMap = A.getGraph()->getColMap();
1635 #ifdef HAVE_IFPACK2_DEBUG
1641 !X.getMap()->isSameAs(*domainMap), std::runtime_error,
1642 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
1643 "multivector X be in the domain Map of the matrix.");
1645 !B.getMap()->isSameAs(*rangeMap), std::runtime_error,
1646 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
1647 "B be in the range Map of the matrix.");
1649 !Diagonal_->getMap()->isSameAs(*rowMap), std::runtime_error,
1650 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the input "
1651 "D be in the row Map of the matrix.");
1653 !rowMap->isSameAs(*rangeMap), std::runtime_error,
1654 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the row Map and the "
1655 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
1657 !domainMap->isSameAs(*rangeMap), std::runtime_error,
1658 "Tpetra::CrsMatrix::gaussSeidelCopy requires that the domain Map and "
1659 "the range Map of the matrix be the same.");
1671 RCP<multivector_type> X_colMap;
1672 RCP<multivector_type> X_domainMap;
1673 bool copyBackOutput =
false;
1674 if (importer.is_null()) {
1675 X_colMap = Teuchos::rcpFromRef(X);
1676 X_domainMap = Teuchos::rcpFromRef(X);
1682 if (ZeroStartingSolution_) {
1683 X_colMap->putScalar(ZERO);
1687 updateCachedMultiVector(colMap, X.getNumVectors());
1688 X_colMap = cachedMV_;
1689 X_domainMap = X_colMap->offsetViewNonConst(domainMap, 0);
1691 if (ZeroStartingSolution_) {
1693 X_colMap->putScalar(ZERO);
1703 X_colMap->doImport(X, *importer, Tpetra::INSERT);
1705 copyBackOutput =
true;
1708 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
1709 if (!importer.is_null() && sweep > 0) {
1712 X_colMap->doImport(*X_domainMap, *importer, Tpetra::INSERT);
1715 serialGaussSeidel_->apply(*X_colMap, B, direction);
1718 if (copyBackOutput) {
1720 deep_copy(X, *X_domainMap);
1721 }
catch (std::exception& e) {
1723 true, std::runtime_error, prefix <<
"deep_copy(X, *X_domainMap) "
1724 "threw an exception: "
1740 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1741 const double numVectors = X.getNumVectors();
1742 const double numGlobalRows = A_->getGlobalNumRows();
1743 const double numGlobalNonzeros = A_->getGlobalNumEntries();
1744 ApplyFlops_ += NumSweeps_ * numVectors *
1745 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1748 template <
class MatrixType>
1749 void Relaxation<MatrixType>::
1750 ApplyInverseSerialGS_BlockCrsMatrix(
const block_crs_matrix_type& A,
1751 const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1752 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
1753 Tpetra::ESweepDirection direction) {
1756 using Teuchos::rcpFromRef;
1757 using Tpetra::INSERT;
1766 block_multivector_type yBlock(Y, *(A.getGraph()->getDomainMap()), A.getBlockSize());
1767 const block_multivector_type xBlock(X, *(A.getColMap()), A.getBlockSize());
1769 bool performImport =
false;
1770 RCP<block_multivector_type> yBlockCol;
1771 if (Importer_.is_null()) {
1772 yBlockCol = rcpFromRef(yBlock);
1774 if (yBlockColumnPointMap_.is_null() ||
1775 yBlockColumnPointMap_->getNumVectors() != yBlock.getNumVectors() ||
1776 yBlockColumnPointMap_->getBlockSize() != yBlock.getBlockSize()) {
1777 yBlockColumnPointMap_ =
1778 rcp(
new block_multivector_type(*(A.getColMap()), A.getBlockSize(),
1779 static_cast<local_ordinal_type
>(yBlock.getNumVectors())));
1781 yBlockCol = yBlockColumnPointMap_;
1782 if (pointImporter_.is_null()) {
1783 auto srcMap =
rcp(
new map_type(yBlock.getPointMap()));
1784 auto tgtMap =
rcp(
new map_type(yBlockCol->getPointMap()));
1785 pointImporter_ =
rcp(
new import_type(srcMap, tgtMap));
1787 performImport =
true;
1790 multivector_type yBlock_mv;
1791 multivector_type yBlockCol_mv;
1792 RCP<const multivector_type> yBlockColPointDomain;
1793 if (performImport) {
1794 yBlock_mv = yBlock.getMultiVectorView();
1795 yBlockCol_mv = yBlockCol->getMultiVectorView();
1796 yBlockColPointDomain =
1797 yBlockCol_mv.offsetView(A.getDomainMap(), 0);
1800 if (ZeroStartingSolution_) {
1801 yBlockCol->putScalar(STS::zero());
1802 }
else if (performImport) {
1803 yBlockCol_mv.doImport(yBlock_mv, *pointImporter_, Tpetra::INSERT);
1806 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
1807 if (performImport && sweep > 0) {
1808 yBlockCol_mv.doImport(yBlock_mv, *pointImporter_, Tpetra::INSERT);
1810 serialGaussSeidel_->applyBlock(*yBlockCol, xBlock, direction);
1811 if (performImport) {
1812 Tpetra::deep_copy(Y, *yBlockColPointDomain);
1817 template <
class MatrixType>
1818 void Relaxation<MatrixType>::
1819 ApplyInverseMTGS_CrsMatrix(
1820 const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& B,
1821 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
1822 Tpetra::ESweepDirection direction)
const {
1824 using Teuchos::null;
1827 using Teuchos::rcp_const_cast;
1828 using Teuchos::rcpFromRef;
1830 typedef scalar_type Scalar;
1832 const char prefix[] =
"Ifpack2::Relaxation::(reordered)MTGaussSeidel: ";
1835 auto crsMat = Details::getCrsMatrix(A_);
1837 "Ifpack2::Relaxation::apply: "
1838 "Multithreaded Gauss-Seidel methods currently only work when the "
1839 "input matrix is a Tpetra::CrsMatrix.");
1843 "Ifpack2's implementation of Multithreaded Gauss-Seidel does not "
1844 "implement the case where the user supplies an iteration order. "
1845 "This error used to appear as \"MT GaussSeidel ignores the given "
1847 "I tried to add more explanation, but I didn't implement \"MT "
1848 "GaussSeidel\" [sic]. "
1849 "You'll have to ask the person who did.");
1852 "input CrsMatrix is not fill complete. Please call fillComplete "
1853 "on the matrix, then do setup again, before calling apply(). "
1854 "\"Do setup\" means that if only the matrix's values have changed "
1855 "since last setup, you need only call compute(). If the matrix's "
1856 "structure may also have changed, you must first call initialize(), "
1857 "then call compute(). If you have not set up this preconditioner "
1858 "for this matrix before, you must first call initialize(), then "
1860 TEUCHOS_TEST_FOR_EXCEPTION(NumSweeps_ < 0, std::logic_error, prefix <<
": NumSweeps_ = " << NumSweeps_ <<
" < 0. Please report this bug to the Ifpack2 "
1862 if (NumSweeps_ == 0) {
1866 RCP<const import_type> importer = crsMat->getGraph()->getImporter();
1868 !crsMat->getGraph()->getExporter().is_null(), std::runtime_error,
1869 "This method's implementation currently requires that the matrix's row, "
1870 "domain, and range Maps be the same. This cannot be the case, because "
1871 "the matrix has a nontrivial Export object.");
1873 RCP<const map_type> domainMap = crsMat->getDomainMap();
1874 RCP<const map_type> rangeMap = crsMat->getRangeMap();
1875 RCP<const map_type> rowMap = crsMat->getGraph()->getRowMap();
1876 RCP<const map_type> colMap = crsMat->getGraph()->getColMap();
1878 #ifdef HAVE_IFPACK2_DEBUG
1884 !X.getMap()->isSameAs(*domainMap), std::runtime_error,
1885 "Ifpack2::Relaxation::MTGaussSeidel requires that the input "
1886 "multivector X be in the domain Map of the matrix.");
1888 !B.getMap()->isSameAs(*rangeMap), std::runtime_error,
1889 "Ifpack2::Relaxation::MTGaussSeidel requires that the input "
1890 "B be in the range Map of the matrix.");
1892 !rowMap->isSameAs(*rangeMap), std::runtime_error,
1893 "Ifpack2::Relaxation::MTGaussSeidel requires that the row Map and the "
1894 "range Map be the same (in the sense of Tpetra::Map::isSameAs).");
1896 !domainMap->isSameAs(*rangeMap), std::runtime_error,
1897 "Ifpack2::Relaxation::MTGaussSeidel requires that the domain Map and "
1898 "the range Map of the matrix be the same.");
1904 #endif // HAVE_IFPACK2_DEBUG
1914 RCP<multivector_type> X_colMap;
1915 RCP<multivector_type> X_domainMap;
1916 bool copyBackOutput =
false;
1917 if (importer.is_null()) {
1918 if (X.isConstantStride()) {
1919 X_colMap = rcpFromRef(X);
1920 X_domainMap = rcpFromRef(X);
1927 if (ZeroStartingSolution_) {
1928 X_colMap->putScalar(ZERO);
1936 updateCachedMultiVector(colMap, as<size_t>(X.getNumVectors()));
1937 X_colMap = cachedMV_;
1941 X_domainMap = X_colMap;
1942 if (!ZeroStartingSolution_) {
1944 deep_copy(*X_domainMap, X);
1945 }
catch (std::exception& e) {
1946 std::ostringstream os;
1947 os <<
"Ifpack2::Relaxation::MTGaussSeidel: "
1948 "deep_copy(*X_domainMap, X) threw an exception: "
1953 copyBackOutput =
true;
1966 updateCachedMultiVector(colMap, as<size_t>(X.getNumVectors()));
1967 X_colMap = cachedMV_;
1969 X_domainMap = X_colMap->offsetViewNonConst(domainMap, 0);
1971 if (ZeroStartingSolution_) {
1973 X_colMap->putScalar(ZERO);
1983 X_colMap->doImport(X, *importer, Tpetra::CombineMode::INSERT);
1985 copyBackOutput =
true;
1991 RCP<const multivector_type> B_in;
1992 if (B.isConstantStride()) {
1993 B_in = rcpFromRef(B);
1998 RCP<multivector_type> B_in_nonconst =
rcp(
new multivector_type(rowMap, B.getNumVectors()));
2000 deep_copy(*B_in_nonconst, B);
2001 }
catch (std::exception& e) {
2002 std::ostringstream os;
2003 os <<
"Ifpack2::Relaxation::MTGaussSeidel: "
2004 "deep_copy(*B_in_nonconst, B) threw an exception: "
2008 B_in = rcp_const_cast<
const multivector_type>(B_in_nonconst);
2022 local_matrix_device_type kcsr = crsMat->getLocalMatrixDevice();
2024 bool update_y_vector =
true;
2026 bool zero_x_vector =
false;
2028 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
2029 if (!importer.is_null() && sweep > 0) {
2032 X_colMap->doImport(*X_domainMap, *importer, Tpetra::CombineMode::INSERT);
2035 if (direction == Tpetra::Symmetric) {
2036 KokkosSparse::symmetric_gauss_seidel_apply(mtKernelHandle_.getRawPtr(), A_->getLocalNumRows(), A_->getLocalNumCols(),
2037 kcsr.graph.row_map, kcsr.graph.entries, kcsr.values,
2038 X_colMap->getLocalViewDevice(Tpetra::Access::ReadWrite),
2039 B_in->getLocalViewDevice(Tpetra::Access::ReadOnly),
2040 zero_x_vector, update_y_vector, DampingFactor_, 1);
2041 }
else if (direction == Tpetra::Forward) {
2042 KokkosSparse::forward_sweep_gauss_seidel_apply(mtKernelHandle_.getRawPtr(), A_->getLocalNumRows(), A_->getLocalNumCols(),
2043 kcsr.graph.row_map, kcsr.graph.entries, kcsr.values,
2044 X_colMap->getLocalViewDevice(Tpetra::Access::ReadWrite),
2045 B_in->getLocalViewDevice(Tpetra::Access::ReadOnly),
2046 zero_x_vector, update_y_vector, DampingFactor_, 1);
2047 }
else if (direction == Tpetra::Backward) {
2048 KokkosSparse::backward_sweep_gauss_seidel_apply(mtKernelHandle_.getRawPtr(), A_->getLocalNumRows(), A_->getLocalNumCols(),
2049 kcsr.graph.row_map, kcsr.graph.entries, kcsr.values,
2050 X_colMap->getLocalViewDevice(Tpetra::Access::ReadWrite),
2051 B_in->getLocalViewDevice(Tpetra::Access::ReadOnly),
2052 zero_x_vector, update_y_vector, DampingFactor_, 1);
2055 true, std::invalid_argument,
2056 prefix <<
"The 'direction' enum does not have any of its valid "
2057 "values: Forward, Backward, or Symmetric.");
2059 update_y_vector =
false;
2062 if (copyBackOutput) {
2064 deep_copy(X, *X_domainMap);
2065 }
catch (std::exception& e) {
2067 true, std::runtime_error, prefix <<
"deep_copy(X, *X_domainMap) "
2068 "threw an exception: "
2073 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
2074 const double numVectors = as<double>(X.getNumVectors());
2075 const double numGlobalRows = as<double>(A_->getGlobalNumRows());
2076 const double numGlobalNonzeros = as<double>(A_->getGlobalNumEntries());
2077 double ApplyFlops = NumSweeps_ * numVectors *
2078 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
2079 if (direction == Tpetra::Symmetric)
2081 ApplyFlops_ += ApplyFlops;
2084 template <
class MatrixType>
2086 std::ostringstream os;
2091 os <<
"\"Ifpack2::Relaxation\": {";
2093 os <<
"Initialized: " << (isInitialized() ?
"true" :
"false") <<
", "
2094 <<
"Computed: " << (isComputed() ?
"true" :
"false") <<
", ";
2100 if (PrecType_ == Ifpack2::Details::JACOBI) {
2102 }
else if (PrecType_ == Ifpack2::Details::GS) {
2103 os <<
"Gauss-Seidel";
2104 }
else if (PrecType_ == Ifpack2::Details::SGS) {
2105 os <<
"Symmetric Gauss-Seidel";
2106 }
else if (PrecType_ == Ifpack2::Details::MTGS) {
2107 os <<
"MT Gauss-Seidel";
2108 }
else if (PrecType_ == Ifpack2::Details::MTSGS) {
2109 os <<
"MT Symmetric Gauss-Seidel";
2110 }
else if (PrecType_ == Ifpack2::Details::GS2) {
2111 os <<
"Two-stage Gauss-Seidel";
2112 }
else if (PrecType_ == Ifpack2::Details::SGS2) {
2113 os <<
"Two-stage Symmetric Gauss-Seidel";
2117 if (hasBlockCrsMatrix_)
2121 <<
"sweeps: " << NumSweeps_ <<
", "
2122 <<
"damping factor: " << DampingFactor_ <<
", ";
2124 if (PrecType_ == Ifpack2::Details::MTGS || PrecType_ == Ifpack2::Details::MTSGS) {
2125 os <<
"\"relaxation: mtgs cluster size\": " << clusterSize_ <<
", ";
2126 os <<
"\"relaxation: long row threshold\": " << longRowThreshold_ <<
", ";
2127 os <<
"\"relaxation: symmetric matrix structure\": " << (is_matrix_structurally_symmetric_ ?
"true" :
"false") <<
", ";
2128 os <<
"\"relaxation: relaxation: mtgs coloring algorithm\": ";
2129 switch (mtColoringAlgorithm_) {
2130 case KokkosGraph::COLORING_DEFAULT:
2133 case KokkosGraph::COLORING_SERIAL:
2136 case KokkosGraph::COLORING_VB:
2139 case KokkosGraph::COLORING_VBBIT:
2142 case KokkosGraph::COLORING_VBCS:
2145 case KokkosGraph::COLORING_VBD:
2148 case KokkosGraph::COLORING_VBDBIT:
2151 case KokkosGraph::COLORING_EB:
2160 if (PrecType_ == Ifpack2::Details::GS2 ||
2161 PrecType_ == Ifpack2::Details::SGS2) {
2162 os <<
"outer sweeps: " << NumOuterSweeps_ <<
", "
2163 <<
"inner sweeps: " << NumInnerSweeps_ <<
", "
2164 <<
"inner damping factor: " << InnerDampingFactor_ <<
", ";
2168 os <<
"use l1: " << DoL1Method_ <<
", "
2169 <<
"l1 eta: " << L1Eta_ <<
", ";
2173 os <<
"Matrix: null";
2175 os <<
"Global matrix dimensions: ["
2176 << A_->getGlobalNumRows() <<
", " << A_->getGlobalNumCols() <<
"]"
2177 <<
", Global nnz: " << A_->getGlobalNumEntries();
2184 template <
class MatrixType>
2201 const int myRank = this->getComm()->getRank();
2213 out <<
"\"Ifpack2::Relaxation\":" << endl;
2215 out <<
"MatrixType: \"" << TypeNameTraits<MatrixType>::name() <<
"\""
2217 if (this->getObjectLabel() !=
"") {
2218 out <<
"Label: " << this->getObjectLabel() << endl;
2220 out <<
"Initialized: " << (isInitialized() ?
"true" :
"false") << endl
2221 <<
"Computed: " << (isComputed() ?
"true" :
"false") << endl
2222 <<
"Parameters: " << endl;
2225 out <<
"\"relaxation: type\": ";
2226 if (PrecType_ == Ifpack2::Details::JACOBI) {
2228 }
else if (PrecType_ == Ifpack2::Details::GS) {
2229 out <<
"Gauss-Seidel";
2230 }
else if (PrecType_ == Ifpack2::Details::SGS) {
2231 out <<
"Symmetric Gauss-Seidel";
2232 }
else if (PrecType_ == Ifpack2::Details::MTGS) {
2233 out <<
"MT Gauss-Seidel";
2234 }
else if (PrecType_ == Ifpack2::Details::MTSGS) {
2235 out <<
"MT Symmetric Gauss-Seidel";
2236 }
else if (PrecType_ == Ifpack2::Details::GS2) {
2237 out <<
"Two-stage Gauss-Seidel";
2238 }
else if (PrecType_ == Ifpack2::Details::SGS2) {
2239 out <<
"Two-stage Symmetric Gauss-Seidel";
2246 <<
"\"relaxation: sweeps\": " << NumSweeps_ << endl
2247 <<
"\"relaxation: damping factor\": " << DampingFactor_ << endl
2248 <<
"\"relaxation: min diagonal value\": " << MinDiagonalValue_ << endl
2249 <<
"\"relaxation: zero starting solution\": " << ZeroStartingSolution_ << endl
2250 <<
"\"relaxation: backward mode\": " << DoBackwardGS_ << endl
2251 <<
"\"relaxation: use l1\": " << DoL1Method_ << endl
2252 <<
"\"relaxation: l1 eta\": " << L1Eta_ << endl;
2253 if (PrecType_ == Ifpack2::Details::MTGS || PrecType_ == Ifpack2::Details::MTSGS) {
2254 out <<
"\"relaxation: mtgs cluster size\": " << clusterSize_ << endl;
2255 out <<
"\"relaxation: long row threshold\": " << longRowThreshold_ << endl;
2256 out <<
"\"relaxation: symmetric matrix structure\": " << (is_matrix_structurally_symmetric_ ?
"true" :
"false") << endl;
2257 out <<
"\"relaxation: relaxation: mtgs coloring algorithm\": ";
2258 switch (mtColoringAlgorithm_) {
2259 case KokkosGraph::COLORING_DEFAULT:
2262 case KokkosGraph::COLORING_SERIAL:
2265 case KokkosGraph::COLORING_VB:
2268 case KokkosGraph::COLORING_VBBIT:
2271 case KokkosGraph::COLORING_VBCS:
2274 case KokkosGraph::COLORING_VBD:
2277 case KokkosGraph::COLORING_VBDBIT:
2280 case KokkosGraph::COLORING_EB:
2288 if (PrecType_ == Ifpack2::Details::GS2 || PrecType_ == Ifpack2::Details::SGS2) {
2289 out <<
"\"relaxation: inner damping factor\": " << InnerDampingFactor_ << endl;
2290 out <<
"\"relaxation: outer sweeps\" : " << NumOuterSweeps_ << endl;
2291 out <<
"\"relaxation: inner sweeps\" : " << NumInnerSweeps_ << endl;
2294 out <<
"Computed quantities:" << endl;
2297 out <<
"Global number of rows: " << A_->getGlobalNumRows() << endl
2298 <<
"Global number of columns: " << A_->getGlobalNumCols() << endl;
2300 if (checkDiagEntries_ && isComputed()) {
2301 out <<
"Properties of input diagonal entries:" << endl;
2304 out <<
"Magnitude of minimum-magnitude diagonal entry: "
2305 << globalMinMagDiagEntryMag_ << endl
2306 <<
"Magnitude of maximum-magnitude diagonal entry: "
2307 << globalMaxMagDiagEntryMag_ << endl
2308 <<
"Number of diagonal entries with small magnitude: "
2309 << globalNumSmallDiagEntries_ << endl
2310 <<
"Number of zero diagonal entries: "
2311 << globalNumZeroDiagEntries_ << endl
2312 <<
"Number of diagonal entries with negative real part: "
2313 << globalNumNegDiagEntries_ << endl
2314 <<
"Abs 2-norm diff between computed and actual inverse "
2315 <<
"diagonal: " << globalDiagNormDiff_ << endl;
2319 out <<
"Saved diagonal offsets: "
2320 << (savedDiagOffsets_ ?
"true" :
"false") << endl;
2322 out <<
"Call counts and total times (in seconds): " << endl;
2325 out <<
"initialize: " << endl;
2328 out <<
"Call count: " << NumInitialize_ << endl;
2329 out <<
"Total time: " << InitializeTime_ << endl;
2331 out <<
"compute: " << endl;
2334 out <<
"Call count: " << NumCompute_ << endl;
2335 out <<
"Total time: " << ComputeTime_ << endl;
2337 out <<
"apply: " << endl;
2340 out <<
"Call count: " << NumApply_ << endl;
2341 out <<
"Total time: " << ApplyTime_ << endl;
2349 #define IFPACK2_RELAXATION_INSTANT(S, LO, GO, N) \
2350 template class Ifpack2::Relaxation<Tpetra::RowMatrix<S, LO, GO, N>>;
2352 #endif // IFPACK2_RELAXATION_DEF_HPP
bool hasTransposeApply() const
Whether apply() and applyMat() let you apply the transpose or conjugate transpose.
Definition: Ifpack2_Relaxation_def.hpp:484
double getComputeFlops() const
Total number of floating-point operations over all calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:519
double getApplyFlops() const
Total number of floating-point operations over all calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:524
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print the object's attributes to the given output stream.
Definition: Ifpack2_Relaxation_def.hpp:2186
bool is_null(const boost::shared_ptr< T > &p)
basic_OSTab< char > OSTab
static magnitudeType eps()
Relaxation(const Teuchos::RCP< const row_matrix_type > &A)
Constructor.
Definition: Ifpack2_Relaxation_def.hpp:182
T & get(const std::string &name, T def_value)
void compute()
Compute the preconditioner ("numeric setup");.
Definition: Ifpack2_Relaxation_def.hpp:960
virtual void printDoc(std::string const &docString, std::ostream &out) const =0
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Definition: Ifpack2_Relaxation_def.hpp:529
virtual const std::string getXMLTypeName() const =0
Diagonal preconditioner.
Definition: Ifpack2_Diagonal_decl.hpp:38
static std::ostream & printLines(std::ostream &os, const std::string &linePrefix, const std::string &lines)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix and vectors are distributed.
Definition: Ifpack2_Relaxation_def.hpp:442
virtual void setMatrix(const Teuchos::RCP< const row_matrix_type > &A)
Change the matrix to be preconditioned.
Definition: Ifpack2_Relaxation_def.hpp:162
int getNumApply() const
Total number of calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:499
bool remove(std::string const &name, bool throwIfNotExists=true)
double getComputeTime() const
Total time in seconds spent in all calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:509
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:230
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getDomainMap() const
Returns the Tpetra::Map object associated with the domain of this operator.
Definition: Ifpack2_Relaxation_def.hpp:461
void setParameters(const Teuchos::ParameterList ¶ms)
Set the relaxation / preconditioner parameters.
Definition: Ifpack2_Relaxation_def.hpp:434
File for utility functions.
std::string description() const
A simple one-line description of this object.
Definition: Ifpack2_Relaxation_def.hpp:2085
int getNumInitialize() const
Total number of calls to initialize().
Definition: Ifpack2_Relaxation_def.hpp:489
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
virtual ValidStringsList validStringValues() const =0
Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRangeMap() const
Returns the Tpetra::Map object associated with the range of this operator.
Definition: Ifpack2_Relaxation_def.hpp:474
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:227
double getInitializeTime() const
Total time in seconds spent in all calls to initialize().
Definition: Ifpack2_Relaxation_def.hpp:504
any & getAny(bool activeQry=true)
Compute scaled damped residual for Chebyshev.
Definition: Ifpack2_Details_InverseDiagonalKernel_decl.hpp:45
void applyMat(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &X, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS) const
Apply the input matrix to X, returning the result in Y.
Definition: Ifpack2_Relaxation_def.hpp:653
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix to be preconditioned.
Definition: Ifpack2_Relaxation_def.hpp:453
TypeTo as(const TypeFrom &t)
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:224
bool isType(const std::string &name) const
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:221
std::string typeName() const
const std::type_info & type() const
int getNumCompute() const
Total number of calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:494
Relaxation preconditioners for Tpetra::RowMatrix and Tpetra::CrsMatrix sparse matrices.
Definition: Ifpack2_Relaxation_decl.hpp:206
double getApplyTime() const
Total time in seconds spent in all calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:514
void getValidParameters(Teuchos::ParameterList ¶ms)
Fills a list which contains all the parameters possibly used by Ifpack2.
Definition: Ifpack2_Parameters.cpp:18
void initialize()
Initialize the preconditioner ("symbolic setup").
Definition: Ifpack2_Relaxation_def.hpp:674
Tpetra::RowMatrix< scalar_type, local_ordinal_type, global_ordinal_type, node_type > row_matrix_type
Tpetra::RowMatrix specialization used by this class.
Definition: Ifpack2_Relaxation_decl.hpp:241
void apply(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &X, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, scalar_type alpha=Teuchos::ScalarTraits< scalar_type >::one(), scalar_type beta=Teuchos::ScalarTraits< scalar_type >::zero()) const
Apply the preconditioner to X, returning the result in Y.
Definition: Ifpack2_Relaxation_def.hpp:541
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a list of all the parameters that this class accepts.
Definition: Ifpack2_Relaxation_def.hpp:191
Teuchos::ScalarTraits< scalar_type >::magnitudeType magnitude_type
The type of the magnitude (absolute value) of a matrix entry.
Definition: Ifpack2_Relaxation_decl.hpp:236
virtual void validate(ParameterEntry const &entry, std::string const ¶mName, std::string const &sublistName) const =0