Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
AnasaziStatusTestSpecTrans.hpp
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 
00029 #ifndef ANASAZI_STATUS_TEST_SPECTRANS_HPP
00030 #define ANASAZI_STATUS_TEST_SPECTRANS_HPP
00031 
00032 #include "AnasaziTypes.hpp"
00033 #include "AnasaziStatusTestResNorm.hpp"
00034 #include "AnasaziTraceMinBase.hpp"
00035 
00036 using Teuchos::RCP;
00037 
00038 namespace Anasazi {
00039 namespace Experimental {
00040 
00041   template<class ScalarType, class MV, class OP>
00042   class StatusTestSpecTrans : public StatusTest<ScalarType,MV,OP> {
00043 
00044   typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00045   typedef MultiVecTraits<ScalarType,MV>                             MVT;
00046   typedef OperatorTraits<ScalarType,MV,OP>                          OPT;
00047 
00048   public:
00049 
00050     // Constructor
00051     StatusTestSpecTrans(MagnitudeType tol, int quorum = -1, ResType whichNorm = RES_2NORM, bool scaled = true, bool throwExceptionOnNan = true, const RCP<const OP> Mop = Teuchos::null);
00052     
00053     // Destructor
00054     virtual ~StatusTestSpecTrans() {};
00055 
00056     // Check whether the test passed or failed
00057     TestStatus checkStatus(Eigensolver<ScalarType,MV,OP> *solver);
00058 
00059     // Return the result of the most recent checkStatus call
00060     TestStatus getStatus() const { return state_; }
00061 
00062     // Get the indices for the vectors that passed the test
00063     std::vector<int> whichVecs() const { return ind_; }
00064 
00065     // Get the number of vectors that passed the test
00066     int howMany() const { return ind_.size(); }
00067 
00068     void setQuorum(int quorum) const {
00069       state_ = Undefined;
00070       quorum_ = quorum;
00071     }
00072 
00073     int getQuorum() const { return quorum_; }
00074 
00075     void setTolerance(MagnitudeType tol)
00076     {
00077       state_ = Undefined;
00078       tol_ = tol;
00079     }
00080 
00081     MagnitudeType getTolerance() const { return tol_; }
00082 
00083     void setWhichNorm(ResType whichNorm)
00084     {
00085       state_ = Undefined;
00086       whichNorm_ = whichNorm;
00087     }
00088 
00089     ResType getWhichNorm() const { return whichNorm_; }
00090 
00091     void setScale(bool relscale)
00092     {
00093       state_ = Undefined;
00094       scaled_ = relscale;
00095     }
00096 
00097     bool getScale() const { return scaled_; }
00098 
00099     // Informs the status test that it should reset its internal configuration to the uninitialized state
00100     void reset()
00101     {
00102       ind_.resize(0);
00103       state_ = Undefined;
00104     }
00105 
00106     // Clears the results of the last status test
00107     void clearStatus() { reset(); };
00108 
00109     // Output formatted description of stopping test to output stream
00110     std::ostream & print(std::ostream &os, int indent=0) const;
00111 
00112   private:
00113     TestStatus state_;
00114     MagnitudeType tol_;
00115     std::vector<int> ind_;
00116     int quorum_;
00117     bool scaled_;
00118     enum ResType whichNorm_;
00119     bool throwExceptionOnNaN_;
00120     RCP<const OP> M_;
00121 
00122     const MagnitudeType ONE;  
00123   };
00124 
00125 
00126 
00127   template <class ScalarType, class MV, class OP>
00128   StatusTestSpecTrans<ScalarType,MV,OP>::StatusTestSpecTrans(MagnitudeType tol, int quorum, ResType whichNorm, bool scaled, bool throwExceptionOnNaN, const RCP<const OP> Mop)
00129   : state_(Undefined), 
00130     tol_(tol), 
00131     quorum_(quorum), 
00132     scaled_(scaled), 
00133     whichNorm_(whichNorm), 
00134     throwExceptionOnNaN_(throwExceptionOnNaN),
00135     M_(Mop),
00136     ONE(Teuchos::ScalarTraits<MagnitudeType>::one())
00137   {}
00138 
00139 
00140 
00141   template <class ScalarType, class MV, class OP>
00142   TestStatus StatusTestSpecTrans<ScalarType,MV,OP>::checkStatus( Eigensolver<ScalarType,MV,OP>* solver )
00143   {
00144     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00145     typedef TraceMinBase<ScalarType,MV,OP>       TS;
00146 
00147     // Cast the eigensolver to a TraceMin solver
00148     // Throw an exception if this fails
00149     TS* tm_solver = dynamic_cast<TS*>(solver);
00150     TEUCHOS_TEST_FOR_EXCEPTION(tm_solver == 0, std::invalid_argument, "The status test for spectral transformations currently only works for the trace minimization eigensolvers.  Sorry!");
00151 
00152     // Get the residual Ax-\lambda Bx, which is not computed when there's a spectral transformation
00153     // TraceMin computes Bx-1/\lambda Ax
00154     TraceMinBaseState<ScalarType,MV> state = tm_solver->getState();
00155 
00156     size_t nvecs = state.ritzShifts->size();
00157     std::vector<int> curind(nvecs);
00158     for(size_t i=0; i<nvecs; i++)
00159       curind[i] = i;
00160 
00161     RCP<const MV> locKX, locMX, locX;
00162     RCP<MV> R;
00163     locX = MVT::CloneView(*state.X,curind);
00164     if(state.KX != Teuchos::null)
00165       locKX = MVT::CloneView(*state.KX,curind);
00166     else
00167       locKX = locX;
00168     if(state.MX != Teuchos::null)
00169       locMX = MVT::CloneView(*state.MX,curind);
00170     else
00171       locMX = locX;
00172     R = MVT::CloneCopy(*locKX,curind);
00173 
00174     std::vector<MagnitudeType> evals(nvecs);
00175     for(size_t i=0; i<nvecs; i++)
00176       evals[i] = ONE/(*state.T)[i];
00177     MVT::MvScale(*R,evals);
00178     MVT::MvAddMv(-ONE,*R,ONE,*locMX,*R);
00179 
00180     // Compute the norms
00181     std::vector<MagnitudeType> res(nvecs);
00182     switch (whichNorm_) {
00183       case RES_2NORM:
00184       {
00185         MVT::MvNorm(*R,res);
00186         break;
00187       }
00188       case RES_ORTH:
00189       {
00190         RCP<MV> MR = MVT::Clone(*R,nvecs);
00191         OPT::Apply(*M_,*R,*MR);
00192         MVT::MvDot(*R,*MR,res);
00193         for(size_t i=0; i<nvecs; i++)
00194           res[i] = MT::squareroot(res[i]);
00195         break;
00196       }
00197       case RITZRES_2NORM:
00198       {
00199         TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The trace minimization solvers do not define a Ritz residual.  Please choose a different residual type");
00200         break;
00201       }
00202     }
00203 
00204     // if appropriate, scale the norms by the magnitude of the eigenvalue estimate
00205     if(scaled_)
00206     {
00207       for(size_t i=0; i<nvecs; i++)
00208         res[i] /= std::abs(evals[i]);
00209     }
00210 
00211     // test the norms
00212     ind_.resize(0);
00213     for(size_t i=0; i<nvecs; i++)
00214     {
00215       TEUCHOS_TEST_FOR_EXCEPTION( MT::isnaninf(res[i]), ResNormNaNError,
00216        "StatusTestSpecTrans::checkStatus(): residual norm is nan or inf" );
00217       if(res[i] < tol_) 
00218         ind_.push_back(i);
00219     }
00220     int have = ind_.size();
00221     int need = (quorum_ == -1) ? nvecs : quorum_;
00222     state_ = (have >= need) ? Passed : Failed;
00223     return state_;
00224   }
00225 
00226 
00227 
00228   template <class ScalarType, class MV, class OP>
00229   std::ostream& StatusTestSpecTrans<ScalarType,MV,OP>::print(std::ostream& os, int indent) const
00230   {
00231     std::string ind(indent,' ');
00232     os << ind << "- StatusTestSpecTrans: ";
00233     switch (state_) {
00234       case Passed:
00235         os << "Passed\n";
00236         break;
00237       case Failed:
00238         os << "Failed\n";
00239         break;
00240       case Undefined:
00241         os << "Undefined\n";
00242         break;
00243     }
00244     os << ind << "  (Tolerance, WhichNorm,Scaled,Quorum): "
00245        << "(" << tol_;
00246     switch (whichNorm_) {
00247       case RES_ORTH:
00248         os << ",RES_ORTH";
00249         break;
00250       case RES_2NORM:
00251         os << ",RES_2NORM";
00252         break;
00253       case RITZRES_2NORM:
00254         os << ",RITZRES_2NORM";
00255         break;
00256     }
00257     os << "," << (scaled_ ? "true" : "false")
00258        << "," << quorum_
00259        << ")\n";
00260 
00261     if (state_ != Undefined) {
00262       os << ind << "  Which vectors: ";
00263       if (ind_.size() > 0) {
00264         for(size_t i=0; i<ind_.size(); i++) os << ind_[i] << " ";
00265         os << std::endl;
00266       }
00267       else
00268         os << "[empty]\n";
00269     }
00270     return os;
00271   }
00272 
00273 }} // end of namespace
00274 
00275 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends