00001 // $Id$ 00002 // $Source$ 00003 00004 //@HEADER 00005 // 00006 //@HEADER 00007 00008 #ifndef NOX_STATUSTEST_SAFECOMBO_H 00009 #define NOX_STATUSTEST_SAFECOMBO_H 00010 00011 #include "NOX_StatusTest_Generic.H" // base class 00012 #include "NOX_Common.H" // class data element (vector) 00013 #include "Teuchos_RefCountPtr.hpp" 00014 00015 namespace NOX { 00016 00017 namespace StatusTest { 00018 00019 /*! 00020 \brief Arbitrary combination of status tests, implemented with safe memory management. 00021 00022 In the \c AND (see NOX::StatusTest::Combo::ComboType) combination, the 00023 result is \c Unconverged (see NOX::StatusTest::StatusType) if \e any of 00024 the tests is \c Unconverged. Otherwise, the result is equal to the 00025 result of the \e first test in the list that is either \c Converged 00026 or \c Failed. It is not recommended to mix \c Converged and \c 00027 Failed tests in an \c AND combination. 00028 00029 In the \c OR combination, the result is \c Unconverged if \e all of 00030 the tests are \c Unconverged. Otherwise, it is the result of the \e 00031 first test in the list that is either \c Converged or \c 00032 Failed. Therefore, it will generally make sense to put the \c Failed 00033 -type tests at the end of the \c OR list. 00034 00035 \note We call checkStatus on \e every convergence test, though some 00036 may be called with the NOX::StatusTest::None option. 00037 00038 \note This is identical in operation to StatusTest::Combo. but stores 00039 the constituent subtests using a reference-counted pointer. This ensures 00040 safe behavior if the constituent subtests go out of scope before the combo. 00041 - KL 24 August 2004. 00042 00043 \author Tammy Kolda (SNL 8950) 00044 \author Kevin Long (SNL 8962) 00045 */ 00046 class SafeCombo : public Generic { 00047 00048 public: 00049 00050 /*! 00051 \brief The test can be either the AND of all the component tests, 00052 or the OR of all the component tests. 00053 */ 00054 enum ComboType { 00055 //! Logically "AND" together the results of the tests in this combination 00056 AND, 00057 //! Logically "OR" together the results of the tests in this combination 00058 OR 00059 }; 00060 00061 //! Constructor 00062 SafeCombo(ComboType t); 00063 00064 //! Constructor with a single test. 00065 SafeCombo(ComboType t, const Teuchos::RCP<Generic>& a); 00066 00067 //! Constructor with two tests. 00068 SafeCombo(ComboType t, const Teuchos::RCP<Generic>& a, 00069 const Teuchos::RCP<Generic>& b); 00070 00071 //! Add another test to this combination. 00072 /*! 00073 Calls isSafe() to determine if it is safe to add \c a to the combination. 00074 */ 00075 virtual SafeCombo& addStatusTest(const Teuchos::RCP<Generic>& a); 00076 00077 //! Destructor 00078 virtual ~SafeCombo(); 00079 00080 /*! 00081 \brief Calls checkStatus(problem, NOX::StatusTest::Minimal) 00082 */ 00083 virtual StatusType checkStatus(const NOX::Solver::Generic& problem); 00084 00085 /*! 00086 \brief Tests stopping criterion. 00087 00088 See addOp() and orOp() for details. 00089 */ 00090 #ifdef TRILINOS_6 00091 virtual StatusType checkStatusEfficiently(const NOX::Solver::Generic& problem, NOX::StatusTest::CheckType checkType); 00092 #else 00093 virtual StatusType checkStatus(const NOX::Solver::Generic& problem, NOX::StatusTest::CheckType checkType); 00094 #endif 00095 00096 virtual StatusType getStatus() const; 00097 00098 virtual ostream& print(std::ostream& stream, int indent = 0) const; 00099 00100 protected: 00101 00102 //! Use this for checkStatus when this is an OR type combo. Updates NOX::StatusTest::Combo::status. 00103 /*! 00104 If there is a combination of NOX::StatusTest::Failed and 00105 NOX::StatusTest::Converged in the tests that are OR'd together, 00106 the value of status for this test is set to the status of the 00107 first test it encounters which is not NOX::Status::Unconvered. The 00108 tests are evaluated in the order that they were added to the 00109 combination. 00110 00111 \note We compute the status of all tests in the combination for 00112 the sake of completeness, even if we could determine the status of 00113 this combination test without that check. 00114 00115 */ 00116 virtual void orOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType); 00117 00118 //! Use this for checkStatus when this is an AND type combo. Updates NOX::StatusTest::Combo::status. 00119 /*! 00120 00121 If any tests are NOX::StatusTest::Unconverged, then the status of 00122 this test is NOX::StatusTest::Unconverged. If there is a 00123 combination of NOX::StatusTest::Failed and 00124 NOX::StatusTest::Converged in the tests that are AND'd together, 00125 the value of status for this test is set to the status of the 00126 first test it encounters. The tests are evaluated in the 00127 order that they were added to the combination. 00128 00129 \note We compute the status of all tests in the combination for 00130 the sake of completeness, even if we could determine the status of 00131 this combination test without that check. 00132 */ 00133 virtual void andOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType); 00134 00135 /*! \brief Check whether or not it is safe to add \c a to this list 00136 of tests. 00137 00138 This is necessary to avoid any infinite recursions 00139 (i.e., a test cannot own a copy of itself). 00140 */ 00141 bool isSafe(const Teuchos::RCP<Generic>& a); 00142 00143 private: 00144 00145 //! Type of test 00146 const ComboType type; 00147 00148 //! Vector of generic status tests 00149 vector<Teuchos::RCP<Generic> > tests; 00150 00151 //! %Status 00152 StatusType status; 00153 00154 }; // class Combo 00155 00156 } // namespace Status 00157 } // namespace NOX 00158 00159 #endif