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

Generated on Wed May 12 21:45:51 2010 for Belos by  doxygen 1.4.7