|
Ifpack2 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 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 //@HEADER 00041 */ 00042 00043 #ifndef IFPACK2_HIPTMAIR_DEF_HPP 00044 #define IFPACK2_HIPTMAIR_DEF_HPP 00045 00046 #include "Ifpack2_Hiptmair_decl.hpp" 00047 #include "Ifpack2_Details_OneLevelFactory_decl.hpp" 00048 #include "Ifpack2_Details_OneLevelFactory_def.hpp" 00049 00050 namespace Ifpack2 { 00051 00052 template <class MatrixType> 00053 Hiptmair<MatrixType>:: 00054 Hiptmair (const Teuchos::RCP<const row_matrix_type>& A, 00055 const Teuchos::RCP<const row_matrix_type>& PtAP, 00056 const Teuchos::RCP<const row_matrix_type>& P) : 00057 A_ (A), 00058 PtAP_ (PtAP), 00059 P_ (P), 00060 // Default values 00061 precType1_ ("CHEBYSHEV"), 00062 precType2_ ("CHEBYSHEV"), 00063 preOrPost_ ("both"), 00064 ZeroStartingSolution_ (true), 00065 // General 00066 Condest_ (-STM::one ()), 00067 IsInitialized_ (false), 00068 IsComputed_ (false), 00069 NumInitialize_ (0), 00070 NumCompute_ (0), 00071 NumApply_ (0), 00072 InitializeTime_ (0.0), 00073 ComputeTime_ (0.0), 00074 ApplyTime_ (0.0) 00075 {} 00076 00077 00078 template <class MatrixType> 00079 Hiptmair<MatrixType>::~Hiptmair() {} 00080 00081 template <class MatrixType> 00082 void Hiptmair<MatrixType>::setParameters (const Teuchos::ParameterList& plist) 00083 { 00084 using Teuchos::as; 00085 using Teuchos::ParameterList; 00086 using Teuchos::Exceptions::InvalidParameterName; 00087 using Teuchos::Exceptions::InvalidParameterType; 00088 00089 ParameterList params = plist; 00090 00091 // Get the current parameters' values. We don't assign to the 00092 // instance data directly until we've gotten all the parameters. 00093 // This ensures "transactional" semantics, so that if attempting to 00094 // get some parameter throws an exception, the class' state doesn't 00095 // change. 00096 std::string precType1 = precType1_; 00097 std::string precType2 = precType2_; 00098 std::string preOrPost = preOrPost_; 00099 Teuchos::ParameterList precList1 = precList1_; 00100 Teuchos::ParameterList precList2 = precList2_; 00101 bool zeroStartingSolution = ZeroStartingSolution_; 00102 00103 precType1 = params.get("hiptmair: smoother type 1", precType1); 00104 precType2 = params.get("hiptmair: smoother type 2", precType2); 00105 precList1 = params.get("hiptmair: smoother list 1", precList1); 00106 precList2 = params.get("hiptmair: smoother list 2", precList2); 00107 preOrPost = params.get("hiptmair: pre or post", preOrPost); 00108 zeroStartingSolution = params.get("hiptmair: zero starting solution", 00109 zeroStartingSolution); 00110 00111 // "Commit" the new values to the instance data. 00112 precType1_ = precType1; 00113 precType2_ = precType2; 00114 precList1_ = precList1; 00115 precList2_ = precList2; 00116 preOrPost_ = preOrPost; 00117 ZeroStartingSolution_ = zeroStartingSolution; 00118 } 00119 00120 00121 template <class MatrixType> 00122 Teuchos::RCP<const Teuchos::Comm<int> > 00123 Hiptmair<MatrixType>::getComm () const { 00124 TEUCHOS_TEST_FOR_EXCEPTION( 00125 A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getComm: " 00126 "The input matrix A is null. Please call setMatrix() with a nonnull " 00127 "input matrix before calling this method."); 00128 return A_->getComm (); 00129 } 00130 00131 00132 template <class MatrixType> 00133 Teuchos::RCP<const Tpetra::RowMatrix<typename MatrixType::scalar_type,typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> > 00134 Hiptmair<MatrixType>::getMatrix () const { 00135 return A_; 00136 } 00137 00138 00139 template <class MatrixType> 00140 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> > 00141 Hiptmair<MatrixType>::getDomainMap () const 00142 { 00143 TEUCHOS_TEST_FOR_EXCEPTION( 00144 A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getDomainMap: " 00145 "The input matrix A is null. Please call setMatrix() with a nonnull " 00146 "input matrix before calling this method."); 00147 return A_->getDomainMap (); 00148 } 00149 00150 00151 template <class MatrixType> 00152 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type,typename MatrixType::global_ordinal_type,typename MatrixType::node_type> > 00153 Hiptmair<MatrixType>::getRangeMap () const 00154 { 00155 TEUCHOS_TEST_FOR_EXCEPTION( 00156 A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::getRangeMap: " 00157 "The input matrix A is null. Please call setMatrix() with a nonnull " 00158 "input matrix before calling this method."); 00159 return A_->getRangeMap (); 00160 } 00161 00162 00163 template <class MatrixType> 00164 bool Hiptmair<MatrixType>::hasTransposeApply () const { 00165 // FIXME (mfh 17 Jan 2014) apply() does not currently work with mode 00166 // != NO_TRANS, so it's correct to return false here. 00167 return false; 00168 } 00169 00170 00171 template <class MatrixType> 00172 int Hiptmair<MatrixType>::getNumInitialize () const { 00173 return NumInitialize_; 00174 } 00175 00176 00177 template <class MatrixType> 00178 int Hiptmair<MatrixType>::getNumCompute () const { 00179 return NumCompute_; 00180 } 00181 00182 00183 template <class MatrixType> 00184 int Hiptmair<MatrixType>::getNumApply () const { 00185 return NumApply_; 00186 } 00187 00188 00189 template <class MatrixType> 00190 double Hiptmair<MatrixType>::getInitializeTime () const { 00191 return InitializeTime_; 00192 } 00193 00194 00195 template <class MatrixType> 00196 double Hiptmair<MatrixType>::getComputeTime () const { 00197 return ComputeTime_; 00198 } 00199 00200 00201 template <class MatrixType> 00202 double Hiptmair<MatrixType>::getApplyTime () const { 00203 return ApplyTime_; 00204 } 00205 00206 00207 template <class MatrixType> 00208 typename Hiptmair<MatrixType>::magnitude_type 00209 Hiptmair<MatrixType>:: 00210 computeCondEst (CondestType CT, 00211 local_ordinal_type MaxIters, 00212 magnitude_type Tol, 00213 const Teuchos::Ptr<const row_matrix_type>& matrix) 00214 { 00215 if (! isComputed ()) { // cannot compute right now 00216 return -STM::one (); 00217 } 00218 // NOTE: this is computing the *local* condest 00219 if (Condest_ == -STM::one ()) { 00220 Condest_ = Ifpack2::Condest (*this, CT, MaxIters, Tol, matrix); 00221 } 00222 return Condest_; 00223 } 00224 00225 00226 template <class MatrixType> 00227 void Hiptmair<MatrixType>::initialize () 00228 { 00229 using Teuchos::ParameterList; 00230 using Teuchos::RCP; 00231 using Teuchos::rcp; 00232 00233 TEUCHOS_TEST_FOR_EXCEPTION( 00234 A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::initialize: " 00235 "The input matrix A is null. Please call setMatrix() with a nonnull " 00236 "input matrix before calling this method."); 00237 00238 // clear any previous allocation 00239 IsInitialized_ = false; 00240 IsComputed_ = false; 00241 00242 Teuchos::Time timer ("initialize"); 00243 { // The body of code to time 00244 Teuchos::TimeMonitor timeMon (timer); 00245 00246 Details::OneLevelFactory<MatrixType> factory; 00247 00248 ifpack2_prec1_=factory.create(precType1_,A_); 00249 ifpack2_prec1_->initialize(); 00250 ifpack2_prec1_->setParameters(precList1_); 00251 00252 ifpack2_prec2_=factory.create(precType2_,PtAP_); 00253 ifpack2_prec2_->initialize(); 00254 ifpack2_prec2_->setParameters(precList2_); 00255 00256 } 00257 IsInitialized_ = true; 00258 ++NumInitialize_; 00259 InitializeTime_ += timer.totalElapsedTime (); 00260 } 00261 00262 00263 template <class MatrixType> 00264 void Hiptmair<MatrixType>::compute () 00265 { 00266 TEUCHOS_TEST_FOR_EXCEPTION( 00267 A_.is_null (), std::runtime_error, "Ifpack2::Hiptmair::compute: " 00268 "The input matrix A is null. Please call setMatrix() with a nonnull " 00269 "input matrix before calling this method."); 00270 00271 // Don't time the initialize(); that gets timed separately. 00272 if (! isInitialized ()) { 00273 initialize (); 00274 } 00275 00276 Teuchos::Time timer ("compute"); 00277 { // The body of code to time 00278 Teuchos::TimeMonitor timeMon (timer); 00279 ifpack2_prec1_->compute(); 00280 ifpack2_prec2_->compute(); 00281 } 00282 IsComputed_ = true; 00283 ++NumCompute_; 00284 ComputeTime_ += timer.totalElapsedTime (); 00285 } 00286 00287 00288 template <class MatrixType> 00289 void Hiptmair<MatrixType>:: 00290 apply (const Tpetra::MultiVector<typename MatrixType::scalar_type, 00291 typename MatrixType::local_ordinal_type, 00292 typename MatrixType::global_ordinal_type, 00293 typename MatrixType::node_type>& X, 00294 Tpetra::MultiVector<typename MatrixType::scalar_type, 00295 typename MatrixType::local_ordinal_type, 00296 typename MatrixType::global_ordinal_type, 00297 typename MatrixType::node_type>& Y, 00298 Teuchos::ETransp mode, 00299 typename MatrixType::scalar_type alpha, 00300 typename MatrixType::scalar_type beta) const 00301 { 00302 using Teuchos::RCP; 00303 using Teuchos::rcp; 00304 using Teuchos::rcpFromRef; 00305 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, 00306 global_ordinal_type, node_type> MV; 00307 TEUCHOS_TEST_FOR_EXCEPTION( 00308 ! isComputed (), std::runtime_error, 00309 "Ifpack2::Hiptmair::apply: You must call compute() before you may call apply()."); 00310 TEUCHOS_TEST_FOR_EXCEPTION( 00311 X.getNumVectors () != Y.getNumVectors (), std::invalid_argument, 00312 "Ifpack2::Hiptmair::apply: The MultiVector inputs X and Y do not have the " 00313 "same number of columns. X.getNumVectors() = " << X.getNumVectors () 00314 << " != Y.getNumVectors() = " << Y.getNumVectors () << "."); 00315 00316 // Catch unimplemented cases: alpha != 1, beta != 0, mode != NO_TRANS. 00317 TEUCHOS_TEST_FOR_EXCEPTION( 00318 alpha != STS::one (), std::logic_error, 00319 "Ifpack2::Hiptmair::apply: alpha != 1 has not been implemented."); 00320 TEUCHOS_TEST_FOR_EXCEPTION( 00321 beta != STS::zero (), std::logic_error, 00322 "Ifpack2::Hiptmair::apply: zero != 0 has not been implemented."); 00323 TEUCHOS_TEST_FOR_EXCEPTION( 00324 mode != Teuchos::NO_TRANS, std::logic_error, 00325 "Ifpack2::Hiptmair::apply: mode != Teuchos::NO_TRANS has not been implemented."); 00326 00327 Teuchos::Time timer ("apply"); 00328 { // The body of code to time 00329 Teuchos::TimeMonitor timeMon (timer); 00330 00331 // If X and Y are pointing to the same memory location, 00332 // we need to create an auxiliary vector, Xcopy 00333 RCP<const MV> Xcopy; 00334 if (X.getLocalMV ().getValues () == Y.getLocalMV ().getValues ()) { 00335 Xcopy = rcp (new MV (X, Teuchos::Copy)); 00336 } else { 00337 Xcopy = rcpFromRef (X); 00338 } 00339 00340 RCP<MV> Ycopy = rcpFromRef (Y); 00341 if (ZeroStartingSolution_) { 00342 Ycopy->putScalar (STS::zero ()); 00343 } 00344 00345 // apply Hiptmair Smoothing 00346 applyHiptmairSmoother (*Xcopy, *Ycopy); 00347 00348 } 00349 ++NumApply_; 00350 ApplyTime_ += timer.totalElapsedTime (); 00351 } 00352 00353 template <class MatrixType> 00354 void Hiptmair<MatrixType>:: 00355 applyHiptmairSmoother(const Tpetra::MultiVector<typename MatrixType::scalar_type, 00356 typename MatrixType::local_ordinal_type, 00357 typename MatrixType::global_ordinal_type, 00358 typename MatrixType::node_type>& X, 00359 Tpetra::MultiVector<typename MatrixType::scalar_type, 00360 typename MatrixType::local_ordinal_type, 00361 typename MatrixType::global_ordinal_type, 00362 typename MatrixType::node_type>& Y) const 00363 { 00364 using Teuchos::RCP; 00365 using Teuchos::rcp; 00366 using Teuchos::rcpFromRef; 00367 typedef Teuchos::ScalarTraits<scalar_type> STS; 00368 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, 00369 global_ordinal_type, node_type> MV; 00370 const scalar_type ZERO = STS::zero (); 00371 const scalar_type ONE = STS::one (); 00372 00373 RCP<MV> res1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ())); 00374 RCP<MV> vec1 = rcp (new MV (A_->getRowMap (), X.getNumVectors ())); 00375 RCP<MV> res2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ())); 00376 RCP<MV> vec2 = rcp (new MV (PtAP_->getRowMap (), X.getNumVectors ())); 00377 00378 if (preOrPost_ == "pre" || preOrPost_ == "both") { 00379 // apply initial relaxation to primary space 00380 A_->apply (Y, *res1); 00381 res1->update (ONE, X, -ONE); 00382 vec1->putScalar (ZERO); 00383 ifpack2_prec1_->apply (*res1, *vec1); 00384 Y.update (ONE, *vec1, ONE); 00385 } 00386 00387 // project to auxiliary space and smooth 00388 A_->apply (Y, *res1); 00389 res1->update (ONE, X, -ONE); 00390 P_->apply (*res1, *res2, Teuchos::TRANS); 00391 vec2->putScalar (ZERO); 00392 ifpack2_prec2_->apply (*res2, *vec2); 00393 P_->apply (*vec2, *vec1, Teuchos::NO_TRANS); 00394 Y.update (ONE,*vec1,ONE); 00395 00396 if (preOrPost_ == "post" || preOrPost_ == "both") { 00397 // smooth again on primary space 00398 A_->apply (Y, *res1); 00399 res1->update (ONE, X, -ONE); 00400 vec1->putScalar (ZERO); 00401 ifpack2_prec1_->apply (*res1, *vec1); 00402 Y.update (ONE, *vec1, ONE); 00403 } 00404 } 00405 00406 template <class MatrixType> 00407 std::string Hiptmair<MatrixType>::description () const 00408 { 00409 std::ostringstream os; 00410 00411 // Output is a valid YAML dictionary in flow style. If you don't 00412 // like everything on a single line, you should call describe() 00413 // instead. 00414 os << "\"Ifpack2::Hiptmair\": {"; 00415 if (this->getObjectLabel () != "") { 00416 os << "Label: \"" << this->getObjectLabel () << "\", "; 00417 } 00418 os << "Initialized: " << (isInitialized () ? "true" : "false") << ", " 00419 << "Computed: " << (isComputed () ? "true" : "false") << ", "; 00420 00421 if (A_.is_null ()) { 00422 os << "Matrix: null"; 00423 } 00424 else { 00425 os << "Matrix: not null" 00426 << ", Global matrix dimensions: [" 00427 << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]"; 00428 } 00429 00430 os << "}"; 00431 return os.str (); 00432 } 00433 00434 00435 template <class MatrixType> 00436 void Hiptmair<MatrixType>:: 00437 describe (Teuchos::FancyOStream &out, 00438 const Teuchos::EVerbosityLevel verbLevel) const 00439 { 00440 using std::endl; 00441 using std::setw; 00442 using Teuchos::VERB_DEFAULT; 00443 using Teuchos::VERB_NONE; 00444 using Teuchos::VERB_LOW; 00445 using Teuchos::VERB_MEDIUM; 00446 using Teuchos::VERB_HIGH; 00447 using Teuchos::VERB_EXTREME; 00448 00449 const Teuchos::EVerbosityLevel vl = 00450 (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel; 00451 00452 if (vl != VERB_NONE) { 00453 // describe() always starts with a tab by convention. 00454 Teuchos::OSTab tab0 (out); 00455 out << "\"Ifpack2::Hiptmair\":"; 00456 00457 Teuchos::OSTab tab1 (out); 00458 if (this->getObjectLabel () != "") { 00459 out << "Label: " << this->getObjectLabel () << endl; 00460 } 00461 out << "Initialized: " << (isInitialized () ? "true" : "false") << endl 00462 << "Computed: " << (isComputed () ? "true" : "false") << endl 00463 << "Global number of rows: " << A_->getGlobalNumRows () << endl 00464 << "Global number of columns: " << A_->getGlobalNumCols () << endl 00465 << "Matrix:"; 00466 if (A_.is_null ()) { 00467 out << " null" << endl; 00468 } else { 00469 A_->describe (out, vl); 00470 } 00471 } 00472 } 00473 00474 } // namespace Ifpack2 00475 00476 #define IFPACK2_HIPTMAIR_INSTANT(S,LO,GO,N) \ 00477 template class Ifpack2::Hiptmair< Tpetra::CrsMatrix<S, LO, GO, N> >; 00478 00479 #endif /* IFPACK2_HIPTMAIR_DEF_HPP */
1.7.6.1