Belos Package Browser (Single Doxygen Collection) Development
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 
00088 namespace Belos {
00089 
00090 template <class ScalarType, class MV, class OP>
00091 class StatusTestCombo: public StatusTest<ScalarType,MV,OP> {
00092   
00093  public:
00094 
00095 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00096 
00097   typedef std::vector< Teuchos::RCP<StatusTest<ScalarType,MV,OP> > > st_vector;
00098   typedef typename st_vector::iterator iterator;
00099   typedef typename st_vector::const_iterator const_iterator;
00100 
00101 #endif // DOXYGEN_SHOULD_SKIP_THIS
00102   
00104 
00105 
00109   enum ComboType {AND,  
00110       OR,   
00111       SEQ   
00113   };
00115 
00117 
00118 
00120   StatusTestCombo(ComboType t);
00121 
00123   StatusTestCombo(ComboType t, 
00124       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1);
00125 
00127   StatusTestCombo(ComboType t, 
00128       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1, 
00129       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test2);
00130 
00134   StatusTestCombo<ScalarType,MV,OP>& addStatusTest(const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& add_test);
00135 
00137   virtual ~StatusTestCombo() {};
00139 
00141 
00142   
00148   StatusType checkStatus( Iteration<ScalarType,MV,OP>* iSolver );
00149 
00153   StatusType getStatus() const { return(status_); };
00154 
00156 
00158 
00159 
00161 
00163   void reset(); 
00164 
00166 
00168 
00169 
00171   ComboType getComboType() const { return type_; }
00172 
00174   st_vector getStatusTests() { return tests_; }
00175 
00177 
00179 
00180   
00182   void print(std::ostream& os, int indent = 0) const;
00183   
00185 
00186 protected:
00187 
00189 
00190 
00191   void orOp( Iteration<ScalarType,MV,OP>* iSolver );
00192 
00194   void andOp( Iteration<ScalarType,MV,OP>* iSolver );
00195 
00197   void seqOp( Iteration<ScalarType,MV,OP>* iSolver );
00198 
00201   bool isSafe( const Teuchos:: RCP<StatusTest<ScalarType,MV,OP> >& test1);
00203 
00204  private:
00205 
00207 
00208 
00209   ComboType type_;
00210 
00212   st_vector tests_;
00213 
00215   StatusType status_;
00217 
00218 };
00219 
00220 template <class ScalarType, class MV, class OP>
00221 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t)
00222 {
00223   type_ = t;
00224   status_ = Undefined;
00225 }
00226 
00227 template <class ScalarType, class MV, class OP>
00228 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, 
00229                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1)
00230 {
00231   type_ = t;
00232   tests_.push_back(test1);
00233   status_ = Undefined;
00234 }
00235 
00236 template <class ScalarType, class MV, class OP>
00237 StatusTestCombo<ScalarType,MV,OP>::StatusTestCombo(ComboType t, 
00238                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1, 
00239                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test2)
00240 {
00241   type_ = t;
00242   tests_.push_back(test1);
00243   addStatusTest(test2);
00244   status_ = Undefined;
00245 }
00246 
00247 template <class ScalarType, class MV, class OP>
00248 StatusTestCombo<ScalarType,MV,OP>& StatusTestCombo<ScalarType,MV,OP>::addStatusTest(const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& add_test)
00249 {
00250   if (isSafe(add_test))
00251     tests_.push_back(add_test);
00252   else
00253     {
00254       const int indent = 2;
00255       std::cout << "\n*** WARNING! ***\n";
00256       std::cout << "This combo test currently consists of the following:\n";
00257       this->print(std::cout, indent);
00258       std::cout << "Unable to add the following test:\n";
00259       add_test->print(std::cout, indent);
00260       std::cout << "\n";
00261     }
00262   return *this;
00263 }
00264 
00265 template <class ScalarType, class MV, class OP>
00266 bool StatusTestCombo<ScalarType,MV,OP>::isSafe( const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& test1)
00267 {
00268   // Are we trying to add "this" to "this"? This would result in an infinite recursion.
00269   if (test1.get() == this)
00270     return false;
00271   
00272   // Recursively test that we're not adding something that's already
00273   // in the list because that can also lead to infinite recursions.
00274   for (iterator i = tests_.begin(); i != tests_.end(); ++i) {
00275     
00276     StatusTestCombo<ScalarType,MV,OP>* ptr = dynamic_cast<StatusTestCombo<ScalarType,MV,OP> *>(i->get());
00277     if (ptr != NULL)
00278       if (!ptr->isSafe(test1))
00279         return false;
00280   }
00281   return true;
00282 }
00283 
00284 template <class ScalarType, class MV, class OP>
00285 StatusType StatusTestCombo<ScalarType,MV,OP>::checkStatus( Iteration<ScalarType,MV,OP>* iSolver )
00286 {
00287   status_ = Failed;
00288 
00289   if (type_ == OR)
00290     orOp( iSolver );
00291   else if (type_ == AND)
00292     andOp( iSolver );
00293   else
00294     seqOp( iSolver );
00295 
00296   return status_;
00297 }
00298 
00299 template <class ScalarType, class MV, class OP>
00300 void StatusTestCombo<ScalarType,MV,OP>::reset( )
00301 {
00302   // Resets all status tests in my list.
00303   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00304     {
00305       (*i)->reset();
00306     }
00307   // Reset my status.
00308   status_ = Undefined;
00309   //
00310   return;
00311 }
00312 
00313 template <class ScalarType, class MV, class OP>
00314 void StatusTestCombo<ScalarType,MV,OP>::orOp( Iteration<ScalarType,MV,OP>* iSolver )
00315 {
00316   status_ = Failed;
00317 
00318   // Checks the status of each test. The first test it encounters, if
00319   // any, that is unconverged is the status that it sets itself too.
00320   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) 
00321     {
00322       StatusType s = (*i)->checkStatus( iSolver );
00323 
00324       // Check for failure.
00325       if (s==Passed) status_ = Passed;
00326     }
00327 }
00328 
00329 template <class ScalarType, class MV, class OP>
00330 void StatusTestCombo<ScalarType,MV,OP>::andOp( Iteration<ScalarType,MV,OP>* iSolver )
00331 {
00332   bool isFailed = false;
00333   
00334   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00335     
00336     StatusType s = (*i)->checkStatus( iSolver );
00337 
00338     // Check for failure.
00339     if (s==Failed) isFailed = true;
00340 
00341     // If any of the tests are failed, then the AND test is failed.
00342     if (s == Failed) {
00343       status_ = Failed;
00344     }
00345 
00346     // If this is the first test and it's failed, copy its
00347     // status to the combo status.
00348     if ((!isFailed) && (status_ == Failed)) {
00349       status_ = s;
00350     }
00351   }
00352   
00353   // Any failure is a complete failure
00354   if (isFailed) status_ = Failed;
00355   
00356   return;
00357 }
00358 
00359 template <class ScalarType, class MV, class OP>
00360 void StatusTestCombo<ScalarType,MV,OP>::seqOp( Iteration<ScalarType,MV,OP>* iSolver ) 
00361 {
00362   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i) {
00363 
00364     StatusType s = (*i)->checkStatus( iSolver );
00365 
00366     // Check for failure.
00367     if (s==Failed) {
00368       status_ = Failed;
00369       return;
00370     }
00371     else if (s==Undefined) {
00372       status_ = s;
00373       return;
00374     }
00375   }
00376   // If we make it here, we have converged
00377   status_ = Passed;
00378 
00379   return;
00380 }
00381 
00382 template <class ScalarType, class MV, class OP>
00383 void StatusTestCombo<ScalarType,MV,OP>::print(std::ostream& os, int indent) const {
00384   for (int j = 0; j < indent; j ++)
00385     os << ' ';
00386   this->printStatus(os, status_);
00387   os << ((type_ == OR) ? "OR" : (type_ == AND) ? "AND" :"SEQ");
00388   os << " Combination";
00389   os << " -> " << std::endl;
00390 
00391   for (const_iterator i = tests_.begin(); i != tests_.end(); ++i)
00392     (*i)->print(os, indent+2);
00393 }
00394 
00395 } // end namespace Belos
00396 
00397 #endif /* BELOS_STATUS_TEST_COMBO_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines