|
Belos Version of the Day
|
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 */
1.7.4