Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
AnasaziSaddleOperator.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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 
00035 #ifndef ANASAZI_SADDLE_OPERATOR_HPP
00036 #define ANASAZI_SADDLE_OPERATOR_HPP
00037 
00038 #include "AnasaziConfigDefs.hpp"
00039 #include "AnasaziSaddleContainer.hpp"
00040 #include "AnasaziTraceMinRitzOp.hpp"
00041 
00042 #include "Teuchos_SerialDenseSolver.hpp"
00043 
00044 using Teuchos::RCP;
00045 
00046 enum PrecType {NO_PREC, BD_PREC, UT_PREC};
00047 
00048 namespace Anasazi {
00049 namespace Experimental {
00050 
00051 template <class ScalarType, class MV, class OP>
00052 class SaddleOperator : public TraceMinOp<ScalarType,SaddleContainer<ScalarType,MV>,OP>
00053 {
00054 public:
00055   // Default constructor
00056   SaddleOperator( ) { };
00057   SaddleOperator( const Teuchos::RCP<OP> A, const Teuchos::RCP<const MV> B, PrecType pt=NO_PREC );
00058 
00059   // Applies the saddle point operator to a "multivector"
00060   void Apply(const SaddleContainer<ScalarType,MV>& X, SaddleContainer<ScalarType,MV>& Y) const;
00061 
00062   void removeIndices(const std::vector<int>& indicesToRemove) { A_->removeIndices(indicesToRemove); };
00063 
00064 private:
00065   // A is the 1-1 block, and B the 1-2 block
00066   Teuchos::RCP<OP> A_;
00067   Teuchos::RCP<const MV> B_;
00068   Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > Schur_;
00069   PrecType pt_;
00070   
00071   typedef Anasazi::MultiVecTraits<ScalarType,MV> MVT;
00072 };
00073 
00074 
00075 
00076 // Default constructor
00077 template <class ScalarType, class MV, class OP>
00078 SaddleOperator<ScalarType, MV, OP>::SaddleOperator( const Teuchos::RCP<OP> A, const Teuchos::RCP<const MV> B, PrecType pt )
00079 {
00080   // Get a pointer to A and B
00081   A_ = A;
00082   B_ = B;
00083   pt_ = pt;
00084 
00085   if(pt == BD_PREC || pt == UT_PREC)
00086   {
00087     // Form the Schur complement
00088     int nvecs = MVT::GetNumberVecs(*B);
00089     Teuchos::RCP<MV> AinvB = MVT::Clone(*B,nvecs);
00090     Schur_ = rcp(new Teuchos::SerialDenseMatrix<int,ScalarType>(nvecs,nvecs));
00091 
00092     A_->Apply(*B_,*AinvB);
00093 
00094     MVT::MvTransMv(1., *B_, *AinvB, *Schur_);
00095   }
00096 }
00097 
00098 // Applies the saddle point operator to a "multivector"
00099 template <class ScalarType, class MV, class OP>
00100 void SaddleOperator<ScalarType, MV, OP>::Apply(const SaddleContainer<ScalarType,MV>& X, SaddleContainer<ScalarType,MV>& Y) const
00101 {
00102   if(pt_ == NO_PREC)
00103   {
00104     // trans does literally nothing, because the operator is symmetric
00105     // Y.bottom = B'X.top
00106     MVT::MvTransMv(1., *B_, *(X.X_), *Y.Y_);
00107   
00108     // Y.top = A*X.top+B*X.bottom
00109     A_->Apply(*(X.X_), *(Y.X_));
00110     MVT::MvTimesMatAddMv(1., *B_, *X.Y_, 1., *(Y.X_));
00111   }
00112   else if(pt_ == BD_PREC)
00113   {
00114     Teuchos::SerialDenseSolver<int,ScalarType> MySolver;
00115 
00116     // Solve A Y.X = X.X
00117     A_->Apply(*(X.X_),*(Y.X_));
00118 
00119     // So, let me tell you a funny story about how the SerialDenseSolver destroys the original matrix...
00120     Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > localSchur = Teuchos::rcp(new Teuchos::SerialDenseMatrix<int,ScalarType>(*Schur_));
00121 
00122     // Solve the small system
00123     MySolver.setMatrix(localSchur);
00124     MySolver.setVectors(Y.Y_, X.Y_);
00125     MySolver.solve();
00126   }
00127   else if(pt_ == UT_PREC)
00128   {
00129     std::cout << "block upper triangular preconditioning is not implemented yet.  Sorry for any inconvenience!\n";
00130   }
00131   else
00132   {
00133     std::cout << "Not a valid preconditioner type\n";
00134   }
00135 }
00136 
00137 } // End namespace Experimental
00138 
00139 template<class ScalarType, class MV, class OP>
00140 class OperatorTraits<ScalarType, Experimental::SaddleContainer<ScalarType,MV>, Experimental::SaddleOperator<ScalarType,MV,OP> >
00141 {
00142 public:
00143   static void Apply( const Experimental::SaddleOperator<ScalarType,MV,OP>& Op, 
00144                      const Experimental::SaddleContainer<ScalarType,MV>& x, 
00145                      Experimental::SaddleContainer<ScalarType,MV>& y)
00146     { Op.Apply( x, y); };
00147 };
00148 
00149 } // end namespace Anasazi
00150 
00151 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends