NOX_StatusTest_SafeCombo.C
Go to the documentation of this file.
00001 // $Id$ 
00002 // $Source$ 
00003 
00004 //@HEADER
00005 // ************************************************************************
00006 // 
00007 //            NOX: An Object-Oriented Nonlinear Solver Package
00008 //                 Copyright (2002) Sandia Corporation
00009 // 
00010 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00011 // license for use of this work by or on behalf of the U.S. Government.
00012 // 
00013 // This library is free software; you can redistribute it and/or modify
00014 // it under the terms of the GNU Lesser General Public License as
00015 // published by the Free Software Foundation; either version 2.1 of the
00016 // License, or (at your option) any later version.
00017 //  
00018 // This library is distributed in the hope that it will be useful, but
00019 // WITHOUT ANY WARRANTY; without even the implied warranty of
00020 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021 // Lesser General Public License for more details.
00022 //                                                                                 
00023 // You should have received a copy of the GNU Lesser General Public
00024 // License along with this library; if not, write to the Free Software
00025 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00026 // USA                                                                                
00027 // Questions? Contact Tammy Kolda (tgkolda@sandia.gov) or Roger Pawlowski
00028 // (rppawlo@sandia.gov), Sandia National Laboratories.
00029 // 
00030 // ************************************************************************
00031 //@HEADER
00032 
00033 #include "SundanceDefs.hpp"
00034 #include "NOX_StatusTest_SafeCombo.H"
00035 #include "NOX_Utils.H"
00036 
00037 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t) :
00038   type(t)
00039 {
00040   status = Unevaluated;
00041 }
00042 
00043 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t, 
00044                                       const Teuchos::RCP<Generic>& a) :
00045   type(t)
00046 {
00047   tests.push_back(a);
00048   status = Unevaluated;
00049 }
00050 
00051 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t, 
00052                                       const Teuchos::RCP<Generic>& a, 
00053                                       const Teuchos::RCP<Generic>& b) :
00054   type(t)
00055 {
00056   tests.push_back(a);
00057   addStatusTest(b);
00058   status = Unevaluated;
00059 }
00060 
00061 NOX::StatusTest::SafeCombo& NOX::StatusTest::SafeCombo::addStatusTest(const Teuchos::RCP<Generic>& a)
00062 {
00063   if (isSafe(a))
00064     tests.push_back(a);
00065   else 
00066   {
00067     const int indent = 2;
00068     cout << "\n*** WARNING! ***\n";
00069     cout << "This combo test currently consists of the following:\n";
00070     this->print(cout, indent);
00071     cout << "Unable to add the following test:\n";
00072     a->print(cout, indent);
00073     cout << "\n";
00074   }
00075   return *this;
00076 }
00077 
00078 bool NOX::StatusTest::SafeCombo::isSafe(const Teuchos::RCP<Generic>& a)
00079 {
00080   // Are we trying to add "this" to "this"? This would result in an infinite recursion.
00081   if (a.get() == this)
00082     return false;
00083   
00084   // Recursively test that we're not adding something that's already
00085   // in the list because that can also lead to infinite recursions.
00086   for (vector<Teuchos::RCP<Generic> >::iterator i = tests.begin(); 
00087        i != tests.end(); ++i) 
00088   {
00089     
00090     SafeCombo* ptr = dynamic_cast<SafeCombo*>((*i).get());
00091     if (ptr != NULL)
00092       if (!ptr->isSafe(a))
00093   return false;
00094   }
00095 
00096   // Otherwise, it's safe to add a to the list.
00097   return true;
00098 }
00099 
00100 NOX::StatusTest::SafeCombo::~SafeCombo()
00101 {
00102 }
00103 
00104 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo::checkStatus(const Solver::Generic& problem)
00105 {
00106 #ifdef TRILINOS_6
00107   return checkStatusEfficiently(problem, NOX::StatusTest::Minimal);
00108 #else
00109   return checkStatus(problem, NOX::StatusTest::Minimal);
00110 #endif
00111 }
00112 
00113 #ifdef TRILINOS_6
00114 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo
00115 ::checkStatusEfficiently(const Solver::Generic& problem, 
00116                          NOX::StatusTest::CheckType checkType)
00117 #else
00118 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo
00119 ::checkStatus(const Solver::Generic& problem, 
00120               NOX::StatusTest::CheckType checkType)
00121 #endif
00122 {
00123   if (type == OR)
00124     orOp(problem, checkType);
00125   else
00126     andOp(problem, checkType);
00127 
00128   return status;
00129 }
00130 
00131 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo::getStatus() const
00132 {
00133   return status;
00134 }
00135 
00136 void NOX::StatusTest::SafeCombo::orOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType)
00137 {
00138   if (checkType == NOX::StatusTest::None)
00139     status = Unevaluated;
00140   else
00141     status = Unconverged;
00142 
00143   // Checks the status of each test. The first test it encounters, if
00144   // any, that is unconverged is the status that it sets itself too.
00145   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) 
00146   {
00147 #ifdef TRILINOS_6
00148     NOX::StatusTest::StatusType s = (*i)->checkStatusEfficiently(problem, checkType);
00149 #else
00150     NOX::StatusTest::StatusType s = (*i)->checkStatus(problem, checkType);
00151 #endif
00152     if ((status == Unconverged) && (s != Unconverged)) 
00153     {
00154       status = s;
00155 
00156       // Turn off checking for the remaining tests
00157       if (checkType == NOX::StatusTest::Minimal)
00158         checkType = NOX::StatusTest::None;
00159     }
00160 
00161   }
00162 
00163   return;
00164 }
00165 
00166 void NOX::StatusTest::SafeCombo::andOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType)
00167 {
00168   if (checkType == NOX::StatusTest::None)
00169     status = Unevaluated;
00170   else
00171     status = Unconverged;
00172 
00173   bool isUnconverged = false;
00174 
00175   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) {
00176 
00177 
00178 #ifdef TRILINOS_6
00179     NOX::StatusTest::StatusType s = (*i)->checkStatusEfficiently(problem, checkType);
00180 #else
00181     NOX::StatusTest::StatusType s = (*i)->checkStatus(problem, checkType);
00182 #endif
00183 
00184     // If any of the tests are unconverged, then the AND test is
00185     // unconverged.
00186     if (s == Unconverged) 
00187     {
00188       isUnconverged = true;
00189       status = Unconverged;
00190 
00191       // Turn off checking for the remaining tests
00192       if (checkType == NOX::StatusTest::Minimal)
00193   checkType = NOX::StatusTest::None;
00194     }
00195 
00196     // If this is the first test and it's converged/failed, copy its
00197     // status to the combo status.
00198     if ((!isUnconverged) && (status == Unconverged)) 
00199     {
00200       status = s;
00201     }
00202 
00203   }
00204 
00205   return;
00206 }
00207 
00208 
00209 ostream& NOX::StatusTest::SafeCombo::print(std::ostream& stream, int indent) const
00210 {
00211   for (int j = 0; j < indent; j ++)
00212     stream << ' ';
00213 //   stream << setiosflags(ios::left) << setw(13) << setfill('.');
00214 //   if (status == Unconverged) 
00215 //     stream << "**";
00216 //   else if (status == Failed)
00217 //     stream << "Failed";
00218 //   else
00219 //     stream << "Converged";
00220   stream << status;
00221   stream << ((type == OR) ? "OR" : "AND");
00222   stream << " Combination";
00223   stream << " -> " << std::endl;
00224 
00225   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) 
00226     (*i)->print(stream, indent+2);
00227     
00228   return stream;
00229 }

Site Contact