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< Teuchos::RCP<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, 
00109       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1);
00110 
00112   StatusTestCombo(ComboType t, 
00113       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1, 
00114       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test2);
00115 
00117   StatusTestCombo<ScalarType,MV,OP>& addStatusTest(const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& add_test);
00118 
00120   virtual ~StatusTestCombo() {};
00122 
00124 
00125   
00127 
00130   StatusType checkStatus( Iteration<ScalarType,MV,OP>* iSolver );
00131 
00133   StatusType getStatus() const { return(status_); };
00134 
00136 
00138 
00139 
00141 
00143   void reset(); 
00144 
00146 
00148 
00149 
00151   ComboType getComboType() const {return(type_);}
00152 
00154   st_vector getStatusTests() {return(tests_);}
00155 
00157 
00159 
00160   
00162   void print(std::ostream& os, int indent = 0) const;
00163   
00165 
00166 protected:
00167 
00169 
00170 
00171   void orOp( Iteration<ScalarType,MV,OP>* iSolver );
00172 
00174   void andOp( Iteration<ScalarType,MV,OP>* iSolver );
00175 
00177   void seqOp( Iteration<ScalarType,MV,OP>* iSolver );
00178 
00181   bool isSafe( const Teuchos:: RCP<StatusTest<ScalarType,MV,OP> >& test1);
00183 
00184  private:
00185 
00187 
00188 
00189   ComboType type_;
00190 
00192   st_vector tests_;
00193 
00195    StatusType status_;
00197 
00198 };
00199 
00200 template <class ScalarType, class MV, class OP>
00201 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t)
00202 {
00203   type_ = t;
00204   status_ = Undefined;
00205 }
00206 
00207 template <class ScalarType, class MV, class OP>
00208 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, 
00209                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1)
00210 {
00211   type_ = t;
00212   tests_.push_back(test1);
00213   status_ = Undefined;
00214 }
00215 
00216 template <class ScalarType, class MV, class OP>
00217 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, 
00218                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1, 
00219                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test2)
00220 {
00221   type_ = t;
00222   tests_.push_back(test1);
00223   addStatusTest(test2);
00224   status_ = Undefined;
00225 }
00226 
00227 template <class ScalarType, class MV, class OP>
00228 StatusTestCombo<ScalarType,MV,OP>& StatusTestCombo<ScalarType,MV,OP>::addStatusTest(const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& add_test)
00229 {
00230   if (isSafe(add_test))
00231     tests_.push_back(add_test);
00232   else
00233     {
00234       const int indent = 2;
00235       std::cout << "\n*** WARNING! ***\n";
00236       std::cout << "This combo test currently consists of the following:\n";
00237       this->print(std::cout, indent);
00238       std::cout << "Unable to add the following test:\n";
00239       add_test->print(std::cout, indent);
00240       std::cout << "\n";
00241     }
00242   return *this;
00243 }
00244 
00245 template <class ScalarType, class MV, class OP>
00246 bool StatusTestCombo<ScalarType,MV,OP>::isSafe( const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1)
00247 {
00248   // Are we trying to add "this" to "this"? This would result in an infinite recursion.
00249   if (test1.get() == this)
00250     return false;
00251   
00252   // Recursively test that we're not adding something that's already
00253   // in the list because that can also lead to infinite recursions.
00254   for (iterator i = tests_.begin(); i != tests_.end(); ++i) {
00255     
00256     StatusTestCombo<ScalarType,MV,OP>* ptr = dynamic_cast<StatusTestCombo<ScalarType,MV,OP> *>(i->get());
00257     if (ptr != NULL)
00258       if (!ptr->isSafe(test1))
00259         return false;
00260   }
00261   return true;
00262 }
00263 
00264 template <class ScalarType, class MV, class OP>
00265 StatusType StatusTestCombo<ScalarType,MV,OP>::checkStatus( Iteration<ScalarType,MV,OP>* iSolver )
00266 {
00267   status_ = Failed;
00268 
00269   if (type_ == OR)
00270     orOp( iSolver );
00271   else if (type_ == AND)
00272     andOp( iSolver );
00273   else
00274     seqOp( iSolver );
00275 
00276   return status_;
00277 }
00278 
00279 template <class ScalarType, class MV, class OP>
00280 void StatusTestCombo<ScalarType,MV,OP>::reset( )
00281 {
00282   // Resets all status tests in my list.
00283   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00284     {
00285       (*i)->reset();
00286     }
00287   // Reset my status.
00288   status_ = Undefined;
00289   //
00290   return;
00291 }
00292 
00293 template <class ScalarType, class MV, class OP>
00294 void StatusTestCombo<ScalarType,MV,OP>::orOp( Iteration<ScalarType,MV,OP>* iSolver )
00295 {
00296   status_ = Failed;
00297 
00298   // Checks the status of each test. The first test it encounters, if
00299   // any, that is unconverged is the status that it sets itself too.
00300   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00301     {
00302       StatusType s = (*i)->checkStatus( iSolver );
00303 
00304       // Check for failure.
00305       if (s==Passed) status_ = Passed;
00306     }
00307 }
00308 
00309 template <class ScalarType, class MV, class OP>
00310 void StatusTestCombo<ScalarType,MV,OP>::andOp( Iteration<ScalarType,MV,OP>* iSolver )
00311 {
00312   bool isFailed = false;
00313   
00314   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00315     
00316     StatusType s = (*i)->checkStatus( iSolver );
00317 
00318     // Check for failure.
00319     if (s==Failed) isFailed = true;
00320 
00321     // If any of the tests are failed, then the AND test is failed.
00322     if (s == Failed) {
00323       status_ = Failed;
00324     }
00325 
00326     // If this is the first test and it's failed, copy its
00327     // status to the combo status.
00328     if ((!isFailed) && (status_ == Failed)) {
00329       status_ = s;
00330     }
00331   }
00332   
00333   // Any failure is a complete failure
00334   if (isFailed) status_ = Failed;
00335   
00336   return;
00337 }
00338 
00339 template <class ScalarType, class MV, class OP>
00340 void StatusTestCombo<ScalarType,MV,OP>::seqOp( Iteration<ScalarType,MV,OP>* iSolver ) 
00341 {
00342   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00343 
00344     StatusType s = (*i)->checkStatus( iSolver );
00345 
00346     // Check for failure.
00347     if (s==Failed) {
00348       status_ = Failed;
00349       return;
00350     }
00351     else if (s==Undefined) {
00352       status_ = s;
00353       return;
00354     }
00355   }
00356   // If we make it here, we have converged
00357   status_ = Passed;
00358 
00359   return;
00360 }
00361 
00362 template <class ScalarType, class MV, class OP>
00363 void StatusTestCombo<ScalarType,MV,OP>::print(std::ostream& os, int indent) const {
00364   for (int j = 0; j < indent; j ++)
00365     os << ' ';
00366   this->printStatus(os, status_);
00367   os << ((type_ == OR) ? "OR" : (type_ == AND) ? "AND" :"SEQ");
00368   os << " Combination";
00369   os << " -> " << std::endl;
00370 
00371   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i)
00372     (*i)->print(os, indent+2);
00373 }
00374 
00375 } // end namespace Belos
00376 
00377 #endif /* BELOS_STATUS_TEST_COMBO_H */

Generated on Tue Jul 13 09:27:03 2010 for Belos by  doxygen 1.4.7