|
Anasazi
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Anasazi: Block Eigensolvers Package 00005 // Copyright (2004) 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 00033 #ifndef TRACEMIN_RITZ_OP_HPP 00034 #define TRACEMIN_RITZ_OP_HPP 00035 00036 #include "AnasaziConfigDefs.hpp" 00037 #include "AnasaziMatOrthoManager.hpp" 00038 #include "AnasaziMinres.hpp" 00039 #include "AnasaziTraceMinBase.hpp" 00040 00041 #ifdef HAVE_ANASAZI_BELOS 00042 #include "BelosMultiVecTraits.hpp" 00043 #include "BelosLinearProblem.hpp" 00044 #include "BelosPseudoBlockGmresSolMgr.hpp" 00045 #include "BelosOperator.hpp" 00046 #ifdef HAVE_ANASAZI_TPETRA 00047 #include "BelosTpetraAdapter.hpp" 00048 #endif 00049 #ifdef HAVE_ANASAZI_EPETRA 00050 #include "BelosEpetraAdapter.hpp" 00051 #endif 00052 #endif 00053 00054 #include "Teuchos_RCP.hpp" 00055 #include "Teuchos_SerialDenseSolver.hpp" 00056 #include "Teuchos_ScalarTraitsDecl.hpp" 00057 00058 00059 using Teuchos::RCP; 00060 00061 namespace Anasazi { 00062 namespace Experimental { 00063 00064 00065 00068 // Abstract base class for all operators 00071 template <class Scalar, class MV, class OP> 00072 class TraceMinOp 00073 { 00074 public: 00075 virtual ~TraceMinOp() { }; 00076 virtual void Apply(const MV& X, MV& Y) const =0; 00077 virtual void removeIndices(const std::vector<int>& indicesToRemove) =0; 00078 }; 00079 00080 00081 00084 // Defines a projector 00085 // Applies P_i to each individual vector x_i 00088 template <class Scalar, class MV, class OP> 00089 class TraceMinProjOp 00090 { 00091 typedef Anasazi::MultiVecTraits<Scalar,MV> MVT; 00092 const Scalar ONE; 00093 00094 public: 00095 // Constructors 00096 TraceMinProjOp(const Teuchos::RCP<const MV> X, const Teuchos::RCP<const OP> B, Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman = Teuchos::null); 00097 TraceMinProjOp(const Teuchos::RCP<const MV> X, const Teuchos::RCP<const OP> B, Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array<Teuchos::RCP<const MV> > auxVecs); 00098 00099 // Destructor 00100 ~TraceMinProjOp(); 00101 00102 // Applies the projector to a multivector 00103 void Apply(const MV& X, MV& Y) const; 00104 00105 // Called by MINRES when certain vectors converge 00106 void removeIndices(const std::vector<int>& indicesToRemove); 00107 00108 private: 00109 Teuchos::Array< Teuchos::RCP<const MV> > projVecs_; 00110 Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman_; 00111 Teuchos::RCP<const OP> B_; 00112 00113 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00114 RCP<Teuchos::Time> ProjTime_; 00115 #endif 00116 }; 00117 00118 00121 // This class defines an operator A + \sigma B 00122 // This is used to apply shifts within TraceMin 00125 template <class Scalar, class MV, class OP> 00126 class TraceMinRitzOp : public TraceMinOp<Scalar,MV,OP> 00127 { 00128 template <class Scalar_, class MV_, class OP_> friend class TraceMinProjRitzOp; 00129 template <class Scalar_, class MV_, class OP_> friend class TraceMinProjRitzOpWithPrec; 00130 template <class Scalar_, class MV_, class OP_> friend class TraceMinProjectedPrecOp; 00131 00132 typedef Anasazi::MultiVecTraits<Scalar,MV> MVT; 00133 typedef Anasazi::OperatorTraits<Scalar,MV,OP> OPT; 00134 const Scalar ONE; 00135 const Scalar ZERO; 00136 00137 public: 00138 // constructors for standard/generalized EVP 00139 TraceMinRitzOp(const Teuchos::RCP<const OP>& A, const Teuchos::RCP<const OP>& B = Teuchos::null, const Teuchos::RCP<const OP>& Prec = Teuchos::null); 00140 00141 // Destructor 00142 ~TraceMinRitzOp() { }; 00143 00144 // sets the Ritz shift 00145 void setRitzShifts(std::vector<Scalar> shifts) {ritzShifts_ = shifts;}; 00146 00147 Scalar getRitzShift(const int subscript) { return ritzShifts_[subscript]; }; 00148 00149 // sets the tolerances for the inner solves 00150 void setInnerTol(const std::vector<Scalar>& tolerances) { tolerances_ = tolerances; }; 00151 00152 void getInnerTol(std::vector<Scalar>& tolerances) const { tolerances = tolerances_; }; 00153 00154 void setMaxIts(const int maxits) { maxits_ = maxits; }; 00155 00156 int getMaxIts() const { return maxits_; }; 00157 00158 // applies A+\sigma B to a vector 00159 void Apply(const MV& X, MV& Y) const; 00160 00161 // returns (A+\sigma B)\X 00162 void ApplyInverse(const MV& X, MV& Y); 00163 00164 void removeIndices(const std::vector<int>& indicesToRemove); 00165 00166 private: 00167 Teuchos::RCP<const OP> A_, B_; 00168 Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> > Prec_; 00169 00170 int maxits_; 00171 std::vector<Scalar> ritzShifts_; 00172 std::vector<Scalar> tolerances_; 00173 00174 Teuchos::RCP< PseudoBlockMinres< Scalar,MV,TraceMinRitzOp<Scalar,MV,OP> > > solver_; 00175 00176 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00177 RCP<Teuchos::Time> PetraMultTime_, AopMultTime_; 00178 #endif 00179 }; 00180 00181 00182 00185 // Defines an operator P (A + \sigma B) P 00186 // Used for TraceMin with the projected iterative solver 00189 template <class Scalar, class MV, class OP> 00190 class TraceMinProjRitzOp : public TraceMinOp<Scalar,MV,OP> 00191 { 00192 typedef Anasazi::MultiVecTraits<Scalar,MV> MVT; 00193 typedef Anasazi::OperatorTraits<Scalar,MV,TraceMinRitzOp<Scalar,MV,OP> > OPT; 00194 00195 public: 00196 // constructors for standard/generalized EVP 00197 TraceMinProjRitzOp(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, const Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman = Teuchos::null); 00198 TraceMinProjRitzOp(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, const Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array<Teuchos::RCP<const MV> > auxVecs); 00199 00200 // applies P (A+\sigma B) P to a vector 00201 void Apply(const MV& X, MV& Y) const; 00202 00203 // returns P(A+\sigma B)P\X 00204 // this is not const due to the clumsiness with amSolving 00205 void ApplyInverse(const MV& X, MV& Y); 00206 00207 void removeIndices(const std::vector<int>& indicesToRemove); 00208 00209 private: 00210 Teuchos::RCP< TraceMinRitzOp<Scalar,MV,OP> > Op_; 00211 Teuchos::RCP< TraceMinProjOp<Scalar,MV,OP> > projector_; 00212 00213 Teuchos::RCP< PseudoBlockMinres< Scalar,MV,TraceMinProjRitzOp<Scalar,MV,OP> > > solver_; 00214 }; 00215 00216 00217 00220 // Defines a preconditioner to be used with our projection method 00221 // Because we're using projected CG/minres/gmres, this preconditioner has to do projection as well 00224 // TODO: Should this be public? 00225 template <class Scalar, class MV, class OP> 00226 class TraceMinProjectedPrecOp : public TraceMinOp<Scalar,MV,OP> 00227 { 00228 typedef Anasazi::MultiVecTraits<Scalar,MV> MVT; 00229 typedef Anasazi::OperatorTraits<Scalar,MV,OP> OPT; 00230 const Scalar ONE; 00231 00232 public: 00233 // constructors for standard/generalized EVP 00234 TraceMinProjectedPrecOp(const Teuchos::RCP<const OP> Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman = Teuchos::null); 00235 TraceMinProjectedPrecOp(const Teuchos::RCP<const OP> Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array< Teuchos::RCP<const MV> > auxVecs); 00236 00237 ~TraceMinProjectedPrecOp(); 00238 00239 void Apply(const MV& X, MV& Y) const; 00240 00241 void removeIndices(const std::vector<int>& indicesToRemove); 00242 00243 private: 00244 Teuchos::RCP<const OP> Op_; 00245 Teuchos::Array< Teuchos::RCP<const MV> > projVecs_; 00246 00247 Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman_; 00248 Teuchos::RCP<const OP> B_; 00249 }; 00250 00251 00252 00255 // Defines a preconditioner to be used with our projection method 00256 // Because we're using projected CG/minres/gmres, this preconditioner has to do projection as well 00259 #ifdef HAVE_ANASAZI_BELOS 00260 template <class Scalar, class MV, class OP> 00261 class TraceMinProjRitzOpWithPrec : public TraceMinOp<Scalar,MV,OP> 00262 { 00263 typedef Anasazi::MultiVecTraits<Scalar,MV> MVT; 00264 typedef Anasazi::OperatorTraits<Scalar,MV,TraceMinRitzOp<Scalar,MV,OP> > OPT; 00265 const Scalar ONE; 00266 00267 public: 00268 // constructors for standard/generalized EVP 00269 TraceMinProjRitzOpWithPrec(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman = Teuchos::null); 00270 TraceMinProjRitzOpWithPrec(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array< Teuchos::RCP<const MV> > auxVecs); 00271 00272 void Apply(const MV& X, MV& Y) const; 00273 00274 // returns P(A+\sigma B)P\X 00275 // this is not const due to the clumsiness with amSolving 00276 void ApplyInverse(const MV& X, MV& Y); 00277 00278 void removeIndices(const std::vector<int>& indicesToRemove); 00279 00280 private: 00281 Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> > Op_; 00282 Teuchos::RCP<TraceMinProjectedPrecOp<Scalar,MV,OP> > Prec_; 00283 00284 Teuchos::RCP< Belos::PseudoBlockGmresSolMgr< Scalar,MV,TraceMinOp<Scalar,MV,OP> > > solver_; 00285 Teuchos::RCP< Belos::LinearProblem<Scalar,MV,TraceMinOp<Scalar,MV,OP> > > problem_; 00286 }; 00287 #endif 00288 00289 }} // end of namespace 00290 00291 00292 00295 // Operator traits classes 00296 // Required to use user-defined operators with a Krylov solver in Belos 00299 namespace Anasazi 00300 { 00301 template <class Scalar, class MV, class OP> 00302 class OperatorTraits <Scalar, MV, Experimental::TraceMinOp<Scalar,MV,OP> > 00303 { 00304 public: 00305 static void 00306 Apply (const Experimental::TraceMinOp<Scalar,MV,OP>& Op, 00307 const MV& x, 00308 MV& y) {Op.Apply(x,y);}; 00309 00311 static bool 00312 HasApplyTranspose (const Experimental::TraceMinOp<Scalar,MV,OP>& Op) {return true;}; 00313 }; 00314 } 00315 00316 00317 #ifdef HAVE_ANASAZI_BELOS 00318 namespace Belos 00319 { 00320 template <class Scalar, class MV, class OP> 00321 class OperatorTraits <Scalar, MV, Anasazi::Experimental::TraceMinOp<Scalar,MV,OP> > 00322 { 00323 public: 00324 static void 00325 Apply (const Anasazi::Experimental::TraceMinOp<Scalar,MV,OP>& Op, 00326 const MV& x, 00327 MV& y, Belos::ETrans trans = NOTRANS) {Op.Apply(x,y);}; 00328 00330 static bool 00331 HasApplyTranspose (const Anasazi::Experimental::TraceMinOp<Scalar,MV,OP>& Op) {return true;}; 00332 }; 00333 } 00334 #endif 00335 00336 00337 00338 namespace Anasazi 00339 { 00340 template <class Scalar, class MV, class OP> 00341 class OperatorTraits <Scalar, MV, Experimental::TraceMinRitzOp<Scalar,MV,OP> > 00342 { 00343 public: 00344 static void 00345 Apply (const Experimental::TraceMinRitzOp<Scalar,MV,OP>& Op, 00346 const MV& x, 00347 MV& y) {Op.Apply(x,y);}; 00348 00350 static bool 00351 HasApplyTranspose (const Experimental::TraceMinRitzOp<Scalar,MV,OP>& Op) {return true;}; 00352 }; 00353 } 00354 00355 00356 00357 namespace Anasazi 00358 { 00359 template <class Scalar, class MV, class OP> 00360 class OperatorTraits <Scalar, MV, Experimental::TraceMinProjRitzOp<Scalar,MV,OP> > 00361 { 00362 public: 00363 static void 00364 Apply (const Experimental::TraceMinProjRitzOp<Scalar,MV,OP>& Op, 00365 const MV& x, 00366 MV& y) {Op.Apply(x,y);}; 00367 00369 static bool 00370 HasApplyTranspose (const Experimental::TraceMinProjRitzOp<Scalar,MV,OP>& Op) {return true;}; 00371 }; 00372 } 00373 00374 00375 00376 namespace Anasazi 00377 { 00378 template <class Scalar, class MV, class OP> 00379 class OperatorTraits <Scalar, MV, Experimental::TraceMinProjectedPrecOp<Scalar,MV,OP> > 00380 { 00381 public: 00382 static void 00383 Apply (const Experimental::TraceMinProjectedPrecOp<Scalar,MV,OP>& Op, 00384 const MV& x, 00385 MV& y) {Op.Apply(x,y);}; 00386 00388 static bool 00389 HasApplyTranspose (const Experimental::TraceMinProjectedPrecOp<Scalar,MV,OP>& Op) {return true;}; 00390 }; 00391 } 00392 00393 00394 00395 namespace Anasazi { 00396 namespace Experimental { 00399 // TraceMinProjOp implementations 00402 template <class Scalar, class MV, class OP> 00403 TraceMinProjOp<Scalar,MV,OP>::TraceMinProjOp(const Teuchos::RCP<const MV> X, const Teuchos::RCP<const OP> B, Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman) : 00404 ONE(Teuchos::ScalarTraits<Scalar>::one()) 00405 { 00406 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00407 ProjTime_ = Teuchos::TimeMonitor::getNewTimer("Anasazi: TraceMinProjOp::Apply()"); 00408 #endif 00409 00410 B_ = B; 00411 orthman_ = orthman; 00412 if(orthman_ != Teuchos::null && B_ != Teuchos::null) 00413 orthman_->setOp(Teuchos::null); 00414 00415 // Make it so X'BBX = I 00416 // If there is no B, this step is unnecessary because X'X = I already 00417 if(B_ != Teuchos::null) 00418 { 00419 int nvec = MVT::GetNumberVecs(*X); 00420 00421 if(orthman_ != Teuchos::null) 00422 { 00423 // Want: X'X = I NOT X'MX = I 00424 Teuchos::RCP<MV> helperMV = MVT::CloneCopy(*X); 00425 orthman_->normalizeMat(*helperMV); 00426 projVecs_.push_back(helperMV); 00427 } 00428 else 00429 { 00430 std::vector<Scalar> normvec(nvec); 00431 MVT::MvNorm(*X,normvec); 00432 for(int i=0; i<nvec; i++) 00433 normvec[i] = ONE/normvec[i]; 00434 Teuchos::RCP<MV> helperMV = MVT::CloneCopy(*X); 00435 MVT::MvScale(*helperMV,normvec); 00436 projVecs_.push_back(helperMV); 00437 } 00438 } 00439 else 00440 projVecs_.push_back(MVT::CloneCopy(*X)); 00441 } 00442 00443 00444 template <class Scalar, class MV, class OP> 00445 TraceMinProjOp<Scalar,MV,OP>::TraceMinProjOp(const Teuchos::RCP<const MV> X, const Teuchos::RCP<const OP> B, Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array<Teuchos::RCP<const MV> > auxVecs) : 00446 ONE(Teuchos::ScalarTraits<Scalar>::one()) 00447 { 00448 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00449 ProjTime_ = Teuchos::TimeMonitor::getNewTimer("Anasazi: TraceMinProjOp::Apply()"); 00450 #endif 00451 00452 B_ = B; 00453 orthman_ = orthman; 00454 if(B_ != Teuchos::null) 00455 orthman_->setOp(Teuchos::null); 00456 00457 projVecs_ = auxVecs; 00458 00459 // Make it so X'BBX = I 00460 // If there is no B, this step is unnecessary because X'X = I already 00461 if(B_ != Teuchos::null) 00462 { 00463 // Want: X'X = I NOT X'MX = I 00464 Teuchos::RCP<MV> helperMV = MVT::CloneCopy(*X); 00465 orthman_->normalizeMat(*helperMV); 00466 projVecs_.push_back(helperMV); 00467 00468 } 00469 else 00470 projVecs_.push_back(MVT::CloneCopy(*X)); 00471 } 00472 00473 00474 // Destructor - make sure to reset the operator in the ortho manager 00475 template <class Scalar, class MV, class OP> 00476 TraceMinProjOp<Scalar,MV,OP>::~TraceMinProjOp() 00477 { 00478 if(orthman_ != Teuchos::null) 00479 orthman_->setOp(B_); 00480 } 00481 00482 00483 // Compute Px = x - proj proj'x 00484 template <class Scalar, class MV, class OP> 00485 void TraceMinProjOp<Scalar,MV,OP>::Apply(const MV& X, MV& Y) const 00486 { 00487 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00488 Teuchos::TimeMonitor lcltimer( *ProjTime_ ); 00489 #endif 00490 00491 if(orthman_ != Teuchos::null) 00492 { 00493 MVT::Assign(X,Y); 00494 orthman_->projectMat(Y,projVecs_); 00495 } 00496 else 00497 { 00498 int nvec = MVT::GetNumberVecs(X); 00499 std::vector<Scalar> dotProducts(nvec); 00500 MVT::MvDot(*projVecs_[0],X,dotProducts); 00501 Teuchos::RCP<MV> helper = MVT::CloneCopy(*projVecs_[0]); 00502 MVT::MvScale(*helper,dotProducts); 00503 MVT::MvAddMv(ONE,X,-ONE,*helper,Y); 00504 } 00505 } 00506 00507 00508 00509 template <class Scalar, class MV, class OP> 00510 void TraceMinProjOp<Scalar,MV,OP>::removeIndices(const std::vector<int>& indicesToRemove) 00511 { 00512 if (orthman_ == Teuchos::null) { 00513 const int nprojvecs = projVecs_.size(); 00514 const int nvecs = MVT::GetNumberVecs(*projVecs_[nprojvecs-1]); 00515 const int numRemoving = indicesToRemove.size(); 00516 std::vector<int> helper(nvecs), indicesToLeave(nvecs-numRemoving); 00517 00518 for (int i=0; i<nvecs; i++) { 00519 helper[i] = i; 00520 } 00521 00522 std::set_difference(helper.begin(), helper.end(), indicesToRemove.begin(), indicesToRemove.end(), indicesToLeave.begin()); 00523 00524 Teuchos::RCP<MV> helperMV = MVT::CloneCopy(*projVecs_[nprojvecs-1],indicesToLeave); 00525 projVecs_[nprojvecs-1] = helperMV; 00526 } 00527 } 00528 00529 00532 // TraceMinRitzOp implementations 00535 template <class Scalar, class MV, class OP> 00536 TraceMinRitzOp<Scalar,MV,OP>::TraceMinRitzOp(const Teuchos::RCP<const OP>& A, const Teuchos::RCP<const OP>& B, const Teuchos::RCP<const OP>& Prec) : 00537 ONE(Teuchos::ScalarTraits<Scalar>::one()), 00538 ZERO(Teuchos::ScalarTraits<Scalar>::zero()) 00539 { 00540 A_ = A; 00541 B_ = B; 00542 // TODO: maxits should not be hard coded 00543 maxits_ = 1000; 00544 00545 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00546 PetraMultTime_ = Teuchos::TimeMonitor::getNewTimer("Anasazi: TraceMinRitzOp: *Petra::Apply()"); 00547 AopMultTime_ = Teuchos::TimeMonitor::getNewTimer("Anasazi: TraceMinRitzOp::Apply()"); 00548 #endif 00549 00550 // create the operator for my minres solver 00551 Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> > linSolOp = Teuchos::rcp(this); 00552 linSolOp.release(); 00553 00554 // TODO: This should support left and right prec 00555 if(Prec != Teuchos::null) 00556 Prec_ = Teuchos::rcp( new TraceMinRitzOp<Scalar,MV,OP>(Prec) ); 00557 00558 // create my minres solver 00559 solver_ = Teuchos::rcp( new PseudoBlockMinres< Scalar,MV,TraceMinRitzOp<Scalar,MV,OP> >(linSolOp,Prec_) ); 00560 } 00561 00562 00563 00564 template <class Scalar, class MV, class OP> 00565 void TraceMinRitzOp<Scalar,MV,OP>::Apply(const MV& X, MV& Y) const 00566 { 00567 int nvecs = MVT::GetNumberVecs(X); 00568 00569 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00570 Teuchos::TimeMonitor outertimer( *AopMultTime_ ); 00571 #endif 00572 00573 // Y := A*X 00574 { 00575 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 00576 Teuchos::TimeMonitor lcltimer( *PetraMultTime_ ); 00577 #endif 00578 00579 OPT::Apply(*A_,X,Y); 00580 } 00581 00582 // If we are a preconditioner, we're not using shifts 00583 if(ritzShifts_.size() > 0) 00584 { 00585 // Get the indices of nonzero Ritz shifts 00586 std::vector<int> nonzeroRitzIndices; 00587 nonzeroRitzIndices.reserve(nvecs); 00588 for(int i=0; i<nvecs; i++) 00589 { 00590 if(ritzShifts_[i] != ZERO) 00591 nonzeroRitzIndices.push_back(i); 00592 } 00593 00594 // Handle Ritz shifts 00595 int numRitzShifts = nonzeroRitzIndices.size(); 00596 if(numRitzShifts > 0) 00597 { 00598 // Get pointers to the appropriate parts of X and Y 00599 Teuchos::RCP<const MV> ritzX = MVT::CloneView(X,nonzeroRitzIndices); 00600 Teuchos::RCP<MV> ritzY = MVT::CloneViewNonConst(Y,nonzeroRitzIndices); 00601 00602 // Get the nonzero Ritz shifts 00603 std::vector<Scalar> nonzeroRitzShifts(numRitzShifts); 00604 for(int i=0; i<numRitzShifts; i++) 00605 nonzeroRitzShifts[i] = ritzShifts_[nonzeroRitzIndices[i]]; 00606 00607 // Compute Y := AX + ritzShift BX 00608 if(B_ != Teuchos::null) 00609 { 00610 Teuchos::RCP<MV> BX = MVT::Clone(*ritzX,numRitzShifts); 00611 OPT::Apply(*B_,*ritzX,*BX); 00612 MVT::MvScale(*BX,nonzeroRitzShifts); 00613 MVT::MvAddMv(ONE,*ritzY,-ONE,*BX,*ritzY); 00614 } 00615 // Compute Y := AX + ritzShift X 00616 else 00617 { 00618 Teuchos::RCP<MV> scaledX = MVT::CloneCopy(*ritzX); 00619 MVT::MvScale(*scaledX,nonzeroRitzShifts); 00620 MVT::MvAddMv(ONE,*ritzY,-ONE,*scaledX,*ritzY); 00621 } 00622 } 00623 } 00624 } 00625 00626 00627 00628 template <class Scalar, class MV, class OP> 00629 void TraceMinRitzOp<Scalar,MV,OP>::ApplyInverse(const MV& X, MV& Y) 00630 { 00631 int nvecs = MVT::GetNumberVecs(X); 00632 std::vector<int> indices(nvecs); 00633 for(int i=0; i<nvecs; i++) 00634 indices[i] = i; 00635 00636 Teuchos::RCP<const MV> rcpX = MVT::CloneView(X,indices); 00637 Teuchos::RCP<MV> rcpY = MVT::CloneViewNonConst(Y,indices); 00638 00639 // Solve the linear system A*Y = X 00640 solver_->setTol(tolerances_); 00641 solver_->setMaxIter(maxits_); 00642 00643 // Set solution and RHS 00644 solver_->setSol(rcpY); 00645 solver_->setRHS(rcpX); 00646 00647 // Solve the linear system 00648 solver_->solve(); 00649 } 00650 00651 00652 00653 template <class Scalar, class MV, class OP> 00654 void TraceMinRitzOp<Scalar,MV,OP>::removeIndices(const std::vector<int>& indicesToRemove) 00655 { 00656 int nvecs = tolerances_.size(); 00657 int numRemoving = indicesToRemove.size(); 00658 std::vector<int> helper(nvecs), indicesToLeave(nvecs-numRemoving); 00659 std::vector<Scalar> helperS(nvecs-numRemoving); 00660 00661 for(int i=0; i<nvecs; i++) 00662 helper[i] = i; 00663 00664 std::set_difference(helper.begin(), helper.end(), indicesToRemove.begin(), indicesToRemove.end(), indicesToLeave.begin()); 00665 00666 for(int i=0; i<nvecs-numRemoving; i++) 00667 helperS[i] = ritzShifts_[indicesToLeave[i]]; 00668 ritzShifts_ = helperS; 00669 00670 for(int i=0; i<nvecs-numRemoving; i++) 00671 helperS[i] = tolerances_[indicesToLeave[i]]; 00672 tolerances_ = helperS; 00673 } 00674 00675 00676 00679 // TraceMinProjRitzOp implementations 00682 template <class Scalar, class MV, class OP> 00683 TraceMinProjRitzOp<Scalar,MV,OP>::TraceMinProjRitzOp(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, const Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman) 00684 { 00685 Op_ = Op; 00686 00687 // Create the projector object 00688 projector_ = Teuchos::rcp( new TraceMinProjOp<Scalar,MV,OP>(projVecs, Op_->B_, orthman) ); 00689 00690 // create the operator for my minres solver 00691 Teuchos::RCP<TraceMinProjRitzOp<Scalar,MV,OP> > linSolOp = Teuchos::rcp(this); 00692 linSolOp.release(); 00693 00694 // create my minres solver 00695 solver_ = Teuchos::rcp( new PseudoBlockMinres< Scalar,MV,TraceMinProjRitzOp<Scalar,MV,OP> >(linSolOp) ); 00696 } 00697 00698 00699 template <class Scalar, class MV, class OP> 00700 TraceMinProjRitzOp<Scalar,MV,OP>::TraceMinProjRitzOp(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, const Teuchos::RCP<Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array<Teuchos::RCP<const MV> > auxVecs) 00701 { 00702 Op_ = Op; 00703 00704 // Create the projector object 00705 projector_ = Teuchos::rcp( new TraceMinProjOp<Scalar,MV,OP>(projVecs, Op_->B_, orthman, auxVecs) ); 00706 00707 // create the operator for my minres solver 00708 Teuchos::RCP<TraceMinProjRitzOp<Scalar,MV,OP> > linSolOp = Teuchos::rcp(this); 00709 linSolOp.release(); 00710 00711 // create my minres solver 00712 solver_ = Teuchos::rcp( new PseudoBlockMinres< Scalar,MV,TraceMinProjRitzOp<Scalar,MV,OP> >(linSolOp) ); 00713 } 00714 00715 00716 00717 // Y:= P (A+\sigma B) P X 00718 template <class Scalar, class MV, class OP> 00719 void TraceMinProjRitzOp<Scalar,MV,OP>::Apply(const MV& X, MV& Y) const 00720 { 00721 int nvecs = MVT::GetNumberVecs(X); 00722 00723 // compute PX 00724 Teuchos::RCP<MV> PX = MVT::Clone(X,nvecs); 00725 projector_->Apply(X,*PX); 00726 00727 // compute (A+\sigma B) P X 00728 Teuchos::RCP<MV> APX = MVT::Clone(X,nvecs); 00729 OPT::Apply(*Op_,*PX,*APX); 00730 00731 // compute Y := P (A+\sigma B) P X 00732 projector_->Apply(*APX,Y); 00733 } 00734 00735 00736 00737 template <class Scalar, class MV, class OP> 00738 void TraceMinProjRitzOp<Scalar,MV,OP>::ApplyInverse(const MV& X, MV& Y) 00739 { 00740 int nvecs = MVT::GetNumberVecs(X); 00741 std::vector<int> indices(nvecs); 00742 for(int i=0; i<nvecs; i++) 00743 indices[i] = i; 00744 00745 Teuchos::RCP<MV> rcpY = MVT::CloneViewNonConst(Y,indices); 00746 Teuchos::RCP<MV> PX = MVT::Clone(X,nvecs); 00747 projector_->Apply(X,*PX); 00748 00749 // Solve the linear system A*Y = X 00750 solver_->setTol(Op_->tolerances_); 00751 solver_->setMaxIter(Op_->maxits_); 00752 00753 // Set solution and RHS 00754 solver_->setSol(rcpY); 00755 solver_->setRHS(PX); 00756 00757 // Solve the linear system 00758 solver_->solve(); 00759 } 00760 00761 00762 00763 template <class Scalar, class MV, class OP> 00764 void TraceMinProjRitzOp<Scalar,MV,OP>::removeIndices(const std::vector<int>& indicesToRemove) 00765 { 00766 Op_->removeIndices(indicesToRemove); 00767 00768 projector_->removeIndices(indicesToRemove); 00769 } 00770 00771 00772 00773 00774 #ifdef HAVE_ANASAZI_BELOS 00775 00776 00777 // TraceMinProjRitzOpWithPrec implementations 00780 template <class Scalar, class MV, class OP> 00781 TraceMinProjRitzOpWithPrec<Scalar,MV,OP>::TraceMinProjRitzOpWithPrec(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman) : 00782 ONE(Teuchos::ScalarTraits<Scalar>::one()) 00783 { 00784 Op_ = Op; 00785 00786 // create the operator for the Belos solver 00787 Teuchos::RCP<TraceMinProjRitzOpWithPrec<Scalar,MV,OP> > linSolOp = Teuchos::rcp(this); 00788 linSolOp.release(); 00789 00790 // Create the linear problem 00791 problem_ = Teuchos::rcp(new Belos::LinearProblem< Scalar,MV,TraceMinOp<Scalar,MV,OP> >()); 00792 00793 // Set the operator 00794 problem_->setOperator(linSolOp); 00795 00796 // Set the preconditioner 00797 // TODO: This does not support right preconditioning 00798 Prec_ = Teuchos::rcp( new TraceMinProjectedPrecOp<Scalar,MV,OP>(Op_->Prec_->A_, projVecs, orthman) ); 00799 problem_->setLeftPrec(Prec_); 00800 00801 // create the pseudoblock gmres solver 00802 // minres has trouble with the projected preconditioner 00803 solver_ = Teuchos::rcp( new Belos::PseudoBlockGmresSolMgr< Scalar,MV,TraceMinOp<Scalar,MV,OP> >()); 00804 } 00805 00806 00807 template <class Scalar, class MV, class OP> 00808 TraceMinProjRitzOpWithPrec<Scalar,MV,OP>::TraceMinProjRitzOpWithPrec(const Teuchos::RCP<TraceMinRitzOp<Scalar,MV,OP> >& Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array< Teuchos::RCP<const MV> > auxVecs) : 00809 ONE(Teuchos::ScalarTraits<Scalar>::one()) 00810 { 00811 Op_ = Op; 00812 00813 // create the operator for the Belos solver 00814 Teuchos::RCP<const TraceMinProjRitzOpWithPrec<Scalar,MV,OP> > linSolOp = Teuchos::rcp(this); 00815 linSolOp.release(); 00816 00817 // Create the linear problem 00818 problem_ = Teuchos::rcp(new Belos::LinearProblem< Scalar,MV,TraceMinOp<Scalar,MV,OP> >()); 00819 00820 // Set the operator 00821 problem_->setOperator(linSolOp); 00822 00823 // Set the preconditioner 00824 // TODO: This does not support right preconditioning 00825 Prec_ = Teuchos::rcp( new TraceMinProjectedPrecOp<Scalar,MV,OP>(Op_->Prec_->A_, projVecs, orthman, auxVecs) ); 00826 problem_->setRightPrec(Prec_); 00827 00828 // create the pseudoblock gmres solver 00829 // minres has trouble with the projected preconditioner 00830 solver_ = Teuchos::rcp( new Belos::PseudoBlockGmresSolMgr< Scalar,MV,TraceMinOp<Scalar,MV,OP> >()); 00831 } 00832 00833 00834 template <class Scalar, class MV, class OP> 00835 void TraceMinProjRitzOpWithPrec<Scalar,MV,OP>::Apply(const MV& X, MV& Y) const 00836 { 00837 OPT::Apply(*Op_,X,Y); 00838 } 00839 00840 00841 template <class Scalar, class MV, class OP> 00842 void TraceMinProjRitzOpWithPrec<Scalar,MV,OP>::ApplyInverse(const MV& X, MV& Y) 00843 { 00844 int nvecs = MVT::GetNumberVecs(X); 00845 std::vector<int> indices(nvecs); 00846 for(int i=0; i<nvecs; i++) 00847 indices[i] = i; 00848 00849 Teuchos::RCP<MV> rcpY = MVT::CloneViewNonConst(Y,indices); 00850 Teuchos::RCP<const MV> rcpX = MVT::CloneView(X,indices); 00851 00852 // Create the linear problem 00853 problem_->setProblem(rcpY,rcpX); 00854 00855 // Set the problem for the solver 00856 solver_->setProblem(problem_); 00857 00858 // Set up the parameters for gmres 00859 // TODO: Accept maximum number of iterations 00860 // TODO: Make sure single shift really means single shift 00861 // TODO: Look into fixing my problem with the deflation quorum 00862 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::rcp(new Teuchos::ParameterList()); 00863 pl->set("Convergence Tolerance", Op_->tolerances_[0]); 00864 pl->set("Verbosity", Belos::Debug+Belos::IterationDetails+Belos::StatusTestDetails); 00865 solver_->setParameters(pl); 00866 00867 // Solve the linear system 00868 solver_->solve(); 00869 } 00870 00871 00872 template <class Scalar, class MV, class OP> 00873 void TraceMinProjRitzOpWithPrec<Scalar,MV,OP>::removeIndices(const std::vector<int>& indicesToRemove) 00874 { 00875 Op_->removeIndices(indicesToRemove); 00876 00877 Prec_->removeIndices(indicesToRemove); 00878 } 00879 #endif 00880 00881 00884 // TraceMinProjectedPrecOp implementations 00887 template <class Scalar, class MV, class OP> 00888 TraceMinProjectedPrecOp<Scalar,MV,OP>::TraceMinProjectedPrecOp(const Teuchos::RCP<const OP> Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman) : 00889 ONE (Teuchos::ScalarTraits<Scalar>::one()) 00890 { 00891 Op_ = Op; 00892 orthman_ = orthman; 00893 00894 int nvecs = MVT::GetNumberVecs(*projVecs); 00895 Teuchos::RCP<MV> helperMV = MVT::Clone(*projVecs,nvecs); 00896 00897 // Compute Prec \ projVecs 00898 OPT::Apply(*Op_,*projVecs,*helperMV); 00899 00900 if(orthman_ != Teuchos::null) 00901 { 00902 // Set the operator for the inner products 00903 B_ = orthman_->getOp(); 00904 orthman_->setOp(Op_); 00905 00906 Teuchos::RCP<MV> locProjVecs = MVT::CloneCopy(*projVecs); 00907 00908 // Normalize the vectors such that Y' Prec \ Y = I 00909 const int rank = orthman_->normalizeMat (*locProjVecs, Teuchos::null, helperMV); 00910 00911 // FIXME (mfh 08 Aug 2014) Write a named exception for this case. 00912 TEUCHOS_TEST_FOR_EXCEPTION(rank != nvecs, std::runtime_error, "Belos::TraceMinProjectedPrecOp: constructor: Loss of orthogonality detected."); 00913 00914 orthman_->setOp(Teuchos::null); 00915 } 00916 else 00917 { 00918 std::vector<Scalar> dotprods(nvecs); 00919 MVT::MvDot(*projVecs,*helperMV,dotprods); 00920 00921 for(int i=0; i<nvecs; i++) 00922 dotprods[i] = ONE/sqrt(dotprods[i]); 00923 00924 MVT::MvScale(*helperMV, dotprods); 00925 } 00926 00927 projVecs_.push_back(helperMV); 00928 } 00929 00930 00931 template <class Scalar, class MV, class OP> 00932 TraceMinProjectedPrecOp<Scalar,MV,OP>::TraceMinProjectedPrecOp(const Teuchos::RCP<const OP> Op, const Teuchos::RCP<const MV> projVecs, Teuchos::RCP< Anasazi::MatOrthoManager<Scalar,MV,OP> > orthman, Teuchos::Array< Teuchos::RCP<const MV> > auxVecs) : 00933 ONE(Teuchos::ScalarTraits<Scalar>::one()) 00934 { 00935 Op_ = Op; 00936 orthman_ = orthman; 00937 00938 int nvecs; 00939 Teuchos::RCP<MV> locProjVecs; 00940 00941 // Add the aux vecs to the projector 00942 if(auxVecs.size() > 0) 00943 { 00944 // Get the total number of vectors 00945 nvecs = MVT::GetNumberVecs(*projVecs); 00946 for(int i=0; i<auxVecs.size(); i++) 00947 nvecs += MVT::GetNumberVecs(*auxVecs[i]); 00948 00949 // Allocate space for all of them 00950 locProjVecs = MVT::Clone(*projVecs, nvecs); 00951 00952 // Copy the vectors over 00953 int startIndex = 0; 00954 std::vector<int> locind(nvecs); 00955 00956 locind.resize(MVT::GetNumberVecs(*projVecs)); 00957 for (size_t i = 0; i<locind.size(); i++) { 00958 locind[i] = startIndex + i; 00959 } 00960 startIndex += locind.size(); 00961 MVT::SetBlock(*projVecs,locind,*locProjVecs); 00962 00963 for (size_t i=0; i < static_cast<size_t> (auxVecs.size ()); ++i) 00964 { 00965 locind.resize(MVT::GetNumberVecs(*auxVecs[i])); 00966 for(size_t j=0; j<locind.size(); j++) locind[j] = startIndex + j; 00967 startIndex += locind.size(); 00968 MVT::SetBlock(*auxVecs[i],locind,*locProjVecs); 00969 } 00970 } 00971 else 00972 { 00973 // Copy the vectors over 00974 nvecs = MVT::GetNumberVecs(*projVecs); 00975 locProjVecs = MVT::CloneCopy(*projVecs); 00976 } 00977 00978 Teuchos::RCP<MV> helperMV = MVT::Clone(*projVecs,nvecs); 00979 00980 // Compute Prec \ projVecs 00981 OPT::Apply(*Op_,*locProjVecs,*helperMV); 00982 00983 // Set the operator for the inner products 00984 B_ = orthman_->getOp(); 00985 orthman_->setOp(Op_); 00986 00987 // Normalize the vectors such that Y' Prec \ Y = I 00988 const int rank = orthman_->normalizeMat(*locProjVecs,Teuchos::null,helperMV); 00989 00990 projVecs_.push_back(helperMV); 00991 00992 // helperMV->describe(*(Teuchos::VerboseObjectBase::getDefaultOStream()),Teuchos::VERB_EXTREME); 00993 00994 // FIXME (mfh 08 Aug 2014) Write a named exception for this case. 00995 TEUCHOS_TEST_FOR_EXCEPTION( 00996 rank != nvecs, std::runtime_error, 00997 "Belos::TraceMinProjectedPrecOp: constructor: Loss of orthogonality detected."); 00998 00999 orthman_->setOp(Teuchos::null); 01000 } 01001 01002 01003 template <class Scalar, class MV, class OP> 01004 TraceMinProjectedPrecOp<Scalar,MV,OP>::~TraceMinProjectedPrecOp() 01005 { 01006 if(orthman_ != Teuchos::null) 01007 orthman_->setOp(B_); 01008 } 01009 01010 01011 01012 template <class Scalar, class MV, class OP> 01013 void TraceMinProjectedPrecOp<Scalar,MV,OP>::Apply(const MV& X, MV& Y) const 01014 { 01015 int nvecsX = MVT::GetNumberVecs(X); 01016 01017 if(orthman_ != Teuchos::null) 01018 { 01019 // Y = M\X - proj proj' X 01020 int nvecsP = MVT::GetNumberVecs(*projVecs_[0]); 01021 OPT::Apply(*Op_,X,Y); 01022 Teuchos::RCP< Teuchos::SerialDenseMatrix<int,Scalar> > projX = Teuchos::rcp(new Teuchos::SerialDenseMatrix<int,Scalar>(nvecsP,nvecsX)); 01023 01024 MVT::MvTransMv(ONE, *projVecs_[0], X, *projX); 01025 MVT::MvTimesMatAddMv(-ONE, *projVecs_[0], *projX, ONE, Y); 01026 } 01027 else 01028 { 01029 Teuchos::RCP<MV> MX = MVT::Clone(X,nvecsX); 01030 OPT::Apply(*Op_,X,*MX); 01031 01032 std::vector<Scalar> dotprods(nvecsX); 01033 MVT::MvDot(*projVecs_[0], X, dotprods); 01034 Teuchos::RCP<MV> helper = MVT::CloneCopy(*projVecs_[0]); 01035 MVT::MvScale(*helper, dotprods); 01036 MVT::MvAddMv(ONE, *MX, -ONE, *helper, Y); 01037 } 01038 } 01039 01040 01041 template <class Scalar, class MV, class OP> 01042 void TraceMinProjectedPrecOp<Scalar,MV,OP>::removeIndices(const std::vector<int>& indicesToRemove) 01043 { 01044 if(orthman_ == Teuchos::null) 01045 { 01046 int nvecs = MVT::GetNumberVecs(*projVecs_[0]); 01047 int numRemoving = indicesToRemove.size(); 01048 std::vector<int> helper(nvecs), indicesToLeave(nvecs-numRemoving); 01049 01050 for(int i=0; i<nvecs; i++) 01051 helper[i] = i; 01052 01053 std::set_difference(helper.begin(), helper.end(), indicesToRemove.begin(), indicesToRemove.end(), indicesToLeave.begin()); 01054 01055 Teuchos::RCP<const MV> helperMV = MVT::CloneCopy(*projVecs_[0],indicesToLeave); 01056 projVecs_[0] = helperMV; 01057 } 01058 } 01059 01060 }} // end of namespace 01061 01062 #endif
1.7.6.1