|
Belos
Version of the Day
|
00001 //@HEADER 00002 // ************************************************************************ 00003 // 00004 // Belos: Block Linear Solvers Package 00005 // Copyright 2004 Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 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 #ifndef BELOS_BLOCK_CG_ITER_HPP 00043 #define BELOS_BLOCK_CG_ITER_HPP 00044 00049 #include "BelosConfigDefs.hpp" 00050 #include "BelosTypes.hpp" 00051 #include "BelosCGIteration.hpp" 00052 00053 #include "BelosLinearProblem.hpp" 00054 #include "BelosMatOrthoManager.hpp" 00055 #include "BelosOutputManager.hpp" 00056 #include "BelosStatusTest.hpp" 00057 #include "BelosOperatorTraits.hpp" 00058 #include "BelosMultiVecTraits.hpp" 00059 00060 #include "Teuchos_BLAS.hpp" 00061 #include "Teuchos_LAPACK.hpp" 00062 #include "Teuchos_SerialDenseMatrix.hpp" 00063 #include "Teuchos_SerialDenseVector.hpp" 00064 #include "Teuchos_ScalarTraits.hpp" 00065 #include "Teuchos_ParameterList.hpp" 00066 #include "Teuchos_TimeMonitor.hpp" 00067 00078 namespace Belos { 00079 00080 template<class ScalarType, class MV, class OP> 00081 class BlockCGIter : virtual public CGIteration<ScalarType,MV,OP> { 00082 00083 public: 00084 00085 // 00086 // Convenience typedefs 00087 // 00088 typedef MultiVecTraits<ScalarType,MV> MVT; 00089 typedef OperatorTraits<ScalarType,MV,OP> OPT; 00090 typedef Teuchos::ScalarTraits<ScalarType> SCT; 00091 typedef typename SCT::magnitudeType MagnitudeType; 00092 00094 00095 00101 BlockCGIter( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem, 00102 const Teuchos::RCP<OutputManager<ScalarType> > &printer, 00103 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester, 00104 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho, 00105 Teuchos::ParameterList ¶ms ); 00106 00108 virtual ~BlockCGIter() {}; 00110 00111 00113 00114 00127 void iterate(); 00128 00143 void initializeCG(CGIterationState<ScalarType,MV> newstate); 00144 00148 void initialize() 00149 { 00150 CGIterationState<ScalarType,MV> empty; 00151 initializeCG(empty); 00152 } 00153 00160 CGIterationState<ScalarType,MV> getState() const { 00161 CGIterationState<ScalarType,MV> state; 00162 state.R = R_; 00163 state.P = P_; 00164 state.AP = AP_; 00165 state.Z = Z_; 00166 return state; 00167 } 00168 00170 00171 00173 00174 00176 int getNumIters() const { return iter_; } 00177 00179 void resetNumIters( int iter=0 ) { iter_ = iter; } 00180 00183 Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> *norms ) const { return R_; } 00184 00186 00188 Teuchos::RCP<MV> getCurrentUpdate() const { return Teuchos::null; } 00189 00191 00193 00194 00196 const LinearProblem<ScalarType,MV,OP>& getProblem() const { return *lp_; } 00197 00199 int getBlockSize() const { return blockSize_; } 00200 00202 void setBlockSize(int blockSize); 00203 00205 bool isInitialized() { return initialized_; } 00206 00208 00209 private: 00210 00211 // 00212 // Internal methods 00213 // 00215 void setStateSize(); 00216 00217 // 00218 // Classes inputed through constructor that define the linear problem to be solved. 00219 // 00220 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > lp_; 00221 const Teuchos::RCP<OutputManager<ScalarType> > om_; 00222 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > stest_; 00223 const Teuchos::RCP<OrthoManager<ScalarType,MV> > ortho_; 00224 00225 // 00226 // Algorithmic parameters 00227 // 00228 // blockSize_ is the solver block size. 00229 int blockSize_; 00230 00231 // 00232 // Current solver state 00233 // 00234 // initialized_ specifies that the basis vectors have been initialized and the iterate() routine 00235 // is capable of running; _initialize is controlled by the initialize() member method 00236 // For the implications of the state of initialized_, please see documentation for initialize() 00237 bool initialized_; 00238 00239 // stateStorageInitialized_ specified that the state storage has be initialized. 00240 // This initialization may be postponed if the linear problem was generated without 00241 // the right-hand side or solution vectors. 00242 bool stateStorageInitialized_; 00243 00244 // Current subspace dimension, and number of iterations performed. 00245 int iter_; 00246 00247 // 00248 // State Storage 00249 // 00250 // Residual 00251 Teuchos::RCP<MV> R_; 00252 // 00253 // Preconditioned residual 00254 Teuchos::RCP<MV> Z_; 00255 // 00256 // Direction std::vector 00257 Teuchos::RCP<MV> P_; 00258 // 00259 // Operator applied to direction std::vector 00260 Teuchos::RCP<MV> AP_; 00261 00262 }; 00263 00265 // Constructor. 00266 template<class ScalarType, class MV, class OP> 00267 BlockCGIter<ScalarType,MV,OP>::BlockCGIter(const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem, 00268 const Teuchos::RCP<OutputManager<ScalarType> > &printer, 00269 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester, 00270 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho, 00271 Teuchos::ParameterList ¶ms ): 00272 lp_(problem), 00273 om_(printer), 00274 stest_(tester), 00275 ortho_(ortho), 00276 blockSize_(0), 00277 initialized_(false), 00278 stateStorageInitialized_(false), 00279 iter_(0) 00280 { 00281 // Set the block size and allocate data 00282 int bs = params.get("Block Size", 1); 00283 setBlockSize( bs ); 00284 } 00285 00287 // Setup the state storage. 00288 template <class ScalarType, class MV, class OP> 00289 void BlockCGIter<ScalarType,MV,OP>::setStateSize () 00290 { 00291 if (!stateStorageInitialized_) { 00292 00293 // Check if there is any multivector to clone from. 00294 Teuchos::RCP<const MV> lhsMV = lp_->getLHS(); 00295 Teuchos::RCP<const MV> rhsMV = lp_->getRHS(); 00296 if (lhsMV == Teuchos::null && rhsMV == Teuchos::null) { 00297 stateStorageInitialized_ = false; 00298 return; 00299 } 00300 else { 00301 00302 // Initialize the state storage 00303 // If the subspace has not be initialized before, generate it using the LHS or RHS from lp_. 00304 if (R_ == Teuchos::null || MVT::GetNumberVecs(*R_)!=blockSize_) { 00305 // Get the multivector that is not null. 00306 Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV ); 00307 TEUCHOS_TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument, 00308 "Belos::BlockCGIter::setStateSize(): linear problem does not specify multivectors to clone from."); 00309 R_ = MVT::Clone( *tmp, blockSize_ ); 00310 Z_ = MVT::Clone( *tmp, blockSize_ ); 00311 P_ = MVT::Clone( *tmp, blockSize_ ); 00312 AP_ = MVT::Clone( *tmp, blockSize_ ); 00313 } 00314 00315 // State storage has now been initialized. 00316 stateStorageInitialized_ = true; 00317 } 00318 } 00319 } 00320 00322 // Set the block size and make necessary adjustments. 00323 template <class ScalarType, class MV, class OP> 00324 void BlockCGIter<ScalarType,MV,OP>::setBlockSize (int blockSize) 00325 { 00326 // This routine only allocates space; it doesn't not perform any computation 00327 // any change in size will invalidate the state of the solver. 00328 00329 TEUCHOS_TEST_FOR_EXCEPTION(blockSize <= 0, std::invalid_argument, "Belos::BlockGmresIter::setBlockSize was passed a non-positive argument."); 00330 if (blockSize == blockSize_) { 00331 // do nothing 00332 return; 00333 } 00334 00335 if (blockSize!=blockSize_) 00336 stateStorageInitialized_ = false; 00337 00338 blockSize_ = blockSize; 00339 00340 initialized_ = false; 00341 00342 // Use the current blockSize_ to initialize the state storage. 00343 setStateSize(); 00344 00345 } 00346 00348 // Initialize this iteration object 00349 template <class ScalarType, class MV, class OP> 00350 void BlockCGIter<ScalarType,MV,OP>::initializeCG(CGIterationState<ScalarType,MV> newstate) 00351 { 00352 // Initialize the state storage if it isn't already. 00353 if (!stateStorageInitialized_) 00354 setStateSize(); 00355 00356 TEUCHOS_TEST_FOR_EXCEPTION(!stateStorageInitialized_,std::invalid_argument, 00357 "Belos::BlockCGIter::initialize(): Cannot initialize state storage!"); 00358 00359 // NOTE: In BlockCGIter R_, the initial residual, is required!!! 00360 // 00361 std::string errstr("Belos::BlockCGIter::initialize(): Specified multivectors must have a consistent length and width."); 00362 00363 // Create convenience variables for zero and one. 00364 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one(); 00365 const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero(); 00366 00367 if (newstate.R != Teuchos::null) { 00368 00369 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetVecLength(*newstate.R) != MVT::GetVecLength(*R_), 00370 std::invalid_argument, errstr ); 00371 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.R) != blockSize_, 00372 std::invalid_argument, errstr ); 00373 00374 // Copy basis vectors from newstate into V 00375 if (newstate.R != R_) { 00376 // copy over the initial residual (unpreconditioned). 00377 MVT::MvAddMv( one, *newstate.R, zero, *newstate.R, *R_ ); 00378 } 00379 // Compute initial direction vectors 00380 // Initially, they are set to the preconditioned residuals 00381 // 00382 if ( lp_->getLeftPrec() != Teuchos::null ) { 00383 lp_->applyLeftPrec( *R_, *Z_ ); 00384 if ( lp_->getRightPrec() != Teuchos::null ) { 00385 Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, blockSize_ ); 00386 lp_->applyRightPrec( *Z_, *tmp ); 00387 Z_ = tmp; 00388 } 00389 } 00390 else if ( lp_->getRightPrec() != Teuchos::null ) { 00391 lp_->applyRightPrec( *R_, *Z_ ); 00392 } 00393 else { 00394 Z_ = R_; 00395 } 00396 MVT::MvAddMv( one, *Z_, zero, *Z_, *P_ ); 00397 } 00398 else { 00399 00400 TEUCHOS_TEST_FOR_EXCEPTION(newstate.R == Teuchos::null,std::invalid_argument, 00401 "Belos::BlockCGIter::initialize(): BlockCGStateIterState does not have initial residual."); 00402 } 00403 00404 // The solver is initialized 00405 initialized_ = true; 00406 } 00407 00408 00410 // Iterate until the status test informs us we should stop. 00411 template <class ScalarType, class MV, class OP> 00412 void BlockCGIter<ScalarType,MV,OP>::iterate() 00413 { 00414 // 00415 // Allocate/initialize data structures 00416 // 00417 if (initialized_ == false) { 00418 initialize(); 00419 } 00420 // Allocate data needed for LAPACK work. 00421 int info = 0; 00422 char UPLO = 'U'; 00423 Teuchos::LAPACK<int,ScalarType> lapack; 00424 00425 // Allocate memory for scalars. 00426 Teuchos::SerialDenseMatrix<int,ScalarType> alpha( blockSize_, blockSize_ ); 00427 Teuchos::SerialDenseMatrix<int,ScalarType> beta( blockSize_, blockSize_ ); 00428 Teuchos::SerialDenseMatrix<int,ScalarType> rHz( blockSize_, blockSize_ ), 00429 rHz_old( blockSize_, blockSize_ ), pAp( blockSize_, blockSize_ ); 00430 00431 // Create convenience variables for zero and one. 00432 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one(); 00433 00434 // Get the current solution std::vector. 00435 Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec(); 00436 00437 // Check that the current solution std::vector has blockSize_ columns. 00438 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*cur_soln_vec) != blockSize_, CGIterateFailure, 00439 "Belos::BlockCGIter::iterate(): current linear system does not have the right number of vectors!" ); 00440 int rank = ortho_->normalize( *P_, Teuchos::null ); 00441 TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,CGIterationOrthoFailure, 00442 "Belos::BlockCGIter::iterate(): Failed to compute initial block of orthonormal direction vectors."); 00443 00444 00446 // Iterate until the status test tells us to stop. 00447 // 00448 while (stest_->checkStatus(this) != Passed) { 00449 00450 // Increment the iteration 00451 iter_++; 00452 00453 // Multiply the current direction std::vector by A and store in Ap_ 00454 lp_->applyOp( *P_, *AP_ ); 00455 00456 // Compute alpha := <P_,R_> / <P_,AP_> 00457 // 1) Compute P^T * A * P = pAp and P^T * R 00458 // 2) Compute the Cholesky Factorization of pAp 00459 // 3) Back and forward solves to compute alpha 00460 // 00461 MVT::MvTransMv( one, *P_, *R_, alpha ); 00462 MVT::MvTransMv( one, *P_, *AP_, pAp ); 00463 00464 // Compute Cholesky factorization of pAp 00465 lapack.POTRF(UPLO, blockSize_, pAp.values(), blockSize_, &info); 00466 TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure, 00467 "Belos::BlockCGIter::iterate(): Failed to compute Cholesky factorization using LAPACK routine POTRF."); 00468 00469 // Compute alpha by performing a back and forward solve with the Cholesky factorization in pAp. 00470 lapack.POTRS(UPLO, blockSize_, blockSize_, pAp.values(), blockSize_, 00471 alpha.values(), blockSize_, &info); 00472 TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure, 00473 "Belos::BlockCGIter::iterate(): Failed to compute alpha using Cholesky factorization (POTRS)."); 00474 00475 // 00476 // Update the solution std::vector X := X + alpha * P_ 00477 // 00478 MVT::MvTimesMatAddMv( one, *P_, alpha, one, *cur_soln_vec ); 00479 lp_->updateSolution(); 00480 // 00481 // Compute the new residual R_ := R_ - alpha * AP_ 00482 // 00483 MVT::MvTimesMatAddMv( -one, *AP_, alpha, one, *R_ ); 00484 // 00485 // Compute the new preconditioned residual, Z_. 00486 if ( lp_->getLeftPrec() != Teuchos::null ) { 00487 lp_->applyLeftPrec( *R_, *Z_ ); 00488 if ( lp_->getRightPrec() != Teuchos::null ) { 00489 Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, blockSize_ ); 00490 lp_->applyRightPrec( *Z_, *tmp ); 00491 Z_ = tmp; 00492 } 00493 } 00494 else if ( lp_->getRightPrec() != Teuchos::null ) { 00495 lp_->applyRightPrec( *R_, *Z_ ); 00496 } 00497 else { 00498 Z_ = R_; 00499 } 00500 // 00501 // Compute beta := <AP_,Z_> / <P_,AP_> 00502 // 1) Compute AP_^T * Z_ 00503 // 2) Compute the Cholesky Factorization of pAp (already have) 00504 // 3) Back and forward solves to compute beta 00505 00506 // Compute <AP_,Z> 00507 MVT::MvTransMv( -one, *AP_, *Z_, beta ); 00508 // 00509 lapack.POTRS(UPLO, blockSize_, blockSize_, pAp.values(), blockSize_, 00510 beta.values(), blockSize_, &info); 00511 TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure, 00512 "Belos::BlockCGIter::iterate(): Failed to compute beta using Cholesky factorization (POTRS)."); 00513 // 00514 // Compute the new direction vectors P_ = Z_ + P_ * beta 00515 // 00516 Teuchos::RCP<MV> Pnew = MVT::CloneCopy( *Z_ ); 00517 MVT::MvTimesMatAddMv(one, *P_, beta, one, *Pnew); 00518 P_ = Pnew; 00519 00520 // Compute orthonormal block of new direction vectors. 00521 rank = ortho_->normalize( *P_, Teuchos::null ); 00522 TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,CGIterationOrthoFailure, 00523 "Belos::BlockCGIter::iterate(): Failed to compute block of orthonormal direction vectors."); 00524 00525 } // end while (sTest_->checkStatus(this) != Passed) 00526 } 00527 00528 } // end Belos namespace 00529 00530 #endif /* BELOS_BLOCK_CG_ITER_HPP */
1.7.6.1