43 #ifndef IFPACK2_RELAXATION_DEF_HPP 44 #define IFPACK2_RELAXATION_DEF_HPP 46 #include <Teuchos_StandardParameterEntryValidators.hpp> 47 #include <Teuchos_TimeMonitor.hpp> 48 #include <Tpetra_ConfigDefs.hpp> 49 #include <Tpetra_CrsMatrix.hpp> 50 #include <Tpetra_Experimental_BlockCrsMatrix.hpp> 52 #include <Ifpack2_Relaxation_decl.hpp> 62 class NonnegativeIntValidator :
public Teuchos::ParameterEntryValidator {
65 NonnegativeIntValidator () {}
68 Teuchos::ParameterEntryValidator::ValidStringsList validStringValues ()
const {
74 validate (
const Teuchos::ParameterEntry& entry,
75 const std::string& paramName,
76 const std::string& sublistName)
const 79 Teuchos::any anyVal = entry.getAny (
true);
80 const std::string entryName = entry.getAny (
false).typeName ();
82 TEUCHOS_TEST_FOR_EXCEPTION(
83 anyVal.type () !=
typeid (int),
84 Teuchos::Exceptions::InvalidParameterType,
85 "Parameter \"" << paramName <<
"\" in sublist \"" << sublistName
86 <<
"\" has the wrong type." << endl <<
"Parameter: " << paramName
87 << endl <<
"Type specified: " << entryName << endl
88 <<
"Type required: int" << endl);
90 const int val = Teuchos::any_cast<
int> (anyVal);
91 TEUCHOS_TEST_FOR_EXCEPTION(
92 val < 0, Teuchos::Exceptions::InvalidParameterValue,
93 "Parameter \"" << paramName <<
"\" in sublist \"" << sublistName
94 <<
"\" is negative." << endl <<
"Parameter: " << paramName
95 << endl <<
"Value specified: " << val << endl
96 <<
"Required range: [0, INT_MAX]" << endl);
100 const std::string getXMLTypeName ()
const {
101 return "NonnegativeIntValidator";
106 printDoc (
const std::string& docString,
107 std::ostream &out)
const 109 Teuchos::StrUtils::printLines (out,
"# ", docString);
110 out <<
"#\tValidator Used: " << std::endl;
111 out <<
"#\t\tNonnegativeIntValidator" << std::endl;
118 template<class Scalar, const bool isOrdinal=Teuchos::ScalarTraits<Scalar>::isOrdinal>
122 static const Scalar eps ();
126 template<
class Scalar>
127 class SmallTraits<Scalar, true> {
129 static const Scalar eps () {
130 return Teuchos::ScalarTraits<Scalar>::one ();
135 template<
class Scalar>
136 class SmallTraits<Scalar, false> {
138 static const Scalar eps () {
139 return Teuchos::ScalarTraits<Scalar>::eps ();
146 template<
class MatrixType>
147 void Relaxation<MatrixType>::
148 setMatrix (
const Teuchos::RCP<const row_matrix_type>& A)
150 if (A.getRawPtr () != A_.getRawPtr ()) {
151 Importer_ = Teuchos::null;
152 Diagonal_ = Teuchos::null;
153 isInitialized_ =
false;
155 diagOffsets_ = Teuchos::null;
156 savedDiagOffsets_ =
false;
157 hasBlockCrsMatrix_ =
false;
158 if (! A.is_null ()) {
159 IsParallel_ = (A->getRowMap ()->getComm ()->getSize () > 1);
166 template<
class MatrixType>
173 DampingFactor_ (STS::one ()),
174 IsParallel_ ((A.is_null () || A->getRowMap ().is_null () || A->getRowMap ()->getComm ().is_null ()) ?
176 A->getRowMap ()->getComm ()->getSize () > 1),
177 ZeroStartingSolution_ (true),
178 DoBackwardGS_ (false),
181 MinDiagonalValue_ (STS::zero ()),
182 fixTinyDiagEntries_ (false),
183 checkDiagEntries_ (false),
184 isInitialized_ (false),
189 InitializeTime_ (0.0),
194 globalMinMagDiagEntryMag_ (STM::zero ()),
195 globalMaxMagDiagEntryMag_ (STM::zero ()),
196 globalNumSmallDiagEntries_ (0),
197 globalNumZeroDiagEntries_ (0),
198 globalNumNegDiagEntries_ (0),
200 savedDiagOffsets_ (false),
201 hasBlockCrsMatrix_ (false)
203 this->setObjectLabel (
"Ifpack2::Relaxation");
207 template<
class MatrixType>
211 template<
class MatrixType>
212 Teuchos::RCP<const Teuchos::ParameterList>
215 using Teuchos::Array;
216 using Teuchos::ParameterList;
217 using Teuchos::parameterList;
220 using Teuchos::rcp_const_cast;
221 using Teuchos::rcp_implicit_cast;
222 using Teuchos::setStringToIntegralParameter;
223 typedef Teuchos::ParameterEntryValidator PEV;
225 if (validParams_.is_null ()) {
226 RCP<ParameterList> pl = parameterList (
"Ifpack2::Relaxation");
230 Array<std::string> precTypes (3);
231 precTypes[0] =
"Jacobi";
232 precTypes[1] =
"Gauss-Seidel";
233 precTypes[2] =
"Symmetric Gauss-Seidel";
234 Array<Details::RelaxationType> precTypeEnums (3);
235 precTypeEnums[0] = Details::JACOBI;
236 precTypeEnums[1] = Details::GS;
237 precTypeEnums[2] = Details::SGS;
238 const std::string defaultPrecType (
"Jacobi");
239 setStringToIntegralParameter<Details::RelaxationType> (
"relaxation: type",
240 defaultPrecType,
"Relaxation method", precTypes (), precTypeEnums (),
243 const int numSweeps = 1;
244 RCP<PEV> numSweepsValidator =
245 rcp_implicit_cast<PEV> (rcp (
new NonnegativeIntValidator));
246 pl->set (
"relaxation: sweeps", numSweeps,
"Number of relaxation sweeps",
247 rcp_const_cast<const PEV> (numSweepsValidator));
250 pl->set (
"relaxation: damping factor", dampingFactor);
252 const bool zeroStartingSolution =
true;
253 pl->set (
"relaxation: zero starting solution", zeroStartingSolution);
255 const bool doBackwardGS =
false;
256 pl->set (
"relaxation: backward mode", doBackwardGS);
258 const bool doL1Method =
false;
259 pl->set (
"relaxation: use l1", doL1Method);
261 const magnitude_type l1eta = (STM::one() + STM::one() + STM::one()) /
262 (STM::one() + STM::one());
263 pl->set (
"relaxation: l1 eta", l1eta);
266 pl->set (
"relaxation: min diagonal value", minDiagonalValue);
268 const bool fixTinyDiagEntries =
false;
269 pl->set (
"relaxation: fix tiny diagonal entries", fixTinyDiagEntries);
271 const bool checkDiagEntries =
false;
272 pl->set (
"relaxation: check diagonal entries", checkDiagEntries);
274 Teuchos::ArrayRCP<local_ordinal_type> localSmoothingIndices = Teuchos::null;
275 pl->set(
"relaxation: local smoothing indices", localSmoothingIndices);
277 validParams_ = rcp_const_cast<
const ParameterList> (pl);
283 template<
class MatrixType>
286 using Teuchos::getIntegralValue;
287 using Teuchos::ParameterList;
293 const Details::RelaxationType precType =
294 getIntegralValue<Details::RelaxationType> (pl,
"relaxation: type");
295 const int numSweeps = pl.get<
int> (
"relaxation: sweeps");
296 const ST dampingFactor = pl.get<ST> (
"relaxation: damping factor");
297 const bool zeroStartSol = pl.get<
bool> (
"relaxation: zero starting solution");
298 const bool doBackwardGS = pl.get<
bool> (
"relaxation: backward mode");
299 const bool doL1Method = pl.get<
bool> (
"relaxation: use l1");
301 const ST minDiagonalValue = pl.get<ST> (
"relaxation: min diagonal value");
302 const bool fixTinyDiagEntries = pl.get<
bool> (
"relaxation: fix tiny diagonal entries");
303 const bool checkDiagEntries = pl.get<
bool> (
"relaxation: check diagonal entries");
304 Teuchos::ArrayRCP<local_ordinal_type> localSmoothingIndices = pl.get<Teuchos::ArrayRCP<local_ordinal_type> >(
"relaxation: local smoothing indices");
308 PrecType_ = precType;
309 NumSweeps_ = numSweeps;
310 DampingFactor_ = dampingFactor;
311 ZeroStartingSolution_ = zeroStartSol;
312 DoBackwardGS_ = doBackwardGS;
313 DoL1Method_ = doL1Method;
315 MinDiagonalValue_ = minDiagonalValue;
316 fixTinyDiagEntries_ = fixTinyDiagEntries;
317 checkDiagEntries_ = checkDiagEntries;
318 localSmoothingIndices_ = localSmoothingIndices;
322 template<
class MatrixType>
327 this->setParametersImpl(const_cast<Teuchos::ParameterList&>(pl));
331 template<
class MatrixType>
332 Teuchos::RCP<const Teuchos::Comm<int> >
334 TEUCHOS_TEST_FOR_EXCEPTION(
335 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::getComm: " 336 "The input matrix A is null. Please call setMatrix() with a nonnull " 337 "input matrix before calling this method.");
338 return A_->getRowMap ()->getComm ();
342 template<
class MatrixType>
343 Teuchos::RCP<const typename Relaxation<MatrixType>::row_matrix_type>
349 template<
class MatrixType>
350 Teuchos::RCP<
const Tpetra::Map<
typename MatrixType::local_ordinal_type,
351 typename MatrixType::global_ordinal_type,
352 typename MatrixType::node_type> >
354 TEUCHOS_TEST_FOR_EXCEPTION(
355 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::getDomainMap: " 356 "The input matrix A is null. Please call setMatrix() with a nonnull " 357 "input matrix before calling this method.");
358 return A_->getDomainMap ();
362 template<
class MatrixType>
363 Teuchos::RCP<
const Tpetra::Map<
typename MatrixType::local_ordinal_type,
364 typename MatrixType::global_ordinal_type,
365 typename MatrixType::node_type> >
367 TEUCHOS_TEST_FOR_EXCEPTION(
368 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::getRangeMap: " 369 "The input matrix A is null. Please call setMatrix() with a nonnull " 370 "input matrix before calling this method.");
371 return A_->getRangeMap ();
375 template<
class MatrixType>
381 template<
class MatrixType>
383 return(NumInitialize_);
387 template<
class MatrixType>
393 template<
class MatrixType>
399 template<
class MatrixType>
401 return(InitializeTime_);
405 template<
class MatrixType>
407 return(ComputeTime_);
411 template<
class MatrixType>
417 template<
class MatrixType>
419 return(ComputeFlops_);
423 template<
class MatrixType>
429 template<
class MatrixType>
432 apply (
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
433 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
434 Teuchos::ETransp mode,
441 using Teuchos::rcpFromRef;
444 TEUCHOS_TEST_FOR_EXCEPTION(
445 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::apply: " 446 "The input matrix A is null. Please call setMatrix() with a nonnull " 447 "input matrix, then call compute(), before calling this method.");
448 TEUCHOS_TEST_FOR_EXCEPTION(
451 "Ifpack2::Relaxation::apply: You must call compute() on this Ifpack2 " 452 "preconditioner instance before you may call apply(). You may call " 453 "isComputed() to find out if compute() has been called already.");
454 TEUCHOS_TEST_FOR_EXCEPTION(
455 X.getNumVectors() != Y.getNumVectors(),
457 "Ifpack2::Relaxation::apply: X and Y have different numbers of columns. " 458 "X has " << X.getNumVectors() <<
" columns, but Y has " 459 << Y.getNumVectors() <<
" columns.");
460 TEUCHOS_TEST_FOR_EXCEPTION(
461 beta != STS::zero (), std::logic_error,
462 "Ifpack2::Relaxation::apply: beta = " << beta <<
" != 0 case not " 467 Teuchos::TimeMonitor timeMon (*Time_,
true);
470 if (alpha == STS::zero ()) {
472 Y.putScalar (STS::zero ());
480 auto X_lcl_host = X.template getLocalView<Kokkos::HostSpace> ();
481 auto Y_lcl_host = Y.template getLocalView<Kokkos::HostSpace> ();
482 if (X_lcl_host.ptr_on_device () == Y_lcl_host.ptr_on_device ()) {
483 Xcopy = rcp (
new MV (X, Teuchos::Copy));
485 Xcopy = rcpFromRef (X);
493 case Ifpack2::Details::JACOBI:
494 ApplyInverseJacobi(*Xcopy,Y);
496 case Ifpack2::Details::GS:
497 ApplyInverseGS(*Xcopy,Y);
499 case Ifpack2::Details::SGS:
500 ApplyInverseSGS(*Xcopy,Y);
503 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
504 "Ifpack2::Relaxation::apply: Invalid preconditioner type enum value " 505 << PrecType_ <<
". Please report this bug to the Ifpack2 developers.");
507 if (alpha != STS::one ()) {
509 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
510 const double numVectors = as<double> (Y.getNumVectors ());
511 ApplyFlops_ += numGlobalRows * numVectors;
515 ApplyTime_ += Time_->totalElapsedTime ();
520 template<
class MatrixType>
523 applyMat (
const Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& X,
524 Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& Y,
525 Teuchos::ETransp mode)
const 527 TEUCHOS_TEST_FOR_EXCEPTION(
528 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::applyMat: " 529 "The input matrix A is null. Please call setMatrix() with a nonnull " 530 "input matrix, then call compute(), before calling this method.");
531 TEUCHOS_TEST_FOR_EXCEPTION(
532 !
isComputed (), std::runtime_error,
"Ifpack2::Relaxation::applyMat: " 533 "isComputed() must be true before you may call applyMat(). " 534 "Please call compute() before calling this method.");
535 TEUCHOS_TEST_FOR_EXCEPTION(
536 X.getNumVectors () != Y.getNumVectors (), std::invalid_argument,
537 "Ifpack2::Relaxation::applyMat: X.getNumVectors() = " << X.getNumVectors ()
538 <<
" != Y.getNumVectors() = " << Y.getNumVectors () <<
".");
539 A_->apply (X, Y, mode);
543 template<
class MatrixType>
546 TEUCHOS_TEST_FOR_EXCEPTION(
547 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::initialize: " 548 "The input matrix A is null. Please call setMatrix() with a nonnull " 549 "input matrix before calling this method.");
552 hasBlockCrsMatrix_ =
false;
555 Teuchos::RCP<const block_crs_matrix_type> A_bcrs =
556 Teuchos::rcp_dynamic_cast<
const block_crs_matrix_type> (A_);
557 if (A_bcrs.is_null ()) {
558 hasBlockCrsMatrix_ =
false;
561 hasBlockCrsMatrix_ =
true;
568 isInitialized_ =
true;
571 template<
class MatrixType>
574 using Teuchos::Array;
575 using Teuchos::ArrayRCP;
576 using Teuchos::ArrayView;
581 using Teuchos::REDUCE_MAX;
582 using Teuchos::REDUCE_MIN;
583 using Teuchos::REDUCE_SUM;
584 using Teuchos::rcp_dynamic_cast;
585 using Teuchos::reduceAll;
590 Teuchos::TimeMonitor timeMon (*Time_,
true);
592 TEUCHOS_TEST_FOR_EXCEPTION(
593 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::" 594 "computeBlockCrs: The input matrix A is null. Please call setMatrix() " 595 "with a nonnull input matrix, then call initialize(), before calling " 597 const block_crs_matrix_type* blockCrsA =
598 dynamic_cast<const block_crs_matrix_type*
> (A_.getRawPtr ());
599 TEUCHOS_TEST_FOR_EXCEPTION(
600 blockCrsA == NULL, std::logic_error,
"Ifpack2::Relaxation::" 601 "computeBlockCrs: A_ is not a BlockCrsMatrix, but it should be if we " 602 "got this far. Please report this bug to the Ifpack2 developers.");
611 if (! savedDiagOffsets_) {
612 BlockDiagonal_ = Teuchos::null;
613 BlockDiagonal_ = rcp(
new block_crs_matrix_type(*Ifpack2::Details::computeDiagonalGraph(blockCrsA->getCrsGraph()), blockSize));
614 blockCrsA->getLocalDiagOffsets (diagOffsets_);
615 savedDiagOffsets_ =
true;
617 blockCrsA->getLocalDiagCopy (*BlockDiagonal_, diagOffsets_ ());
619 const size_t numMyRows = A_->getNodeNumRows ();
621 if (DoL1Method_ && IsParallel_) {
623 const size_t maxLength = A_->getNodeMaxNumRowEntries ();
624 Array<local_ordinal_type> indices (maxLength);
625 Array<scalar_type> values (maxLength * blockSize * blockSize);
626 size_t numEntries = 0;
628 for (
size_t i = 0; i < numMyRows; ++i) {
629 blockCrsA->getLocalRowCopy (i, indices (), values (), numEntries);
633 for (
size_t k = 0 ; k < numEntries ; ++k) {
634 if (static_cast<size_t> (indices[k]) > numMyRows) {
635 const size_t offset = blockSize*blockSize*k + subRow*blockSize;
637 diagonal_boost += STS::magnitude (values[offset+subCol] / two);
641 if (STS::magnitude (diagBlock[subRow*(blockSize+1)]) < L1Eta_ * diagonal_boost) {
642 diagBlock[subRow*(blockSize+1)] += diagonal_boost;
648 blockDiagonalFactorizationPivots.resize (numMyRows * blockSize);
650 for (
size_t i = 0 ; i < numMyRows; ++i) {
651 typename block_crs_matrix_type::little_block_type diagBlock =
652 BlockDiagonal_->getLocalBlock (i, i);
653 diagBlock.factorize (&blockDiagonalFactorizationPivots[i*blockSize], info);
656 Importer_ = A_->getGraph ()->getImporter ();
659 ComputeTime_ += Time_->totalElapsedTime ();
664 template<
class MatrixType>
667 using Teuchos::Array;
668 using Teuchos::ArrayRCP;
669 using Teuchos::ArrayView;
674 using Teuchos::REDUCE_MAX;
675 using Teuchos::REDUCE_MIN;
676 using Teuchos::REDUCE_SUM;
677 using Teuchos::rcp_dynamic_cast;
678 using Teuchos::reduceAll;
679 typedef Tpetra::Vector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> vector_type;
688 if (hasBlockCrsMatrix_) {
696 Teuchos::TimeMonitor timeMon (*Time_,
true);
698 TEUCHOS_TEST_FOR_EXCEPTION(
699 A_.is_null (), std::runtime_error,
"Ifpack2::Relaxation::compute: " 700 "The input matrix A is null. Please call setMatrix() with a nonnull " 701 "input matrix, then call initialize(), before calling this method.");
706 TEUCHOS_TEST_FOR_EXCEPTION(
707 NumSweeps_ < 0, std::logic_error,
708 "Ifpack2::Relaxation::compute: NumSweeps_ = " << NumSweeps_ <<
" < 0. " 709 "Please report this bug to the Ifpack2 developers.");
711 Diagonal_ = rcp (
new vector_type (A_->getRowMap ()));
713 TEUCHOS_TEST_FOR_EXCEPTION(
714 Diagonal_.is_null (), std::logic_error,
715 "Ifpack2::Relaxation::compute: Vector of diagonal entries has not been " 716 "created yet. Please report this bug to the Ifpack2 developers.");
734 const crs_matrix_type* crsMat =
735 dynamic_cast<const crs_matrix_type*
> (A_.getRawPtr ());
736 if (crsMat == NULL || ! crsMat->isStaticGraph ()) {
737 A_->getLocalDiagCopy (*Diagonal_);
739 if (! savedDiagOffsets_) {
740 crsMat->getLocalDiagOffsets (diagOffsets_);
741 savedDiagOffsets_ =
true;
743 crsMat->getLocalDiagCopy (*Diagonal_, diagOffsets_ ());
744 #ifdef HAVE_TPETRA_DEBUG 746 vector_type D_copy (A_->getRowMap ());
747 A_->getLocalDiagCopy (D_copy);
748 D_copy.update (STS::one (), *Diagonal_, -STS::one ());
752 TEUCHOS_TEST_FOR_EXCEPTION(
753 err != STM::zero(), std::logic_error,
"Ifpack2::Relaxation::compute: " 754 "\"fast-path\" diagonal computation failed. \\|D1 - D2\\|_inf = " 756 #endif // HAVE_TPETRA_DEBUG 762 RCP<vector_type> origDiag;
763 if (checkDiagEntries_) {
764 origDiag = rcp (
new vector_type (A_->getRowMap ()));
765 Tpetra::deep_copy (*origDiag, *Diagonal_);
771 ArrayRCP<scalar_type> diagHostView = Diagonal_->get1dViewNonConst ();
777 #ifdef HAVE_IFPACK2_DEBUG 778 ArrayView<scalar_type> diag = diagHostView ();
780 scalar_type* KOKKOSCLASSIC_RESTRICT
const diag = diagHostView.getRawPtr ();
781 #endif // HAVE_IFPACK2_DEBUG 783 const size_t numMyRows = A_->getNodeNumRows ();
792 if (DoL1Method_ && IsParallel_) {
794 const size_t maxLength = A_->getNodeMaxNumRowEntries ();
795 Array<local_ordinal_type> indices (maxLength);
796 Array<scalar_type> values (maxLength);
799 for (
size_t i = 0; i < numMyRows; ++i) {
800 A_->getLocalRowCopy (i, indices (), values (), numEntries);
802 for (
size_t k = 0 ; k < numEntries ; ++k) {
803 if (static_cast<size_t> (indices[k]) > numMyRows) {
804 diagonal_boost += STS::magnitude (values[k] / two);
807 if (STS::magnitude (diag[i]) < L1Eta_ * diagonal_boost) {
808 diag[i] += diagonal_boost;
825 const scalar_type oneOverMinDiagVal = (MinDiagonalValue_ == zero) ?
826 one / SmallTraits<scalar_type>::eps () :
827 one / MinDiagonalValue_;
829 const magnitude_type minDiagValMag = STS::magnitude (MinDiagonalValue_);
831 if (checkDiagEntries_) {
837 size_t numSmallDiagEntries = 0;
838 size_t numZeroDiagEntries = 0;
839 size_t numNegDiagEntries = 0;
855 minMagDiagEntryMag = d_0_mag;
856 maxMagDiagEntryMag = d_0_mag;
864 for (
size_t i = 0 ; i < numMyRows; ++i) {
871 if (d_i_real < STM::zero ()) {
874 if (d_i_mag < minMagDiagEntryMag) {
876 minMagDiagEntryMag = d_i_mag;
878 if (d_i_mag > maxMagDiagEntryMag) {
880 maxMagDiagEntryMag = d_i_mag;
883 if (fixTinyDiagEntries_) {
885 if (d_i_mag <= minDiagValMag) {
886 ++numSmallDiagEntries;
887 if (d_i_mag == STM::zero ()) {
888 ++numZeroDiagEntries;
890 diag[i] = oneOverMinDiagVal;
897 if (d_i_mag <= minDiagValMag) {
898 ++numSmallDiagEntries;
899 if (d_i_mag == STM::zero ()) {
900 ++numZeroDiagEntries;
910 diagHostView = Teuchos::null;
915 if (STS::isComplex) {
916 ComputeFlops_ += 4.0 * numMyRows;
918 ComputeFlops_ += numMyRows;
935 const Comm<int>& comm = * (A_->getRowMap ()->getComm ());
938 Array<magnitude_type> localVals (2);
939 localVals[0] = minMagDiagEntryMag;
941 localVals[1] = -maxMagDiagEntryMag;
942 Array<magnitude_type> globalVals (2);
943 reduceAll<int, magnitude_type> (comm, REDUCE_MIN, 2,
944 localVals.getRawPtr (),
945 globalVals.getRawPtr ());
946 globalMinMagDiagEntryMag_ = globalVals[0];
947 globalMaxMagDiagEntryMag_ = -globalVals[1];
949 Array<size_t> localCounts (3);
950 localCounts[0] = numSmallDiagEntries;
951 localCounts[1] = numZeroDiagEntries;
952 localCounts[2] = numNegDiagEntries;
953 Array<size_t> globalCounts (3);
954 reduceAll<int, size_t> (comm, REDUCE_SUM, 3,
955 localCounts.getRawPtr (),
956 globalCounts.getRawPtr ());
957 globalNumSmallDiagEntries_ = globalCounts[0];
958 globalNumZeroDiagEntries_ = globalCounts[1];
959 globalNumNegDiagEntries_ = globalCounts[2];
967 vector_type diff (A_->getRowMap ());
968 diff.reciprocal (*origDiag);
969 diff.update (-one, *Diagonal_, one);
970 globalDiagNormDiff_ = diff.norm2 ();
973 if (fixTinyDiagEntries_) {
977 for (
size_t i = 0 ; i < numMyRows; ++i) {
982 if (d_i_mag <= minDiagValMag) {
983 diag[i] = oneOverMinDiagVal;
990 for (
size_t i = 0 ; i < numMyRows; ++i) {
991 diag[i] = one / diag[i];
994 if (STS::isComplex) {
995 ComputeFlops_ += 4.0 * numMyRows;
997 ComputeFlops_ += numMyRows;
1001 if (IsParallel_ && (PrecType_ == Ifpack2::Details::GS ||
1002 PrecType_ == Ifpack2::Details::SGS)) {
1003 Importer_ = A_->getGraph ()->getImporter ();
1010 ComputeTime_ += Time_->totalElapsedTime ();
1016 template<
class MatrixType>
1019 ApplyInverseJacobi (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1020 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const 1026 if (hasBlockCrsMatrix_) {
1027 ApplyInverseJacobi_BlockCrsMatrix (X, Y);
1031 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1032 const double numVectors = as<double> (X.getNumVectors ());
1033 if (ZeroStartingSolution_) {
1038 Y.elementWiseMultiply (DampingFactor_, *Diagonal_, X, STS::zero ());
1044 double flopUpdate = 0.0;
1045 if (DampingFactor_ == STS::one ()) {
1047 flopUpdate = numGlobalRows * numVectors;
1051 flopUpdate = 2.0 * numGlobalRows * numVectors;
1053 ApplyFlops_ += flopUpdate;
1054 if (NumSweeps_ == 1) {
1060 const int startSweep = ZeroStartingSolution_ ? 1 : 0;
1063 MV A_times_Y (Y.getMap (), as<size_t>(numVectors),
false);
1064 for (
int j = startSweep; j < NumSweeps_; ++j) {
1067 A_times_Y.update (STS::one (), X, -STS::one ());
1068 Y.elementWiseMultiply (DampingFactor_, *Diagonal_, A_times_Y, STS::one ());
1082 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1083 const double dampingFlops = (DampingFactor_ == STS::one ()) ? 0.0 : 1.0;
1084 ApplyFlops_ += as<double> (NumSweeps_ - startSweep) * numVectors *
1085 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1088 template<
class MatrixType>
1096 typedef Tpetra::Experimental::BlockMultiVector<
scalar_type,
1100 typedef typename block_crs_matrix_type::little_block_type little_block_type;
1101 typedef typename block_crs_matrix_type::little_vec_type little_vec_type;
1103 if (ZeroStartingSolution_) {
1104 Y.putScalar (STS::zero ());
1107 const size_t numVectors = X.getNumVectors ();
1109 const block_crs_matrix_type* blockMat =
1110 dynamic_cast<const block_crs_matrix_type*
> (A_.getRawPtr ());
1112 const local_ordinal_type blockSize = blockMat->getBlockSize ();
1113 BMV A_times_Y_Block (* (blockMat->getRowMap ()), * (Y.getMap ()),
1114 blockSize, numVectors);
1115 MV A_times_Y = A_times_Y_Block.getMultiVectorView();
1116 BMV yBlock (Y, * (blockMat->getRowMap ()), blockSize);
1117 for (
int j = 0; j < NumSweeps_; ++j) {
1118 blockMat->apply (Y, A_times_Y);
1119 A_times_Y.update (STS::one (), X, -STS::one ());
1120 const size_t numRows = blockMat->getNodeNumRows ();
1121 for (
size_t i = 0; i < numVectors; ++i) {
1122 for (
size_t k = 0; k < numRows; ++k) {
1124 little_block_type factorizedBlockDiag = BlockDiagonal_->getLocalBlock (k, k);
1125 little_vec_type xloc = A_times_Y_Block.getLocalBlock (k, i);
1126 little_vec_type yloc = yBlock.getLocalBlock (k, i);
1127 factorizedBlockDiag.solve (xloc, &blockDiagonalFactorizationPivots[i*blockSize]);
1128 yloc.update (DampingFactor_, xloc);
1134 template<
class MatrixType>
1137 ApplyInverseGS (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1138 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const 1150 const block_crs_matrix_type* blockCrsMat =
1151 dynamic_cast<const block_crs_matrix_type*
> (A_.getRawPtr ());
1152 const crs_matrix_type* crsMat =
1153 dynamic_cast<const crs_matrix_type*
> (A_.getRawPtr ());
1154 if (blockCrsMat != NULL) {
1155 const_cast<this_type*
> (
this)->ApplyInverseGS_BlockCrsMatrix (*blockCrsMat, X, Y);
1156 }
else if (crsMat != NULL) {
1157 ApplyInverseGS_CrsMatrix (*crsMat, X, Y);
1159 ApplyInverseGS_RowMatrix (X, Y);
1164 template<
class MatrixType>
1167 ApplyInverseGS_RowMatrix (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1168 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const 1170 using Teuchos::Array;
1171 using Teuchos::ArrayRCP;
1172 using Teuchos::ArrayView;
1176 using Teuchos::rcpFromRef;
1177 typedef Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> MV;
1182 if (ZeroStartingSolution_) {
1183 Y.putScalar (STS::zero ());
1186 const size_t NumVectors = X.getNumVectors ();
1187 const size_t maxLength = A_->getNodeMaxNumRowEntries ();
1188 Array<local_ordinal_type> Indices (maxLength);
1189 Array<scalar_type> Values (maxLength);
1192 const size_t numMyRows = A_->getNodeNumRows();
1194 size_t numActive = numMyRows;
1195 bool do_local = ! localSmoothingIndices_.is_null ();
1197 rowInd = localSmoothingIndices_.getRawPtr ();
1198 numActive = localSmoothingIndices_.size ();
1203 if (Importer_.is_null ()) {
1205 Y2 = rcp (
new MV (Y.getMap (), NumVectors,
false));
1210 Y2 = rcp (
new MV (Importer_->getTargetMap (), NumVectors));
1214 Y2 = rcpFromRef (Y);
1218 ArrayRCP<const scalar_type> d_rcp = Diagonal_->get1dView ();
1219 ArrayView<const scalar_type> d_ptr = d_rcp();
1222 bool constant_stride = X.isConstantStride() && Y2->isConstantStride();
1224 if (constant_stride) {
1226 size_t x_stride = X.getStride();
1227 size_t y2_stride = Y2->getStride();
1228 ArrayRCP<scalar_type> y2_rcp = Y2->get1dViewNonConst();
1229 ArrayRCP<const scalar_type> x_rcp = X.get1dView();
1230 ArrayView<scalar_type> y2_ptr = y2_rcp();
1231 ArrayView<const scalar_type> x_ptr = x_rcp();
1232 Array<scalar_type> dtemp(NumVectors,STS::zero());
1234 for (
int j = 0; j < NumSweeps_; ++j) {
1237 if (Importer_.is_null ()) {
1240 Y2->doImport (Y, *Importer_, Tpetra::INSERT);
1244 if (! DoBackwardGS_) {
1245 for (
size_t ii = 0; ii < numActive; ++ii) {
1248 A_->getLocalRowCopy (i, Indices (), Values (), NumEntries);
1249 dtemp.assign(NumVectors,STS::zero());
1251 for (
size_t k = 0; k < NumEntries; ++k) {
1253 for (
size_t m = 0; m < NumVectors; ++m) {
1254 dtemp[m] += Values[k] * y2_ptr[col + y2_stride*m];
1258 for (
size_t m = 0; m < NumVectors; ++m) {
1259 y2_ptr[i + y2_stride*m] += DampingFactor_ * d_ptr[i] * (x_ptr[i + x_stride*m] - dtemp[m]);
1266 for (ptrdiff_t ii = as<ptrdiff_t> (numActive) - 1; ii >= 0; --ii) {
1269 A_->getLocalRowCopy (i, Indices (), Values (), NumEntries);
1270 dtemp.assign (NumVectors, STS::zero ());
1272 for (
size_t k = 0; k < NumEntries; ++k) {
1274 for (
size_t m = 0; m < NumVectors; ++m) {
1275 dtemp[m] += Values[k] * y2_ptr[col + y2_stride*m];
1279 for (
size_t m = 0; m < NumVectors; ++m) {
1280 y2_ptr[i + y2_stride*m] += DampingFactor_ * d_ptr[i] * (x_ptr[i + x_stride*m] - dtemp[m]);
1286 Tpetra::deep_copy (Y, *Y2);
1292 ArrayRCP<ArrayRCP<scalar_type> > y2_ptr = Y2->get2dViewNonConst ();
1293 ArrayRCP<ArrayRCP<const scalar_type> > x_ptr = X.get2dView ();
1295 for (
int j = 0; j < NumSweeps_; ++j) {
1298 if (Importer_.is_null ()) {
1301 Y2->doImport (Y, *Importer_, Tpetra::INSERT);
1305 if (! DoBackwardGS_) {
1306 for (
size_t ii = 0; ii < numActive; ++ii) {
1309 A_->getLocalRowCopy (i, Indices (), Values (), NumEntries);
1311 for (
size_t m = 0; m < NumVectors; ++m) {
1313 ArrayView<const scalar_type> x_local = (x_ptr())[m]();
1314 ArrayView<scalar_type> y2_local = (y2_ptr())[m]();
1316 for (
size_t k = 0; k < NumEntries; ++k) {
1318 dtemp += Values[k] * y2_local[col];
1320 y2_local[i] += DampingFactor_ * d_ptr[i] * (x_local[i] - dtemp);
1327 for (ptrdiff_t ii = as<ptrdiff_t> (numActive) - 1; ii >= 0; --ii) {
1331 A_->getLocalRowCopy (i, Indices (), Values (), NumEntries);
1333 for (
size_t m = 0; m < NumVectors; ++m) {
1335 ArrayView<const scalar_type> x_local = (x_ptr())[m]();
1336 ArrayView<scalar_type> y2_local = (y2_ptr())[m]();
1338 for (
size_t k = 0; k < NumEntries; ++k) {
1340 dtemp += Values[k] * y2_local[col];
1342 y2_local[i] += DampingFactor_ * d_ptr[i] * (x_local[i] - dtemp);
1349 Tpetra::deep_copy (Y, *Y2);
1356 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1357 const double numVectors = as<double> (X.getNumVectors ());
1358 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1359 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1360 ApplyFlops_ += 2.0 * NumSweeps_ * numVectors *
1361 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1365 template<
class MatrixType>
1369 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1370 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const 1373 const Tpetra::ESweepDirection direction =
1374 DoBackwardGS_ ? Tpetra::Backward : Tpetra::Forward;
1375 if (localSmoothingIndices_.is_null ()) {
1376 A.gaussSeidelCopy (Y, X, *Diagonal_, DampingFactor_, direction,
1377 NumSweeps_, ZeroStartingSolution_);
1380 A.reorderedGaussSeidelCopy (Y, X, *Diagonal_, localSmoothingIndices_ (),
1381 DampingFactor_, direction,
1382 NumSweeps_, ZeroStartingSolution_);
1396 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1397 const double numVectors = as<double> (X.getNumVectors ());
1398 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1399 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1400 ApplyFlops_ += NumSweeps_ * numVectors *
1401 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1404 template<
class MatrixType>
1408 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1409 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
1413 using Teuchos::rcpFromRef;
1414 typedef Tpetra::Experimental::BlockMultiVector<
scalar_type,
1426 BMV yBlock (Y, * (A.getGraph ()->getDomainMap ()), A.getBlockSize ());
1427 const BMV xBlock (X, * (A.getColMap ()), A.getBlockSize ());
1429 bool performImport =
false;
1431 if (Importer_.is_null ()) {
1432 yBlockCol = rcpFromRef (yBlock);
1435 if (yBlockColumnPointMap_.is_null () ||
1436 yBlockColumnPointMap_->getNumVectors () != yBlock.getNumVectors () ||
1437 yBlockColumnPointMap_->getBlockSize () != yBlock.getBlockSize ()) {
1438 yBlockColumnPointMap_ =
1439 rcp (
new BMV (* (A.getColMap ()), A.getBlockSize (),
1440 static_cast<local_ordinal_type
> (yBlock.getNumVectors ())));
1442 yBlockCol = yBlockColumnPointMap_;
1443 performImport =
true;
1446 if (ZeroStartingSolution_) {
1447 yBlockCol->putScalar (STS::zero ());
1449 else if (performImport) {
1450 yBlockCol->doImport (yBlock, *Importer_, Tpetra::INSERT);
1453 const Tpetra::ESweepDirection direction =
1454 DoBackwardGS_ ? Tpetra::Backward : Tpetra::Forward;
1456 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
1457 if (performImport && sweep > 0) {
1458 yBlockCol->doImport(yBlock, *Importer_, Tpetra::INSERT);
1460 A.localGaussSeidel (xBlock, *yBlockCol, *BlockDiagonal_,
1461 &blockDiagonalFactorizationPivots[0],
1462 DampingFactor_, direction);
1463 if (performImport) {
1464 RCP<const MV> yBlockColPointDomain =
1465 yBlockCol->getMultiVectorView ().offsetView (A.getDomainMap (), 0);
1466 Tpetra::deep_copy (Y, *yBlockColPointDomain);
1472 template<
class MatrixType>
1475 ApplyInverseSGS (
const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1476 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const 1488 const block_crs_matrix_type* blockCrsMat =
dynamic_cast<const block_crs_matrix_type*
> (A_.getRawPtr());
1489 const crs_matrix_type* crsMat =
dynamic_cast<const crs_matrix_type*
> (&(*A_));
1490 if (blockCrsMat != NULL) {
1491 const_cast<this_type*
> (
this)->ApplyInverseSGS_BlockCrsMatrix(*blockCrsMat, X, Y);
1493 else if (crsMat != NULL) {
1494 ApplyInverseSGS_CrsMatrix (*crsMat, X, Y);
1496 ApplyInverseSGS_RowMatrix (X, Y);
1501 template<
class MatrixType>
1505 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const 1507 using Teuchos::Array;
1508 using Teuchos::ArrayRCP;
1509 using Teuchos::ArrayView;
1513 using Teuchos::rcpFromRef;
1514 typedef Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> MV;
1519 if (ZeroStartingSolution_) {
1520 Y.putScalar (STS::zero ());
1523 const size_t NumVectors = X.getNumVectors ();
1524 const size_t maxLength = A_->getNodeMaxNumRowEntries ();
1525 Array<local_ordinal_type> Indices (maxLength);
1526 Array<scalar_type> Values (maxLength);
1529 const size_t numMyRows = A_->getNodeNumRows();
1531 size_t numActive = numMyRows;
1532 bool do_local = localSmoothingIndices_.is_null();
1534 rowInd = localSmoothingIndices_.getRawPtr();
1535 numActive = localSmoothingIndices_.size();
1541 if (Importer_.is_null ()) {
1543 Y2 = rcp (
new MV (Y.getMap (), NumVectors,
false));
1548 Y2 = rcp (
new MV (Importer_->getTargetMap (), NumVectors));
1552 Y2 = rcpFromRef (Y);
1556 ArrayRCP<const scalar_type> d_rcp = Diagonal_->get1dView();
1557 ArrayView<const scalar_type> d_ptr = d_rcp();
1560 bool constant_stride = X.isConstantStride() && Y2->isConstantStride();
1562 if(constant_stride) {
1564 size_t x_stride = X.getStride();
1565 size_t y2_stride = Y2->getStride();
1566 ArrayRCP<scalar_type> y2_rcp = Y2->get1dViewNonConst();
1567 ArrayRCP<const scalar_type> x_rcp = X.get1dView();
1568 ArrayView<scalar_type> y2_ptr = y2_rcp();
1569 ArrayView<const scalar_type> x_ptr = x_rcp();
1570 Array<scalar_type> dtemp(NumVectors,STS::zero());
1571 for (
int iter = 0; iter < NumSweeps_; ++iter) {
1574 if (Importer_.is_null ()) {
1576 Tpetra::deep_copy (*Y2, Y);
1578 Y2->doImport (Y, *Importer_, Tpetra::INSERT);
1582 for (
int j = 0; j < NumSweeps_; j++) {
1585 if (Importer_.is_null ()) {
1587 Tpetra::deep_copy (*Y2, Y);
1589 Y2->doImport (Y, *Importer_, Tpetra::INSERT);
1593 for (
size_t ii = 0; ii < numActive; ++ii) {
1596 A_->getLocalRowCopy (i, Indices (), Values (), NumEntries);
1597 dtemp.assign(NumVectors,STS::zero());
1599 for (
size_t k = 0; k < NumEntries; ++k) {
1601 for (
size_t m = 0; m < NumVectors; ++m) {
1602 dtemp[m] += Values[k] * y2_ptr[col + y2_stride*m];
1606 for (
size_t m = 0; m < NumVectors; ++m) {
1607 y2_ptr[i + y2_stride*m] += DampingFactor_ * d_ptr[i] * (x_ptr[i + x_stride*m] - dtemp[m]);
1613 for (ptrdiff_t ii = as<ptrdiff_t> (numActive) - 1; ii >= 0; --ii) {
1616 A_->getLocalRowCopy (i, Indices (), Values (), NumEntries);
1617 dtemp.assign(NumVectors,STS::zero());
1619 for (
size_t k = 0; k < NumEntries; ++k) {
1621 for (
size_t m = 0; m < NumVectors; ++m) {
1622 dtemp[m] += Values[k] * y2_ptr[col + y2_stride*m];
1626 for (
size_t m = 0; m < NumVectors; ++m) {
1627 y2_ptr[i + y2_stride*m] += DampingFactor_ * d_ptr[i] * (x_ptr[i + x_stride*m] - dtemp[m]);
1634 Tpetra::deep_copy (Y, *Y2);
1640 ArrayRCP<ArrayRCP<scalar_type> > y2_ptr = Y2->get2dViewNonConst ();
1641 ArrayRCP<ArrayRCP<const scalar_type> > x_ptr = X.get2dView ();
1643 for (
int iter = 0; iter < NumSweeps_; ++iter) {
1646 if (Importer_.is_null ()) {
1648 Tpetra::deep_copy (*Y2, Y);
1650 Y2->doImport (Y, *Importer_, Tpetra::INSERT);
1654 for (
size_t ii = 0; ii < numActive; ++ii) {
1658 A_->getLocalRowCopy (as<local_ordinal_type> (i), Indices (), Values (), NumEntries);
1660 for (
size_t m = 0; m < NumVectors; ++m) {
1662 ArrayView<const scalar_type> x_local = (x_ptr())[m]();
1663 ArrayView<scalar_type> y2_local = (y2_ptr())[m]();
1665 for (
size_t k = 0; k < NumEntries; ++k) {
1667 dtemp += Values[k] * y2_local[col];
1669 y2_local[i] += DampingFactor_ * (x_local[i] - dtemp) * diag;
1675 for (ptrdiff_t ii = as<ptrdiff_t> (numActive) - 1; ii >= 0; --ii) {
1679 A_->getLocalRowCopy (as<local_ordinal_type> (i), Indices (), Values (), NumEntries);
1681 for (
size_t m = 0; m < NumVectors; ++m) {
1683 ArrayView<const scalar_type> x_local = (x_ptr())[m]();
1684 ArrayView<scalar_type> y2_local = (y2_ptr())[m]();
1686 for (
size_t k = 0; k < NumEntries; ++k) {
1688 dtemp += Values[k] * y2_local[col];
1690 y2_local[i] += DampingFactor_ * (x_local[i] - dtemp) * diag;
1696 Tpetra::deep_copy (Y, *Y2);
1702 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1703 const double numVectors = as<double> (X.getNumVectors ());
1704 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1705 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1706 ApplyFlops_ += 2.0 * NumSweeps_ * numVectors *
1707 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1711 template<
class MatrixType>
1715 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1716 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
const 1719 const Tpetra::ESweepDirection direction = Tpetra::Symmetric;
1720 if (localSmoothingIndices_.is_null ()) {
1721 A.gaussSeidelCopy (Y, X, *Diagonal_, DampingFactor_, direction,
1722 NumSweeps_, ZeroStartingSolution_);
1725 A.reorderedGaussSeidelCopy (Y, X, *Diagonal_, localSmoothingIndices_ (),
1726 DampingFactor_, direction,
1727 NumSweeps_, ZeroStartingSolution_);
1744 const double dampingFlops = (DampingFactor_ == STS::one()) ? 0.0 : 1.0;
1745 const double numVectors = as<double> (X.getNumVectors ());
1746 const double numGlobalRows = as<double> (A_->getGlobalNumRows ());
1747 const double numGlobalNonzeros = as<double> (A_->getGlobalNumEntries ());
1748 ApplyFlops_ += 2.0 * NumSweeps_ * numVectors *
1749 (2.0 * numGlobalRows + 2.0 * numGlobalNonzeros + dampingFlops);
1752 template<
class MatrixType>
1756 const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
1757 Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y)
1761 using Teuchos::rcpFromRef;
1762 typedef Tpetra::Experimental::BlockMultiVector<
scalar_type,
1774 BMV yBlock (Y, * (A.getGraph ()->getDomainMap ()), A.getBlockSize ());
1775 const BMV xBlock (X, * (A.getColMap ()), A.getBlockSize ());
1777 bool performImport =
false;
1779 if (Importer_.is_null ()) {
1780 yBlockCol = Teuchos::rcpFromRef (yBlock);
1783 if (yBlockColumnPointMap_.is_null () ||
1784 yBlockColumnPointMap_->getNumVectors () != yBlock.getNumVectors () ||
1785 yBlockColumnPointMap_->getBlockSize () != yBlock.getBlockSize ()) {
1786 yBlockColumnPointMap_ =
1787 rcp (
new BMV (* (A.getColMap ()), A.getBlockSize (),
1788 static_cast<local_ordinal_type
> (yBlock.getNumVectors ())));
1790 yBlockCol = yBlockColumnPointMap_;
1791 performImport =
true;
1794 if (ZeroStartingSolution_) {
1795 yBlockCol->putScalar (STS::zero ());
1797 else if (performImport) {
1798 yBlockCol->doImport (yBlock, *Importer_, Tpetra::INSERT);
1802 const Tpetra::ESweepDirection direction = Tpetra::Symmetric;
1804 for (
int sweep = 0; sweep < NumSweeps_; ++sweep) {
1805 if (performImport && sweep > 0) {
1806 yBlockCol->doImport (yBlock, *Importer_, Tpetra::INSERT);
1808 A.localGaussSeidel (xBlock, *yBlockCol, *BlockDiagonal_,
1809 &blockDiagonalFactorizationPivots[0],
1810 DampingFactor_, direction);
1811 if (performImport) {
1812 RCP<const MV> yBlockColPointDomain =
1813 yBlockCol->getMultiVectorView ().offsetView (A.getDomainMap (), 0);
1814 MV yBlockView = yBlock.getMultiVectorView ();
1815 Tpetra::deep_copy (yBlockView, *yBlockColPointDomain);
1821 template<
class MatrixType>
1824 std::ostringstream os;
1829 os <<
"\"Ifpack2::Relaxation\": {";
1831 os <<
"Initialized: " << (
isInitialized () ?
"true" :
"false") <<
", " 1832 <<
"Computed: " << (
isComputed () ?
"true" :
"false") <<
", ";
1838 if (PrecType_ == Ifpack2::Details::JACOBI) {
1840 }
else if (PrecType_ == Ifpack2::Details::GS) {
1841 os <<
"Gauss-Seidel";
1842 }
else if (PrecType_ == Ifpack2::Details::SGS) {
1843 os <<
"Symmetric Gauss-Seidel";
1848 os <<
", " <<
"sweeps: " << NumSweeps_ <<
", " 1849 <<
"damping factor: " << DampingFactor_ <<
", ";
1851 os <<
"use l1: " << DoL1Method_ <<
", " 1852 <<
"l1 eta: " << L1Eta_ <<
", ";
1855 if (A_.is_null ()) {
1856 os <<
"Matrix: null";
1859 os <<
"Global matrix dimensions: [" 1860 << A_->getGlobalNumRows () <<
", " << A_->getGlobalNumCols () <<
"]" 1861 <<
", Global nnz: " << A_->getGlobalNumEntries();
1869 template<
class MatrixType>
1873 const Teuchos::EVerbosityLevel verbLevel)
const 1875 using Teuchos::OSTab;
1876 using Teuchos::TypeNameTraits;
1877 using Teuchos::VERB_DEFAULT;
1878 using Teuchos::VERB_NONE;
1879 using Teuchos::VERB_LOW;
1880 using Teuchos::VERB_MEDIUM;
1881 using Teuchos::VERB_HIGH;
1882 using Teuchos::VERB_EXTREME;
1885 const Teuchos::EVerbosityLevel vl =
1886 (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
1888 const int myRank = this->
getComm ()->getRank ();
1896 if (vl != VERB_NONE && myRank == 0) {
1900 out <<
"\"Ifpack2::Relaxation\":" << endl;
1902 out <<
"MatrixType: \"" << TypeNameTraits<MatrixType>::name () <<
"\"" 1904 if (this->getObjectLabel () !=
"") {
1905 out <<
"Label: " << this->getObjectLabel () << endl;
1907 out <<
"Initialized: " << (
isInitialized () ?
"true" :
"false") << endl
1908 <<
"Computed: " << (
isComputed () ?
"true" :
"false") << endl
1909 <<
"Parameters: " << endl;
1912 out <<
"\"relaxation: type\": ";
1913 if (PrecType_ == Ifpack2::Details::JACOBI) {
1915 }
else if (PrecType_ == Ifpack2::Details::GS) {
1916 out <<
"Gauss-Seidel";
1917 }
else if (PrecType_ == Ifpack2::Details::SGS) {
1918 out <<
"Symmetric Gauss-Seidel";
1925 <<
"\"relaxation: sweeps\": " << NumSweeps_ << endl
1926 <<
"\"relaxation: damping factor\": " << DampingFactor_ << endl
1927 <<
"\"relaxation: min diagonal value\": " << MinDiagonalValue_ << endl
1928 <<
"\"relaxation: zero starting solution\": " << ZeroStartingSolution_ << endl
1929 <<
"\"relaxation: backward mode\": " << DoBackwardGS_ << endl
1930 <<
"\"relaxation: use l1\": " << DoL1Method_ << endl
1931 <<
"\"relaxation: l1 eta\": " << L1Eta_ << endl;
1933 out <<
"Computed quantities:" << endl;
1936 out <<
"Global number of rows: " << A_->getGlobalNumRows () << endl
1937 <<
"Global number of columns: " << A_->getGlobalNumCols () << endl;
1940 out <<
"Properties of input diagonal entries:" << endl;
1943 out <<
"Magnitude of minimum-magnitude diagonal entry: " 1944 << globalMinMagDiagEntryMag_ << endl
1945 <<
"Magnitude of maximum-magnitude diagonal entry: " 1946 << globalMaxMagDiagEntryMag_ << endl
1947 <<
"Number of diagonal entries with small magnitude: " 1948 << globalNumSmallDiagEntries_ << endl
1949 <<
"Number of zero diagonal entries: " 1950 << globalNumZeroDiagEntries_ << endl
1951 <<
"Number of diagonal entries with negative real part: " 1952 << globalNumNegDiagEntries_ << endl
1953 <<
"Abs 2-norm diff between computed and actual inverse " 1954 <<
"diagonal: " << globalDiagNormDiff_ << endl;
1958 out <<
"Saved diagonal offsets: " 1959 << (savedDiagOffsets_ ?
"true" :
"false") << endl;
1961 out <<
"Call counts and total times (in seconds): " << endl;
1964 out <<
"initialize: " << endl;
1967 out <<
"Call count: " << NumInitialize_ << endl;
1968 out <<
"Total time: " << InitializeTime_ << endl;
1970 out <<
"compute: " << endl;
1973 out <<
"Call count: " << NumCompute_ << endl;
1974 out <<
"Total time: " << ComputeTime_ << endl;
1976 out <<
"apply: " << endl;
1979 out <<
"Call count: " << NumApply_ << endl;
1980 out <<
"Total time: " << ApplyTime_ << endl;
1988 #define IFPACK2_RELAXATION_INSTANT(S,LO,GO,N) \ 1989 template class Ifpack2::Relaxation< Tpetra::RowMatrix<S, LO, GO, N> >; 1991 #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:376
double getComputeFlops() const
Total number of floating-point operations over all calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:418
double getApplyFlops() const
Total number of floating-point operations over all calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:424
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:1872
void compute()
Compute the preconditioner.
Definition: Ifpack2_Relaxation_def.hpp:665
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix and vectors are distributed.
Definition: Ifpack2_Relaxation_def.hpp:333
int getNumApply() const
Total number of calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:394
Ifpack2 implementation details.
double getComputeTime() const
Total time in seconds spent in all calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:406
MatrixType::node_type node_type
The Node type used by the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:246
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:353
void setParameters(const Teuchos::ParameterList ¶ms)
Set the relaxation / preconditioner parameters.
Definition: Ifpack2_Relaxation_def.hpp:323
File for utility functions.
std::string description() const
A simple one-line description of this object.
Definition: Ifpack2_Relaxation_def.hpp:1822
int getNumInitialize() const
Total number of calls to initialize().
Definition: Ifpack2_Relaxation_def.hpp:382
bool isComputed() const
Return true if compute() has been called.
Definition: Ifpack2_Relaxation_decl.hpp:412
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:366
MatrixType::global_ordinal_type global_ordinal_type
The type of global indices in the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:243
double getInitializeTime() const
Total time in seconds spent in all calls to initialize().
Definition: Ifpack2_Relaxation_def.hpp:400
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 preconditioner to X, returning the result in Y.
Definition: Ifpack2_Relaxation_def.hpp:523
Definition: Ifpack2_Details_Amesos2Wrapper_decl.hpp:63
Teuchos::RCP< const row_matrix_type > getMatrix() const
The matrix to be preconditioned.
Definition: Ifpack2_Relaxation_def.hpp:344
MatrixType::local_ordinal_type local_ordinal_type
The type of local indices in the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:240
MatrixType::scalar_type scalar_type
The type of the entries of the input MatrixType.
Definition: Ifpack2_Relaxation_decl.hpp:237
virtual ~Relaxation()
Destructor.
Definition: Ifpack2_Relaxation_def.hpp:208
int getNumCompute() const
Total number of calls to compute().
Definition: Ifpack2_Relaxation_def.hpp:388
bool isInitialized() const
Returns true if the preconditioner has been successfully initialized.
Definition: Ifpack2_Relaxation_decl.hpp:397
Relaxation preconditioners for Tpetra::RowMatrix and Tpetra::CrsMatrix sparse matrices.
Definition: Ifpack2_Relaxation_decl.hpp:222
Preconditioners and smoothers for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:72
double getApplyTime() const
Total time in seconds spent in all calls to apply().
Definition: Ifpack2_Relaxation_def.hpp:412
void initialize()
Initialize the preconditioner.
Definition: Ifpack2_Relaxation_def.hpp:544
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:432
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a list of all the parameters that this class accepts.
Definition: Ifpack2_Relaxation_def.hpp:213
Teuchos::ScalarTraits< scalar_type >::magnitudeType magnitude_type
The type of the magnitude (absolute value) of a matrix entry.
Definition: Ifpack2_Relaxation_decl.hpp:249