|
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 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 */
1.7.6.1