NOX_StatusTest_SafeCombo.cpp

00001 // $Id$ 
00002 // $Source$ 
00003 
00004 //@HEADER
00005 //   
00006 //@HEADER
00007 
00008 #include "PlayaDefs.hpp"
00009 #include "NOX_StatusTest_SafeCombo.hpp"
00010 #include "NOX_Utils.H"
00011 
00012 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t) :
00013   type(t)
00014 {
00015   status = Unevaluated;
00016 }
00017 
00018 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t, 
00019                                       const Teuchos::RCP<Generic>& a) :
00020   type(t)
00021 {
00022   tests.push_back(a);
00023   status = Unevaluated;
00024 }
00025 
00026 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t, 
00027                                       const Teuchos::RCP<Generic>& a, 
00028                                       const Teuchos::RCP<Generic>& b) :
00029   type(t)
00030 {
00031   tests.push_back(a);
00032   addStatusTest(b);
00033   status = Unevaluated;
00034 }
00035 
00036 NOX::StatusTest::SafeCombo& NOX::StatusTest::SafeCombo::addStatusTest(const Teuchos::RCP<Generic>& a)
00037 {
00038   if (isSafe(a))
00039     tests.push_back(a);
00040   else 
00041   {
00042     const int indent = 2;
00043     cout << "\n*** WARNING! ***\n";
00044     cout << "This combo test currently consists of the following:\n";
00045     this->print(cout, indent);
00046     cout << "Unable to add the following test:\n";
00047     a->print(cout, indent);
00048     cout << "\n";
00049   }
00050   return *this;
00051 }
00052 
00053 bool NOX::StatusTest::SafeCombo::isSafe(const Teuchos::RCP<Generic>& a)
00054 {
00055   // Are we trying to add "this" to "this"? This would result in an infinite recursion.
00056   if (a.get() == this)
00057     return false;
00058   
00059   // Recursively test that we're not adding something that's already
00060   // in the list because that can also lead to infinite recursions.
00061   for (vector<Teuchos::RCP<Generic> >::iterator i = tests.begin(); 
00062        i != tests.end(); ++i) 
00063   {
00064     
00065     SafeCombo* ptr = dynamic_cast<SafeCombo*>((*i).get());
00066     if (ptr != NULL)
00067       if (!ptr->isSafe(a))
00068   return false;
00069   }
00070 
00071   // Otherwise, it's safe to add a to the list.
00072   return true;
00073 }
00074 
00075 NOX::StatusTest::SafeCombo::~SafeCombo()
00076 {
00077 }
00078 
00079 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo::checkStatus(const Solver::Generic& problem)
00080 {
00081 #ifdef TRILINOS_6
00082   return checkStatusEfficiently(problem, NOX::StatusTest::Minimal);
00083 #else
00084   return checkStatus(problem, NOX::StatusTest::Minimal);
00085 #endif
00086 }
00087 
00088 #ifdef TRILINOS_6
00089 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo
00090 ::checkStatusEfficiently(const Solver::Generic& problem, 
00091                          NOX::StatusTest::CheckType checkType)
00092 #else
00093 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo
00094 ::checkStatus(const Solver::Generic& problem, 
00095               NOX::StatusTest::CheckType checkType)
00096 #endif
00097 {
00098   if (type == OR)
00099     orOp(problem, checkType);
00100   else
00101     andOp(problem, checkType);
00102 
00103   return status;
00104 }
00105 
00106 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo::getStatus() const
00107 {
00108   return status;
00109 }
00110 
00111 void NOX::StatusTest::SafeCombo::orOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType)
00112 {
00113   if (checkType == NOX::StatusTest::None)
00114     status = Unevaluated;
00115   else
00116     status = Unconverged;
00117 
00118   // Checks the status of each test. The first test it encounters, if
00119   // any, that is unconverged is the status that it sets itself too.
00120   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) 
00121   {
00122 #ifdef TRILINOS_6
00123     NOX::StatusTest::StatusType s = (*i)->checkStatusEfficiently(problem, checkType);
00124 #else
00125     NOX::StatusTest::StatusType s = (*i)->checkStatus(problem, checkType);
00126 #endif
00127     if ((status == Unconverged) && (s != Unconverged)) 
00128     {
00129       status = s;
00130 
00131       // Turn off checking for the remaining tests
00132       if (checkType == NOX::StatusTest::Minimal)
00133         checkType = NOX::StatusTest::None;
00134     }
00135 
00136   }
00137 
00138   return;
00139 }
00140 
00141 void NOX::StatusTest::SafeCombo::andOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType)
00142 {
00143   if (checkType == NOX::StatusTest::None)
00144     status = Unevaluated;
00145   else
00146     status = Unconverged;
00147 
00148   bool isUnconverged = false;
00149 
00150   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) {
00151 
00152 
00153 #ifdef TRILINOS_6
00154     NOX::StatusTest::StatusType s = (*i)->checkStatusEfficiently(problem, checkType);
00155 #else
00156     NOX::StatusTest::StatusType s = (*i)->checkStatus(problem, checkType);
00157 #endif
00158 
00159     // If any of the tests are unconverged, then the AND test is
00160     // unconverged.
00161     if (s == Unconverged) 
00162     {
00163       isUnconverged = true;
00164       status = Unconverged;
00165 
00166       // Turn off checking for the remaining tests
00167       if (checkType == NOX::StatusTest::Minimal)
00168   checkType = NOX::StatusTest::None;
00169     }
00170 
00171     // If this is the first test and it's converged/failed, copy its
00172     // status to the combo status.
00173     if ((!isUnconverged) && (status == Unconverged)) 
00174     {
00175       status = s;
00176     }
00177 
00178   }
00179 
00180   return;
00181 }
00182 
00183 
00184 ostream& NOX::StatusTest::SafeCombo::print(std::ostream& stream, int indent) const
00185 {
00186   for (int j = 0; j < indent; j ++)
00187     stream << ' ';
00188 //   stream << setiosflags(ios::left) << setw(13) << setfill('.');
00189 //   if (status == Unconverged) 
00190 //     stream << "**";
00191 //   else if (status == Failed)
00192 //     stream << "Failed";
00193 //   else
00194 //     stream << "Converged";
00195   stream << status;
00196   stream << ((type == OR) ? "OR" : "AND");
00197   stream << " Combination";
00198   stream << " -> " << std::endl;
00199 
00200   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) 
00201     (*i)->print(stream, indent+2);
00202     
00203   return stream;
00204 }

doxygen