Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
AnasaziTraceMinRitzOp.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends