Belos Version of the Day
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 the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ************************************************************************
00041 //@HEADER
00042 //
00043 
00044 #ifndef BELOS_STATUS_TEST_COMBO_H
00045 #define BELOS_STATUS_TEST_COMBO_H
00046 
00052 #include "BelosStatusTest.hpp"
00053 #include <vector>
00054 
00086 namespace Belos {
00087 
00088 template <class ScalarType, class MV, class OP>
00089 class StatusTestCombo: public StatusTest<ScalarType,MV,OP> {
00090   
00091  public:
00092 
00093 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00094 
00095   typedef std::vector< Teuchos::RCP<StatusTest<ScalarType,MV,OP> > > st_vector;
00096   typedef typename st_vector::iterator iterator;
00097   typedef typename st_vector::const_iterator const_iterator;
00098 
00099 #endif // DOXYGEN_SHOULD_SKIP_THIS
00100   
00102 
00103 
00107   enum ComboType {AND,  
00108       OR,   
00109       SEQ   
00111   };
00113 
00115 
00116 
00118   StatusTestCombo(ComboType t);
00119 
00121   StatusTestCombo(ComboType t, 
00122       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1);
00123 
00125   StatusTestCombo(ComboType t, 
00126       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1, 
00127       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test2);
00128 
00130   StatusTestCombo<ScalarType,MV,OP>& addStatusTest(const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& add_test);
00131 
00133   virtual ~StatusTestCombo() {};
00135 
00137 
00138   
00140 
00143   StatusType checkStatus( Iteration<ScalarType,MV,OP>* iSolver );
00144 
00146   StatusType getStatus() const { return(status_); };
00147 
00149 
00151 
00152 
00154 
00156   void reset(); 
00157 
00159 
00161 
00162 
00164   ComboType getComboType() const {return(type_);}
00165 
00167   st_vector getStatusTests() {return(tests_);}
00168 
00170 
00172 
00173   
00175   void print(std::ostream& os, int indent = 0) const;
00176   
00178 
00179 protected:
00180 
00182 
00183 
00184   void orOp( Iteration<ScalarType,MV,OP>* iSolver );
00185 
00187   void andOp( Iteration<ScalarType,MV,OP>* iSolver );
00188 
00190   void seqOp( Iteration<ScalarType,MV,OP>* iSolver );
00191 
00194   bool isSafe( const Teuchos:: RCP<StatusTest<ScalarType,MV,OP> >& test1);
00196 
00197  private:
00198 
00200 
00201 
00202   ComboType type_;
00203 
00205   st_vector tests_;
00206 
00208    StatusType status_;
00210 
00211 };
00212 
00213 template <class ScalarType, class MV, class OP>
00214 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t)
00215 {
00216   type_ = t;
00217   status_ = Undefined;
00218 }
00219 
00220 template <class ScalarType, class MV, class OP>
00221 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, 
00222                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1)
00223 {
00224   type_ = t;
00225   tests_.push_back(test1);
00226   status_ = Undefined;
00227 }
00228 
00229 template <class ScalarType, class MV, class OP>
00230 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, 
00231                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1, 
00232                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test2)
00233 {
00234   type_ = t;
00235   tests_.push_back(test1);
00236   addStatusTest(test2);
00237   status_ = Undefined;
00238 }
00239 
00240 template <class ScalarType, class MV, class OP>
00241 StatusTestCombo<ScalarType,MV,OP>& StatusTestCombo<ScalarType,MV,OP>::addStatusTest(const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& add_test)
00242 {
00243   if (isSafe(add_test))
00244     tests_.push_back(add_test);
00245   else
00246     {
00247       const int indent = 2;
00248       std::cout << "\n*** WARNING! ***\n";
00249       std::cout << "This combo test currently consists of the following:\n";
00250       this->print(std::cout, indent);
00251       std::cout << "Unable to add the following test:\n";
00252       add_test->print(std::cout, indent);
00253       std::cout << "\n";
00254     }
00255   return *this;
00256 }
00257 
00258 template <class ScalarType, class MV, class OP>
00259 bool StatusTestCombo<ScalarType,MV,OP>::isSafe( const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1)
00260 {
00261   // Are we trying to add "this" to "this"? This would result in an infinite recursion.
00262   if (test1.get() == this)
00263     return false;
00264   
00265   // Recursively test that we're not adding something that's already
00266   // in the list because that can also lead to infinite recursions.
00267   for (iterator i = tests_.begin(); i != tests_.end(); ++i) {
00268     
00269     StatusTestCombo<ScalarType,MV,OP>* ptr = dynamic_cast<StatusTestCombo<ScalarType,MV,OP> *>(i->get());
00270     if (ptr != NULL)
00271       if (!ptr->isSafe(test1))
00272         return false;
00273   }
00274   return true;
00275 }
00276 
00277 template <class ScalarType, class MV, class OP>
00278 StatusType StatusTestCombo<ScalarType,MV,OP>::checkStatus( Iteration<ScalarType,MV,OP>* iSolver )
00279 {
00280   status_ = Failed;
00281 
00282   if (type_ == OR)
00283     orOp( iSolver );
00284   else if (type_ == AND)
00285     andOp( iSolver );
00286   else
00287     seqOp( iSolver );
00288 
00289   return status_;
00290 }
00291 
00292 template <class ScalarType, class MV, class OP>
00293 void StatusTestCombo<ScalarType,MV,OP>::reset( )
00294 {
00295   // Resets all status tests in my list.
00296   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00297     {
00298       (*i)->reset();
00299     }
00300   // Reset my status.
00301   status_ = Undefined;
00302   //
00303   return;
00304 }
00305 
00306 template <class ScalarType, class MV, class OP>
00307 void StatusTestCombo<ScalarType,MV,OP>::orOp( Iteration<ScalarType,MV,OP>* iSolver )
00308 {
00309   status_ = Failed;
00310 
00311   // Checks the status of each test. The first test it encounters, if
00312   // any, that is unconverged is the status that it sets itself too.
00313   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00314     {
00315       StatusType s = (*i)->checkStatus( iSolver );
00316 
00317       // Check for failure.
00318       if (s==Passed) status_ = Passed;
00319     }
00320 }
00321 
00322 template <class ScalarType, class MV, class OP>
00323 void StatusTestCombo<ScalarType,MV,OP>::andOp( Iteration<ScalarType,MV,OP>* iSolver )
00324 {
00325   bool isFailed = false;
00326   
00327   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00328     
00329     StatusType s = (*i)->checkStatus( iSolver );
00330 
00331     // Check for failure.
00332     if (s==Failed) isFailed = true;
00333 
00334     // If any of the tests are failed, then the AND test is failed.
00335     if (s == Failed) {
00336       status_ = Failed;
00337     }
00338 
00339     // If this is the first test and it's failed, copy its
00340     // status to the combo status.
00341     if ((!isFailed) && (status_ == Failed)) {
00342       status_ = s;
00343     }
00344   }
00345   
00346   // Any failure is a complete failure
00347   if (isFailed) status_ = Failed;
00348   
00349   return;
00350 }
00351 
00352 template <class ScalarType, class MV, class OP>
00353 void StatusTestCombo<ScalarType,MV,OP>::seqOp( Iteration<ScalarType,MV,OP>* iSolver ) 
00354 {
00355   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00356 
00357     StatusType s = (*i)->checkStatus( iSolver );
00358 
00359     // Check for failure.
00360     if (s==Failed) {
00361       status_ = Failed;
00362       return;
00363     }
00364     else if (s==Undefined) {
00365       status_ = s;
00366       return;
00367     }
00368   }
00369   // If we make it here, we have converged
00370   status_ = Passed;
00371 
00372   return;
00373 }
00374 
00375 template <class ScalarType, class MV, class OP>
00376 void StatusTestCombo<ScalarType,MV,OP>::print(std::ostream& os, int indent) const {
00377   for (int j = 0; j < indent; j ++)
00378     os << ' ';
00379   this->printStatus(os, status_);
00380   os << ((type_ == OR) ? "OR" : (type_ == AND) ? "AND" :"SEQ");
00381   os << " Combination";
00382   os << " -> " << std::endl;
00383 
00384   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i)
00385     (*i)->print(os, indent+2);
00386 }
00387 
00388 } // end namespace Belos
00389 
00390 #endif /* BELOS_STATUS_TEST_COMBO_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines