|
Tifpack Templated Preconditioning Package Version 1.0
|
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
1.7.4