|
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., 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
1.7.6.1