BelosStatusTestCombo.hpp

Go to the documentation of this file.
00001 
00002 // @HEADER
00003 // ***********************************************************************
00004 //
00005 //                 Belos: Block Linear Solvers Package
00006 //                 Copyright (2004) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA
00025 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00026 //
00027 // ***********************************************************************
00028 // @HEADER
00029 //
00030 
00031 #ifndef BELOS_STATUS_TEST_COMBO_H
00032 #define BELOS_STATUS_TEST_COMBO_H
00033 
00039 #include "BelosStatusTest.hpp"
00040 #include <vector>
00041 
00073 namespace Belos {
00074 
00075 template <class ScalarType, class MV, class OP>
00076 class StatusTestCombo: public StatusTest<ScalarType,MV,OP> {
00077   
00078  public:
00079 
00080 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00081 
00082   typedef std::vector< StatusTest<ScalarType,MV,OP>* > st_vector;
00083   typedef typename st_vector::iterator iterator;
00084   typedef typename st_vector::const_iterator const_iterator;
00085 
00086 #endif // DOXYGEN_SHOULD_SKIP_THIS
00087   
00089 
00090 
00094   enum ComboType {AND,  
00095       OR,   
00096       SEQ   
00098   };
00100 
00102 
00103 
00105   StatusTestCombo(ComboType t);
00106 
00108   StatusTestCombo(ComboType t, StatusTest<ScalarType,MV,OP>& test1);
00109 
00111   StatusTestCombo(ComboType t, StatusTest<ScalarType,MV,OP>& test1, StatusTest<ScalarType,MV,OP>& test2);
00112 
00114   StatusTestCombo<ScalarType,MV,OP>& AddStatusTest(StatusTest<ScalarType,MV,OP>& add_test);
00115 
00117   virtual ~StatusTestCombo() {};
00119 
00121 
00122   
00124 
00127   StatusType CheckStatus( IterativeSolver<ScalarType,MV,OP>* iSolver );
00128 
00130   StatusType GetStatus() const { return(status_); };
00131 
00133 
00135 
00136 
00138 
00140   void Reset(); 
00141 
00143 
00145 
00146 
00148   ComboType GetComboType() const {return(type_);};
00149 
00151 
00153 
00154 
00156 
00159   bool ResidualVectorRequired() const;
00160 
00162 
00163 
00164   
00166   ostream& Print(ostream& os, int indent = 0) const;
00167   
00169 
00170 protected:
00171 
00173 
00174 
00175   void OrOp( IterativeSolver<ScalarType,MV,OP>* iSolver );
00176 
00178   void AndOp( IterativeSolver<ScalarType,MV,OP>* iSolver );
00179 
00181   void SeqOp( IterativeSolver<ScalarType,MV,OP>* iSolver );
00182 
00185   bool IsSafe(StatusTest<ScalarType,MV,OP>& test1);
00187 
00188  private:
00189 
00191 
00192 
00193   ComboType type_;
00194 
00196   st_vector tests_;
00197 
00199    StatusType status_;
00201 
00202 };
00203 
00204 template <class ScalarType, class MV, class OP>
00205 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t)
00206 {
00207   type_ = t;
00208   status_ = Unchecked;
00209 }
00210 
00211 template <class ScalarType, class MV, class OP>
00212 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, StatusTest<ScalarType,MV,OP>& test1)
00213 {
00214   type_ = t;
00215   tests_.push_back(&test1);
00216   status_ = Unchecked;
00217 }
00218 
00219 template <class ScalarType, class MV, class OP>
00220 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, StatusTest<ScalarType,MV,OP>& test1, StatusTest<ScalarType,MV,OP>& test2)
00221 {
00222   type_ = t;
00223   tests_.push_back(&test1);
00224   AddStatusTest(test2);
00225   status_ = Unchecked;
00226 }
00227 
00228 template <class ScalarType, class MV, class OP>
00229 StatusTestCombo<ScalarType,MV,OP>& StatusTestCombo<ScalarType,MV,OP>::AddStatusTest(StatusTest<ScalarType,MV,OP>& add_test)
00230 {
00231   if (IsSafe(add_test))
00232     tests_.push_back(&add_test);
00233   else
00234     {
00235       const int indent = 2;
00236       cout << "\n*** WARNING! ***\n";
00237       cout << "This combo test currently consists of the following:\n";
00238       this->Print(cout, indent);
00239       cout << "Unable to add the following test:\n";
00240       add_test.Print(cout, indent);
00241       cout << "\n";
00242     }
00243   return *this;
00244 }
00245 
00246 template <class ScalarType, class MV, class OP>
00247 bool StatusTestCombo<ScalarType,MV,OP>::IsSafe(StatusTest<ScalarType,MV,OP>& test1)
00248 {
00249   // Are we trying to add "this" to "this"? This would result in an infinite recursion.
00250   if (&test1 == this)
00251     return false;
00252   
00253   // Recursively test that we're not adding something that's already
00254   // in the list because that can also lead to infinite recursions.
00255   for (iterator i = tests_.begin(); i != tests_.end(); ++i) {
00256     
00257     StatusTestCombo<ScalarType,MV,OP>* ptr = dynamic_cast< StatusTestCombo<ScalarType,MV,OP> *>(*i);
00258     if (ptr != NULL)
00259       if (!ptr->IsSafe(test1))
00260         return false;
00261   }
00262   return true;
00263 }
00264 
00265 template <class ScalarType, class MV, class OP>
00266 bool StatusTestCombo<ScalarType,MV,OP>::ResidualVectorRequired() const
00267 {
00268   // If any of the StatusTest object require the residual vector, then return true.
00269   
00270   // Recursively test this property.
00271   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00272     
00273     StatusTest<ScalarType,MV,OP>* ptr = dynamic_cast< StatusTest<ScalarType,MV,OP> *>(*i);
00274     if (ptr != NULL)
00275       if (ptr->ResidualVectorRequired())
00276         return true;
00277   }
00278   
00279   // Otherwise we don't need residual vector.
00280   return false;
00281 }
00282 
00283 template <class ScalarType, class MV, class OP>
00284 StatusType StatusTestCombo<ScalarType,MV,OP>::CheckStatus( IterativeSolver<ScalarType,MV,OP>* iSolver )
00285 {
00286   status_ = Unconverged;
00287 
00288   if (type_ == OR)
00289     OrOp( iSolver );
00290   else if (type_ == AND)
00291     AndOp( iSolver );
00292   else
00293     SeqOp( iSolver );
00294 
00295   return status_;
00296 }
00297 
00298 template <class ScalarType, class MV, class OP>
00299 void StatusTestCombo<ScalarType,MV,OP>::Reset( )
00300 {
00301   // Resets all status tests in my list.
00302   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00303     {
00304       (*i)->Reset();
00305     }
00306   // Reset my status.
00307   status_ = Unchecked;
00308   //
00309   return;
00310 }
00311 
00312 template <class ScalarType, class MV, class OP>
00313 void StatusTestCombo<ScalarType,MV,OP>::OrOp( IterativeSolver<ScalarType,MV,OP>* iSolver )
00314 {
00315   bool isFailed = false;
00316 
00317   // Checks the status of each test. The first test it encounters, if
00318   // any, that is unconverged is the status that it sets itself too.
00319   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00320     {
00321       StatusType s = (*i)->CheckStatus( iSolver );
00322       
00323       // Check for failure and NaN.  Combo treats NaNs as Fails
00324       if (s==Failed || s==NaN) isFailed = true;
00325       
00326       if ((status_ == Unconverged) && (s != Unconverged)) {
00327   status_ = s;
00328       }      
00329     }
00330   
00331   // Any failure is a complete failure
00332   if (isFailed) status_ = Failed;
00333   
00334   return;
00335 }
00336 
00337 template <class ScalarType, class MV, class OP>
00338 void StatusTestCombo<ScalarType,MV,OP>::AndOp( IterativeSolver<ScalarType,MV,OP>* iSolver )
00339 {
00340   bool isUnconverged = false;
00341   bool isFailed = false;
00342   
00343   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00344     
00345     StatusType s = (*i)->CheckStatus( iSolver );
00346 
00347     // Check for failure and NaN.  Combo treats NaNs as Fails
00348     if (s==Failed || s==NaN) isFailed = true;
00349 
00350     // If any of the tests are unconverged, then the AND test is
00351     // unconverged.
00352     if (s == Unconverged) {
00353       isUnconverged = true;
00354       status_ = Unconverged;
00355     }
00356 
00357     // If this is the first test and it's converged/failed, copy its
00358     // status to the combo status.
00359     if ((!isUnconverged) && (status_ == Unconverged)) {
00360       status_ = s;
00361     }
00362   }
00363   
00364   // Any failure is a complete failure
00365   if (isFailed) status_ = Failed;
00366   
00367   return;
00368 }
00369 
00370 template <class ScalarType, class MV, class OP>
00371 void StatusTestCombo<ScalarType,MV,OP>::SeqOp( IterativeSolver<ScalarType,MV,OP>* iSolver ) 
00372 {
00373   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00374 
00375     StatusType s = (*i)->CheckStatus( iSolver );
00376 
00377     // Check for failure and NaN.  Combo treats NaNs as Fails
00378     if (s==Failed || s==NaN) {
00379       status_ = Failed;
00380       return;
00381     }
00382     else if (s==Unconverged) {
00383       status_ = s;
00384       return;
00385     }
00386   }
00387   // If we make it here, we have converged
00388   status_ = Converged;
00389 
00390   return;
00391 }
00392 
00393 template <class ScalarType, class MV, class OP>
00394 ostream& StatusTestCombo<ScalarType,MV,OP>::Print(ostream& os, int indent) const {
00395   for (int j = 0; j < indent; j ++)
00396     os << ' ';
00397   this->PrintStatus(os, status_);
00398   os << ((type_ == OR) ? "OR" : (type_ == AND) ? "AND" :"SEQ");
00399   os << " Combination";
00400   os << " -> " << endl;
00401 
00402   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i)
00403     (*i)->Print(os, indent+2);
00404 
00405   return os;
00406 }
00407 
00408 } // end namespace Belos
00409 
00410 #endif /* BELOS_STATUS_TEST_COMBO_H */

Generated on Thu Sep 18 12:30:12 2008 for Belos by doxygen 1.3.9.1