Tifpack Templated Preconditioning Package Version 1.0
Ifpack2_Relaxation_def.hpp
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack2: Tempated Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2009) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 //@HEADER
00028 */
00029 
00030 #ifndef IFPACK2_RELAXATION_DEF_HPP
00031 #define IFPACK2_RELAXATION_DEF_HPP
00032 
00033 #include "Ifpack2_Relaxation_decl.hpp"
00034 
00035 namespace Ifpack2 {
00036 
00037 //==========================================================================
00038 template<class MatrixType>
00039 Relaxation<MatrixType>::Relaxation(const Teuchos::RCP<const Tpetra::RowMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& A)
00040 : A_(A),
00041   Comm_(A->getRowMap()->getComm()),
00042   Time_( Teuchos::rcp( new Teuchos::Time("Ifpack2::Relaxation") ) ),
00043   NumSweeps_(1),
00044   PrecType_(Ifpack2::JACOBI),
00045   MinDiagonalValue_(0.0),
00046   DampingFactor_(1.0),
00047   IsParallel_(false),
00048   ZeroStartingSolution_(true),
00049   DoBackwardGS_(false),
00050   Condest_(-1.0),
00051   IsInitialized_(false),
00052   IsComputed_(false),
00053   NumInitialize_(0),
00054   NumCompute_(0),
00055   NumApply_(0),
00056   InitializeTime_(0.0),
00057   ComputeTime_(0.0),
00058   ApplyTime_(0.0),
00059   ComputeFlops_(0.0),
00060   ApplyFlops_(0.0),
00061   NumMyRows_(0),
00062   NumGlobalRows_(0),
00063   NumGlobalNonzeros_(0)
00064 {
00065   TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error, 
00066       Teuchos::typeName(*this) << "::Relaxation(): input matrix reference was null.");
00067 }
00068 
00069 //==========================================================================
00070 template<class MatrixType>
00071 Relaxation<MatrixType>::~Relaxation() {
00072 }
00073 
00074 //==========================================================================
00075 template<class MatrixType>
00076 void Relaxation<MatrixType>::setParameters(const Teuchos::ParameterList& List)
00077 {
00078   Teuchos::ParameterList validparams;
00079   Ifpack2::getValidParameters(validparams);
00080   List.validateParameters(validparams);
00081 
00082   std::string PT;
00083   if (PrecType_ == Ifpack2::JACOBI)
00084     PT = "Jacobi";
00085   else if (PrecType_ == Ifpack2::GS)
00086     PT = "Gauss-Seidel";
00087   else if (PrecType_ == Ifpack2::SGS)
00088     PT = "Symmetric Gauss-Seidel";
00089 
00090   Ifpack2::getParameter(List, "relaxation: type", PT);
00091 
00092   if (PT == "Jacobi")
00093     PrecType_ = Ifpack2::JACOBI;
00094   else if (PT == "Gauss-Seidel")
00095     PrecType_ = Ifpack2::GS;
00096   else if (PT == "Symmetric Gauss-Seidel")
00097     PrecType_ = Ifpack2::SGS;
00098   else {
00099     std::ostringstream osstr;
00100     osstr << "Ifpack2::Relaxation::setParameters: unsupported parameter-value for 'relaxation: type' (" << PT << ")";
00101     std::string str = osstr.str();
00102     throw std::runtime_error(str);
00103   }
00104 
00105   Ifpack2::getParameter(List, "relaxation: sweeps",NumSweeps_);
00106   Ifpack2::getParameter(List, "relaxation: damping factor", DampingFactor_);
00107   Ifpack2::getParameter(List, "relaxation: min diagonal value", MinDiagonalValue_);
00108   Ifpack2::getParameter(List, "relaxation: zero starting solution", ZeroStartingSolution_);
00109   Ifpack2::getParameter(List, "relaxation: backward mode",DoBackwardGS_);
00110 }
00111 
00112 //==========================================================================
00113 template<class MatrixType>
00114 const Teuchos::RCP<const Teuchos::Comm<int> > & 
00115 Relaxation<MatrixType>::getComm() const{
00116   return(Comm_);
00117 }
00118 
00119 //==========================================================================
00120 template<class MatrixType>
00121 Teuchos::RCP<const Tpetra::RowMatrix<typename MatrixType::scalar_type,
00122                                      typename MatrixType::local_ordinal_type,
00123                                      typename MatrixType::global_ordinal_type,
00124                                      typename MatrixType::node_type> >
00125 Relaxation<MatrixType>::getMatrix() const {
00126   return(A_);
00127 }
00128 
00129 //==========================================================================
00130 template<class MatrixType>
00131 const Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,
00132                                      typename MatrixType::global_ordinal_type,
00133                                      typename MatrixType::node_type> >&
00134 Relaxation<MatrixType>::getDomainMap() const {
00135   return A_->getDomainMap();
00136 }
00137 
00138 //==========================================================================
00139 template<class MatrixType>
00140 const Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,
00141                                      typename MatrixType::global_ordinal_type,
00142                                      typename MatrixType::node_type> >&
00143 Relaxation<MatrixType>::getRangeMap() const {
00144   return A_->getRangeMap();
00145 }
00146 
00147 //==========================================================================
00148 template<class MatrixType>
00149 bool Relaxation<MatrixType>::hasTransposeApply() const {
00150   return true;
00151 }
00152 
00153 //==========================================================================
00154 template<class MatrixType>
00155 int Relaxation<MatrixType>::getNumInitialize() const {
00156   return(NumInitialize_);
00157 }
00158 
00159 //==========================================================================
00160 template<class MatrixType>
00161 int Relaxation<MatrixType>::getNumCompute() const {
00162   return(NumCompute_);
00163 }
00164 
00165 //==========================================================================
00166 template<class MatrixType>
00167 int Relaxation<MatrixType>::getNumApply() const {
00168   return(NumApply_);
00169 }
00170 
00171 //==========================================================================
00172 template<class MatrixType>
00173 double Relaxation<MatrixType>::getInitializeTime() const {
00174   return(InitializeTime_);
00175 }
00176 
00177 //==========================================================================
00178 template<class MatrixType>
00179 double Relaxation<MatrixType>::getComputeTime() const {
00180   return(ComputeTime_);
00181 }
00182 
00183 //==========================================================================
00184 template<class MatrixType>
00185 double Relaxation<MatrixType>::getApplyTime() const {
00186   return(ApplyTime_);
00187 }
00188 
00189 //==========================================================================
00190 template<class MatrixType>
00191 double Relaxation<MatrixType>::getComputeFlops() const {
00192   return(ComputeFlops_);
00193 }
00194 
00195 //==========================================================================
00196 template<class MatrixType>
00197 double Relaxation<MatrixType>::getApplyFlops() const {
00198   return(ApplyFlops_);
00199 }
00200 
00201 //==========================================================================
00202 template<class MatrixType>
00203 typename Teuchos::ScalarTraits<typename MatrixType::scalar_type>::magnitudeType
00204 Relaxation<MatrixType>::getCondEst() const
00205 {
00206   return(Condest_);
00207 }
00208 
00209 //==========================================================================
00210 template<class MatrixType>
00211 typename Teuchos::ScalarTraits<typename MatrixType::scalar_type>::magnitudeType
00212 Relaxation<MatrixType>::computeCondEst(
00213                      CondestType CT,
00214                      typename MatrixType::local_ordinal_type MaxIters, 
00215                      magnitudeType Tol,
00216      const Teuchos::Ptr<const Tpetra::RowMatrix<typename MatrixType::scalar_type,
00217                                                 typename MatrixType::local_ordinal_type,
00218                                                 typename MatrixType::global_ordinal_type,
00219                                                 typename MatrixType::node_type> > &matrix)
00220 {
00221   if (!isComputed()) // cannot compute right now
00222     return(-1.0);
00223 
00224   // always compute it. Call Condest() with no parameters to get
00225   // the previous estimate.
00226   Condest_ = Ifpack2::Condest(*this, CT, MaxIters, Tol, matrix);
00227 
00228   return(Condest_);
00229 }
00230 
00231 //==========================================================================
00232 template<class MatrixType>
00233 void Relaxation<MatrixType>::apply(
00234           const Tpetra::MultiVector<typename MatrixType::scalar_type,
00235                                     typename MatrixType::local_ordinal_type,
00236                                     typename MatrixType::global_ordinal_type,
00237                                     typename MatrixType::node_type>& X,
00238                 Tpetra::MultiVector<typename MatrixType::scalar_type,
00239                                     typename MatrixType::local_ordinal_type,
00240                                     typename MatrixType::global_ordinal_type,
00241                                     typename MatrixType::node_type>& Y,
00242                 Teuchos::ETransp mode,
00243                  Scalar alpha,
00244                  Scalar beta) const
00245 {
00246   TEST_FOR_EXCEPTION(isComputed() == false, std::runtime_error,
00247      "Ifpack2::Relaxation::apply ERROR: isComputed() must be true prior to calling apply.");
00248 
00249   TEST_FOR_EXCEPTION(X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
00250      "Ifpack2::Relaxation::apply ERROR: X.getNumVectors() != Y.getNumVectors().");
00251 
00252   Time_->start(true);
00253 
00254   // AztecOO gives X and Y pointing to the same memory location.
00255   // In that case we need to create an auxiliary vector, Xcopy
00256   Teuchos::RCP< const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > Xcopy;
00257   if (&(X.get2dView()[0][0]) == &(Y.get2dView()[0][0]))
00258     Xcopy = Teuchos::rcp( new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(X) );
00259   else
00260     Xcopy = Teuchos::rcp( &X, false );
00261 
00262   if (ZeroStartingSolution_)
00263     Y.putScalar(0.0);
00264 
00265   // Flops are updated in each of the following.
00266   switch (PrecType_) {
00267   case Ifpack2::JACOBI:
00268     ApplyInverseJacobi(*Xcopy,Y);
00269     break;
00270   case Ifpack2::GS:
00271     ApplyInverseGS(*Xcopy,Y);
00272     break;
00273   case Ifpack2::SGS:
00274     ApplyInverseSGS(*Xcopy,Y);
00275     break;
00276   default:
00277     throw std::runtime_error("Ifpack2::Relaxation::apply internal logic error.");
00278   }
00279 
00280   ++NumApply_;
00281   Time_->stop();
00282   ApplyTime_ += Time_->totalElapsedTime();
00283 }
00284 
00285 //==========================================================================
00286 template<class MatrixType>
00287 void Relaxation<MatrixType>::applyMat(
00288           const Tpetra::MultiVector<typename MatrixType::scalar_type,
00289                                     typename MatrixType::local_ordinal_type,
00290                                     typename MatrixType::global_ordinal_type,
00291                                     typename MatrixType::node_type>& X,
00292                 Tpetra::MultiVector<typename MatrixType::scalar_type,
00293                                     typename MatrixType::local_ordinal_type,
00294                                     typename MatrixType::global_ordinal_type,
00295                                     typename MatrixType::node_type>& Y,
00296              Teuchos::ETransp mode) const
00297 {
00298   TEST_FOR_EXCEPTION(isComputed() == false, std::runtime_error,
00299      "Ifpack2::Relaxation::applyMat() ERROR: isComputed() must be true prior to calling applyMat().");
00300   TEST_FOR_EXCEPTION(X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
00301      "Ifpack2::Relaxation::applyMat() ERROR: X.getNumVectors() != Y.getNumVectors().");
00302   A_->apply(X, Y, mode);
00303 }
00304 
00305 //==========================================================================
00306 template<class MatrixType>
00307 void Relaxation<MatrixType>::initialize() {
00308   IsInitialized_ = false;
00309 
00310   TEST_FOR_EXCEPTION(A_ == Teuchos::null, std::runtime_error,
00311     "Ifpack2::Relaxation::Initialize ERROR, Matrix is NULL");
00312 
00313 //  size_t globalrows = A_->getGlobalNumRows();
00314 //  size_t globalcols = A_->getGlobalNumCols();
00315 //  TEST_FOR_EXCEPTION(globalrows != globalcols, std::runtime_error,
00316 //   "Ifpack2::Relaxation::Initialize ERROR, only square matrices are supported");
00317 
00318   NumMyRows_ = A_->getNodeNumRows();
00319   NumGlobalRows_ = A_->getGlobalNumRows();
00320   NumGlobalNonzeros_ = A_->getGlobalNumEntries();
00321 
00322   if (Comm_->getSize() != 1)
00323     IsParallel_ = true;
00324   else
00325     IsParallel_ = false;
00326 
00327   ++NumInitialize_;
00328   Time_->stop();
00329   InitializeTime_ += Time_->totalElapsedTime();
00330   IsInitialized_ = true;
00331 }
00332 
00333 //==========================================================================
00334 template<class MatrixType>
00335 void Relaxation<MatrixType>::compute()
00336 {
00337   if (!isInitialized()) {
00338     initialize();
00339   }
00340 
00341   Time_->start(true);
00342 
00343   // reset values
00344   IsComputed_ = false;
00345   Condest_ = -1.0;
00346 
00347   TEST_FOR_EXCEPTION(NumSweeps_ < 0, std::runtime_error,
00348     "Ifpack2::Relaxation::compute, NumSweeps_ must be >= 0");
00349   
00350   Diagonal_ = Teuchos::rcp( new Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(A_->getRowMap()) );
00351 
00352   TEST_FOR_EXCEPTION(Diagonal_ == Teuchos::null, std::runtime_error,
00353     "Ifpack2::Relaxation::compute, failed to create Diagonal_");
00354 
00355   A_->getLocalDiagCopy(*Diagonal_);
00356 
00357   // check diagonal elements, store the inverses, and verify that
00358   // no zeros are around. If an element is zero, then by default
00359   // its inverse is zero as well (that is, the row is ignored).
00360   Teuchos::ArrayRCP<Scalar> DiagView = Diagonal_->get1dViewNonConst();
00361   for (size_t i = 0 ; i < NumMyRows_ ; ++i) {
00362     Scalar& diag = DiagView[i];
00363     if (Teuchos::ScalarTraits<Scalar>::magnitude(diag) < Teuchos::ScalarTraits<Scalar>::magnitude(MinDiagonalValue_))
00364       diag = MinDiagonalValue_;
00365     if (diag != Teuchos::ScalarTraits<Scalar>::zero())
00366       diag = Teuchos::ScalarTraits<Scalar>::one() / diag;
00367   }
00368   ComputeFlops_ += NumMyRows_;
00369 
00370   //Marzio's comment:
00371   // We need to import data from external processors. Here I create a
00372   // Tpetra::Import object because I cannot assume that A_ has one.
00373   // This is a bit of waste of resources (but the code is more robust).
00374   // Note that I am doing some strange stuff to set the components of Y
00375   // from Y2 (to save some time).
00376   //
00377   if (IsParallel_ && ((PrecType_ == Ifpack2::GS) || (PrecType_ == Ifpack2::SGS))) {
00378     Importer_ = Teuchos::rcp( new Tpetra::Import<LocalOrdinal,GlobalOrdinal,Node>(A_->getColMap(),
00379                                   A_->getRowMap()) );
00380     TEST_FOR_EXCEPTION(Importer_ == Teuchos::null, std::runtime_error,
00381       "Ifpack2::Relaxation::compute ERROR failed to create Importer_");
00382   }
00383 
00384   ++NumCompute_;
00385   Time_->stop();
00386   ComputeTime_ += Time_->totalElapsedTime();
00387   IsComputed_ = true;
00388 }
00389 
00390 //==========================================================================
00391 template<class MatrixType>
00392 void Relaxation<MatrixType>::ApplyInverseJacobi(
00393         const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, 
00394               Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
00395 {
00396   int NumVectors = X.getNumVectors();
00397   Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> A_times_Y( Y.getMap(),NumVectors );
00398 
00399   for (int j = 0; j < NumSweeps_ ; j++) {
00400     applyMat(Y,A_times_Y);
00401     A_times_Y.update(1.0,X,-1.0);
00402     Y.elementWiseMultiply(DampingFactor_, *Diagonal_, A_times_Y, 1.0);
00403   }
00404 
00405   // Flops:
00406   // - matrix vector              (2 * NumGlobalNonzeros_)
00407   // - update                     (2 * NumGlobalRows_)
00408   // - Multiply:
00409   //   - DampingFactor            (NumGlobalRows_)
00410   //   - Diagonal                 (NumGlobalRows_)
00411   //   - A + B                    (NumGlobalRows_)
00412   //   - 1.0                      (NumGlobalRows_)
00413   ApplyFlops_ += NumVectors * (6 * NumGlobalRows_ + 2 * NumGlobalNonzeros_);
00414 }
00415 
00416 //==========================================================================
00417 template<class MatrixType>
00418 void Relaxation<MatrixType>::ApplyInverseGS(
00419         const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, 
00420               Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
00421 {
00422   const MatrixType* CrsMatrix = dynamic_cast<const MatrixType*>(&*A_);
00423   // try to pick the best option; performances may be improved
00424   // if several sweeps are used.
00425   if (CrsMatrix != 0)
00426   {
00427     ApplyInverseGS_CrsMatrix(*CrsMatrix, X, Y);
00428   }
00429   else {
00430     ApplyInverseGS_RowMatrix(X, Y);
00431   }
00432 }
00433 
00434 //==========================================================================
00435 template<class MatrixType>
00436 void Relaxation<MatrixType>::ApplyInverseGS_RowMatrix(
00437         const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, 
00438               Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
00439 {
00440   size_t NumVectors = X.getNumVectors();
00441 
00442   size_t maxLength = A_->getNodeMaxNumRowEntries();
00443   Teuchos::Array<LocalOrdinal> Indices(maxLength);
00444   Teuchos::Array<Scalar> Values(maxLength);
00445 
00446   Teuchos::RCP< Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > Y2;
00447   if (IsParallel_)
00448     Y2 = Teuchos::rcp( new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Importer_->getTargetMap(), NumVectors) );
00449   else
00450     Y2 = Teuchos::rcp( &Y, false );
00451 
00452   // extract views (for nicer and faster code)
00453   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y_ptr = Y.get2dViewNonConst();
00454   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y2_ptr = Y2->get2dViewNonConst();
00455   Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > x_ptr =  X.get2dView();
00456   Teuchos::ArrayRCP<const Scalar> d_ptr = Diagonal_->get1dView();
00457  
00458   for (int j = 0; j < NumSweeps_ ; j++) {
00459 
00460     // data exchange is here, once per sweep
00461     if (IsParallel_)
00462       Y2->doImport(Y,*Importer_,Tpetra::INSERT);
00463 
00464     if(!DoBackwardGS_){      
00465       /* Forward Mode */
00466       for (size_t i = 0 ; i < NumMyRows_ ; ++i) {
00467         
00468         size_t NumEntries;
00469         A_->getLocalRowCopy(i, Indices(), Values(), NumEntries);
00470         
00471         for (size_t m = 0 ; m < NumVectors ; ++m) {
00472 
00473           Scalar dtemp = 0.0;
00474           for (size_t k = 0 ; k < NumEntries ; ++k) {
00475             LocalOrdinal col = Indices[k];
00476             dtemp += Values[k] * y2_ptr[m][col];
00477           }
00478           
00479           y2_ptr[m][i] += DampingFactor_ * d_ptr[i] * (x_ptr[m][i] - dtemp);
00480         }
00481       }
00482     }
00483     else {
00484       /* Backward Mode */
00485       for (int i = NumMyRows_  - 1 ; i > -1 ; --i) {
00486         size_t NumEntries;
00487         A_->getLocalRowCopy(i, Indices(), Values(), NumEntries);
00488 
00489         for (size_t m = 0 ; m < NumVectors ; ++m) {
00490           
00491           Scalar dtemp = 0.0;
00492           for (size_t k = 0 ; k < NumEntries ; ++k) {
00493             LocalOrdinal col = Indices[k];
00494             dtemp += Values[k] * y2_ptr[m][col];
00495           }
00496 
00497           y2_ptr[m][i] += DampingFactor_ * d_ptr[i] * (x_ptr[m][i] - dtemp);
00498         }
00499       }
00500     }
00501 
00502     // using Export() sounded quite expensive   
00503     if (IsParallel_) {
00504       for (size_t m = 0 ; m < NumVectors ; ++m) 
00505         for (size_t i = 0 ; i < NumMyRows_ ; ++i)
00506           y_ptr[m][i] = y2_ptr[m][i];
00507     }
00508   }
00509 
00510   ApplyFlops_ += NumVectors * (4 * NumGlobalRows_ + 2 * NumGlobalNonzeros_);
00511 }
00512 
00513 //==========================================================================
00514 template<class MatrixType>
00515 void Relaxation<MatrixType>::ApplyInverseGS_CrsMatrix(
00516         const MatrixType& A,
00517         const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X,
00518               Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
00519 {
00520   size_t NumVectors = X.getNumVectors();
00521 
00522   Teuchos::ArrayView<const LocalOrdinal> Indices;
00523   Teuchos::ArrayView<const Scalar> Values;
00524 
00525   Teuchos::RCP< Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > Y2;
00526   if (IsParallel_) {
00527     Y2 = Teuchos::rcp( new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Importer_->getTargetMap(), NumVectors) );
00528   }
00529   else
00530     Y2 = Teuchos::rcp( &Y, false );
00531 
00532   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y_ptr = Y.get2dViewNonConst();
00533   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y2_ptr = Y2->get2dViewNonConst();
00534   Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > x_ptr =  X.get2dView();
00535   Teuchos::ArrayRCP<const Scalar> d_ptr = Diagonal_->get1dView();
00536   
00537   for (int iter = 0 ; iter < NumSweeps_ ; ++iter) {
00538     
00539     // only one data exchange per sweep
00540     if (IsParallel_)
00541       Y2->doImport(Y,*Importer_,Tpetra::INSERT);
00542 
00543     if(!DoBackwardGS_){  
00544       /* Forward Mode */
00545       for (size_t i = 0 ; i < NumMyRows_ ; ++i) {
00546 
00547         LocalOrdinal col;
00548         Scalar diag = d_ptr[i];
00549         
00550         A.getLocalRowView(i, Indices, Values);
00551         size_t NumEntries = Indices.size();
00552         
00553         for (size_t m = 0 ; m < NumVectors ; ++m) {
00554           
00555           Scalar dtemp = 0.0;
00556           
00557           for (size_t k = 0; k < NumEntries; ++k) {
00558             col = Indices[k];
00559             dtemp += Values[k] * y2_ptr[m][col];
00560           }
00561           
00562           y2_ptr[m][i] += DampingFactor_ * (x_ptr[m][i] - dtemp) * diag;
00563         }
00564       }
00565     }
00566     else {
00567       /* Backward Mode */
00568       for (int i = NumMyRows_  - 1 ; i > -1 ; --i) {
00569 
00570         LocalOrdinal col;
00571         Scalar diag = d_ptr[i];
00572         
00573         A.getLocalRowView(i, Indices, Values);
00574         size_t NumEntries = Indices.size();
00575         
00576         for (size_t m = 0 ; m < NumVectors ; ++m) {
00577           
00578           Scalar dtemp = 0.0;
00579           for (size_t k = 0; k < NumEntries; ++k) {
00580             col = Indices[k];
00581             dtemp += Values[k] * y2_ptr[m][col];
00582           }
00583           
00584           y2_ptr[m][i] += DampingFactor_ * (x_ptr[m][i] - dtemp) * diag;
00585           
00586         }
00587       }
00588     }
00589     
00590     if (IsParallel_) {
00591       for (size_t m = 0 ; m < NumVectors ; ++m) 
00592         for (size_t i = 0 ; i < NumMyRows_ ; ++i)
00593           y_ptr[m][i] = y2_ptr[m][i];
00594     }
00595   }
00596 
00597   ApplyFlops_ += NumVectors * (8 * NumGlobalRows_ + 4 * NumGlobalNonzeros_);
00598 }
00599 
00600 //==========================================================================
00601 template<class MatrixType>
00602 void Relaxation<MatrixType>::ApplyInverseSGS(
00603         const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, 
00604               Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
00605 {
00606   const MatrixType* CrsMatrix = dynamic_cast<const MatrixType*>(&*A_);
00607   // try to pick the best option; performance may be improved
00608   // if several sweeps are used.
00609   if (CrsMatrix != 0)
00610   {
00611     ApplyInverseSGS_CrsMatrix(*CrsMatrix, X, Y);
00612   }
00613   else
00614     ApplyInverseSGS_RowMatrix(X, Y);
00615 }
00616 
00617 //==========================================================================
00618 template<class MatrixType>
00619 void Relaxation<MatrixType>::ApplyInverseSGS_RowMatrix(
00620         const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, 
00621               Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
00622 {
00623   size_t NumVectors = X.getNumVectors();
00624   size_t maxLength = A_->getNodeMaxNumRowEntries();
00625   Teuchos::Array<LocalOrdinal> Indices(maxLength);
00626   Teuchos::Array<Scalar> Values(maxLength);
00627 
00628   Teuchos::RCP< Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > Y2;
00629   if (IsParallel_) {
00630     Y2 = Teuchos::rcp( new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Importer_->getTargetMap(), NumVectors) );
00631   }
00632   else
00633     Y2 = Teuchos::rcp( &Y, false );
00634 
00635   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y_ptr = Y.get2dViewNonConst();
00636   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y2_ptr = Y2->get2dViewNonConst();
00637   Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > x_ptr =  X.get2dView();
00638   Teuchos::ArrayRCP<const Scalar> d_ptr = Diagonal_->get1dView();
00639   
00640   for (int iter = 0 ; iter < NumSweeps_ ; ++iter) {
00641     
00642     // only one data exchange per sweep
00643     if (IsParallel_)
00644       Y2->doImport(Y,*Importer_,Tpetra::INSERT);
00645 
00646     for (size_t i = 0 ; i < NumMyRows_ ; ++i) {
00647 
00648       size_t NumEntries;
00649       Scalar diag = d_ptr[i];
00650 
00651       A_->getLocalRowCopy(i, Indices(), Values(), NumEntries);
00652 
00653       for (size_t m = 0 ; m < NumVectors ; ++m) {
00654 
00655         Scalar dtemp = 0.0;
00656 
00657         for (size_t k = 0 ; k < NumEntries ; ++k) {
00658           LocalOrdinal col = Indices[k];
00659           dtemp += Values[k] * y2_ptr[m][col];
00660         }
00661 
00662         y2_ptr[m][i] += DampingFactor_ * (x_ptr[m][i] - dtemp) * diag;
00663       }
00664     }
00665 
00666     for (int i = NumMyRows_  - 1 ; i > -1 ; --i) {
00667 
00668       size_t NumEntries;
00669       Scalar diag = d_ptr[i];
00670 
00671       A_->getLocalRowCopy(i, Indices(), Values(), NumEntries);
00672 
00673       for (size_t m = 0 ; m < NumVectors ; ++m) {
00674 
00675         Scalar dtemp = Teuchos::ScalarTraits<Scalar>::zero();
00676         for (size_t k = 0 ; k < NumEntries ; ++k) {
00677           LocalOrdinal col = Indices[k];
00678           dtemp += Values[k] * y2_ptr[m][col];
00679         }
00680 
00681         y2_ptr[m][i] += DampingFactor_ * (x_ptr[m][i] - dtemp) * diag;
00682       }
00683     }
00684 
00685     if (IsParallel_) {
00686       for (size_t m = 0 ; m < NumVectors ; ++m) 
00687         for (size_t i = 0 ; i < NumMyRows_ ; ++i)
00688           y_ptr[m][i] = y2_ptr[m][i];
00689     }
00690   }
00691 
00692   ApplyFlops_ += NumVectors * (8 * NumGlobalRows_ + 4 * NumGlobalNonzeros_);
00693 }
00694 
00695 //==========================================================================
00696 template<class MatrixType>
00697 void Relaxation<MatrixType>::ApplyInverseSGS_CrsMatrix(
00698         const MatrixType& A,
00699         const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X, 
00700               Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y) const
00701 {
00702   size_t NumVectors = X.getNumVectors();
00703 
00704   Teuchos::ArrayView<const LocalOrdinal> Indices;
00705   Teuchos::ArrayView<const Scalar> Values;
00706 
00707   Teuchos::RCP< Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > Y2;
00708   if (IsParallel_) {
00709     Y2 = Teuchos::rcp( new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Importer_->getTargetMap(), NumVectors) );
00710   }
00711   else
00712     Y2 = Teuchos::rcp( &Y, false );
00713 
00714   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y_ptr = Y.get2dViewNonConst();
00715   Teuchos::ArrayRCP<Teuchos::ArrayRCP<Scalar> > y2_ptr = Y2->get2dViewNonConst();
00716   Teuchos::ArrayRCP<Teuchos::ArrayRCP<const Scalar> > x_ptr =  X.get2dView();
00717   Teuchos::ArrayRCP<const Scalar> d_ptr = Diagonal_->get1dView();
00718   
00719   for (int iter = 0 ; iter < NumSweeps_ ; ++iter) {
00720     
00721     // only one data exchange per sweep
00722     if (IsParallel_)
00723       Y2->doImport(Y,*Importer_,Tpetra::INSERT);
00724 
00725     for (size_t i = 0 ; i < NumMyRows_ ; ++i) {
00726 
00727       Scalar diag = d_ptr[i];
00728 
00729       A.getLocalRowView(i, Indices, Values);
00730       size_t NumEntries = Indices.size();
00731 
00732       for (size_t m = 0 ; m < NumVectors ; ++m) {
00733 
00734         Scalar dtemp = Teuchos::ScalarTraits<Scalar>::zero();
00735 
00736         for (size_t k = 0; k < NumEntries; ++k) {
00737 
00738           LocalOrdinal col = Indices[k];
00739           dtemp += Values[k] * y2_ptr[m][col];
00740         }
00741 
00742         y2_ptr[m][i] += DampingFactor_ * (x_ptr[m][i] - dtemp) * diag;
00743       }
00744     }
00745 
00746     for (int i = NumMyRows_  - 1 ; i > -1 ; --i) {
00747 
00748       Scalar diag = d_ptr[i];
00749 
00750       A.getLocalRowView(i, Indices, Values);
00751       size_t NumEntries = Indices.size();
00752 
00753       for (size_t m = 0 ; m < NumVectors ; ++m) {
00754 
00755         Scalar dtemp = Teuchos::ScalarTraits<Scalar>::zero();
00756         for (size_t k = 0; k < NumEntries; ++k) {
00757 
00758           LocalOrdinal col = Indices[k];
00759           dtemp += Values[k] * y2_ptr[m][col];
00760         }
00761 
00762         y2_ptr[m][i] += DampingFactor_ * (x_ptr[m][i] - dtemp) * diag;
00763 
00764       }
00765     }
00766 
00767     if (IsParallel_) {
00768       for (size_t m = 0 ; m < NumVectors ; ++m) 
00769         for (size_t i = 0 ; i < NumMyRows_ ; ++i)
00770           y_ptr[m][i] = y2_ptr[m][i];
00771     }
00772   }
00773 
00774   ApplyFlops_ += NumVectors * (8 * NumGlobalRows_ + 4 * NumGlobalNonzeros_);
00775 }
00776 
00777 //==========================================================================
00778 template<class MatrixType>
00779 std::string Relaxation<MatrixType>::description() const {
00780   std::ostringstream oss;
00781   oss << Teuchos::Describable::description();
00782   if (isInitialized()) {
00783     if (isComputed()) {
00784       oss << "{status = initialized, computed";
00785     }
00786     else {
00787       oss << "{status = initialized, not computed";
00788     }
00789   }
00790   else {
00791     oss << "{status = not initialized, not computed";
00792   }
00793   //
00794   if (PrecType_ == Ifpack2::JACOBI)   oss << "Type = Jacobi, " << std::endl;
00795   else if (PrecType_ == Ifpack2::GS)  oss << "Type = Gauss-Seidel, " << std::endl;
00796   else if (PrecType_ == Ifpack2::SGS) oss << "Type = Sym. Gauss-Seidel, " << std::endl;
00797   //
00798   oss << ", global rows = " << A_->getGlobalNumRows()
00799       << ", global cols = " << A_->getGlobalNumCols()
00800       << "}";
00801   return oss.str();
00802 }
00803 
00804 //==========================================================================
00805 template<class MatrixType>
00806 void Relaxation<MatrixType>::describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const {
00807   using std::endl;
00808   using std::setw;
00809   using Teuchos::VERB_DEFAULT;
00810   using Teuchos::VERB_NONE;
00811   using Teuchos::VERB_LOW;
00812   using Teuchos::VERB_MEDIUM;
00813   using Teuchos::VERB_HIGH;
00814   using Teuchos::VERB_EXTREME;
00815   Teuchos::EVerbosityLevel vl = verbLevel;
00816   if (vl == VERB_DEFAULT) vl = VERB_LOW;
00817   const int myImageID = Comm_->getRank();
00818   Teuchos::OSTab tab(out);
00819 
00820   Scalar MinVal = Teuchos::ScalarTraits<Scalar>::zero();
00821   Scalar MaxVal = Teuchos::ScalarTraits<Scalar>::zero();
00822 
00823   if (IsComputed_) {
00824     Teuchos::ArrayRCP<Scalar> DiagView = Diagonal_->get1dViewNonConst();
00825     Scalar myMinVal = DiagView[0];
00826     Scalar myMaxVal = DiagView[0];
00827     for(typename Teuchos::ArrayRCP<Scalar>::size_type i=0; i<DiagView.size(); ++i) {
00828       if (Teuchos::ScalarTraits<Scalar>::magnitude(myMinVal) > Teuchos::ScalarTraits<Scalar>::magnitude(DiagView[i])) myMinVal = DiagView[i];
00829       if (Teuchos::ScalarTraits<Scalar>::magnitude(myMaxVal) < Teuchos::ScalarTraits<Scalar>::magnitude(DiagView[i])) myMaxVal = DiagView[i];
00830     }
00831 
00832     Teuchos::reduceAll(*Comm_, Teuchos::REDUCE_MIN, 1, &myMinVal, &MinVal);
00833     Teuchos::reduceAll(*Comm_, Teuchos::REDUCE_MAX, 1, &myMaxVal, &MaxVal);
00834   }
00835 
00836   //    none: print nothing
00837   //     low: print O(1) info from node 0
00838   //  medium: 
00839   //    high: 
00840   // extreme: 
00841   if (vl != VERB_NONE && myImageID == 0) {
00842     out << this->description() << endl;
00843     out << endl;
00844     out << "===============================================================================" << endl;
00845     out << "Sweeps         = " << NumSweeps_ << endl;
00846     out << "damping factor = " << DampingFactor_ << endl;
00847     if (PrecType_ == Ifpack2::GS && DoBackwardGS_) {
00848       out << "Using backward mode (GS only)" << endl;
00849     }
00850     if   (ZeroStartingSolution_) { out << "Using zero starting solution" << endl; }
00851     else                         { out << "Using input starting solution" << endl; }
00852     if   (Condest_ == -1.0) { out << "Condition number estimate       = N/A" << endl; }
00853     else                    { out << "Condition number estimate       = " << Condest_ << endl; }
00854     if (IsComputed_) {
00855       out << "Minimum value on stored diagonal = " << MinVal << endl;
00856       out << "Maximum value on stored diagonal = " << MaxVal << endl;
00857     }
00858     out << endl;
00859     out << "Phase           # calls    Total Time (s)     Total MFlops      MFlops/s       " << endl;
00860     out << "------------    -------    ---------------    ---------------   ---------------" << endl;
00861     out << setw(12) << "initialize()" << setw(5) << getNumInitialize() << "    " << setw(15) << getInitializeTime() << endl;
00862     out << setw(12) << "compute()" << setw(5) << getNumCompute()    << "    " << setw(15) << getComputeTime() << "    " 
00863         << setw(15) << getComputeFlops() << "    " 
00864         << setw(15) << (getComputeTime() != 0.0 ? getComputeFlops() / getComputeTime() * 1.0e-6 : 0.0) << endl;
00865     out << setw(12) << "apply()" << setw(5) << getNumApply()    << "    " << setw(15) << getApplyTime() << "    " 
00866         << setw(15) << getApplyFlops() << "    " 
00867         << setw(15) << (getApplyTime() != 0.0 ? getApplyFlops() / getApplyTime() * 1.0e-6 : 0.0) << endl;
00868     out << "===============================================================================" << endl;
00869     out << endl;
00870   }
00871 }
00872 
00873 }//namespace Ifpack2
00874 
00875 #endif // IFPACK2_RELAXATION_DEF_HPP
00876 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends