NOX_StatusTest_SafeCombo.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                 Playa: Programmable Linear Algebra
00005 //                 Copyright 2012 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 // $Id$ 
00044 // $Source$ 
00045 
00046 
00047 //   
00048 
00049 
00050 #include "PlayaDefs.hpp"
00051 #include "NOX_StatusTest_SafeCombo.hpp"
00052 #include "NOX_Utils.H"
00053 
00054 using namespace Teuchos;
00055 using std::runtime_error;
00056 using std::cout;
00057 using std::ostream;
00058 using std::vector;
00059 
00060 
00061 
00062 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t) :
00063   type(t)
00064 {
00065   status = Unevaluated;
00066 }
00067 
00068 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t, 
00069                                       const Teuchos::RCP<Generic>& a) :
00070   type(t)
00071 {
00072   tests.push_back(a);
00073   status = Unevaluated;
00074 }
00075 
00076 NOX::StatusTest::SafeCombo::SafeCombo(ComboType t, 
00077                                       const Teuchos::RCP<Generic>& a, 
00078                                       const Teuchos::RCP<Generic>& b) :
00079   type(t)
00080 {
00081   tests.push_back(a);
00082   addStatusTest(b);
00083   status = Unevaluated;
00084 }
00085 
00086 NOX::StatusTest::SafeCombo& NOX::StatusTest::SafeCombo::addStatusTest(const Teuchos::RCP<Generic>& a)
00087 {
00088   if (isSafe(a))
00089     tests.push_back(a);
00090   else 
00091   {
00092     const int indent = 2;
00093     cout << "\n*** WARNING! ***\n";
00094     cout << "This combo test currently consists of the following:\n";
00095     this->print(cout, indent);
00096     cout << "Unable to add the following test:\n";
00097     a->print(cout, indent);
00098     cout << "\n";
00099   }
00100   return *this;
00101 }
00102 
00103 bool NOX::StatusTest::SafeCombo::isSafe(const Teuchos::RCP<Generic>& a)
00104 {
00105   // Are we trying to add "this" to "this"? This would result in an infinite recursion.
00106   if (a.get() == this)
00107     return false;
00108   
00109   // Recursively test that we're not adding something that's already
00110   // in the list because that can also lead to infinite recursions.
00111   for (vector<Teuchos::RCP<Generic> >::iterator i = tests.begin(); 
00112        i != tests.end(); ++i) 
00113   {
00114     
00115     SafeCombo* ptr = dynamic_cast<SafeCombo*>((*i).get());
00116     if (ptr != NULL)
00117       if (!ptr->isSafe(a))
00118   return false;
00119   }
00120 
00121   // Otherwise, it's safe to add a to the list.
00122   return true;
00123 }
00124 
00125 NOX::StatusTest::SafeCombo::~SafeCombo()
00126 {
00127 }
00128 
00129 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo::checkStatus(const Solver::Generic& problem)
00130 {
00131 #ifdef TRILINOS_6
00132   return checkStatusEfficiently(problem, NOX::StatusTest::Minimal);
00133 #else
00134   return checkStatus(problem, NOX::StatusTest::Minimal);
00135 #endif
00136 }
00137 
00138 #ifdef TRILINOS_6
00139 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo
00140 ::checkStatusEfficiently(const Solver::Generic& problem, 
00141                          NOX::StatusTest::CheckType checkType)
00142 #else
00143 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo
00144 ::checkStatus(const Solver::Generic& problem, 
00145               NOX::StatusTest::CheckType checkType)
00146 #endif
00147 {
00148   if (type == OR)
00149     orOp(problem, checkType);
00150   else
00151     andOp(problem, checkType);
00152 
00153   return status;
00154 }
00155 
00156 NOX::StatusTest::StatusType NOX::StatusTest::SafeCombo::getStatus() const
00157 {
00158   return status;
00159 }
00160 
00161 void NOX::StatusTest::SafeCombo::orOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType)
00162 {
00163   if (checkType == NOX::StatusTest::None)
00164     status = Unevaluated;
00165   else
00166     status = Unconverged;
00167 
00168   // Checks the status of each test. The first test it encounters, if
00169   // any, that is unconverged is the status that it sets itself too.
00170   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) 
00171   {
00172 #ifdef TRILINOS_6
00173     NOX::StatusTest::StatusType s = (*i)->checkStatusEfficiently(problem, checkType);
00174 #else
00175     NOX::StatusTest::StatusType s = (*i)->checkStatus(problem, checkType);
00176 #endif
00177     if ((status == Unconverged) && (s != Unconverged)) 
00178     {
00179       status = s;
00180 
00181       // Turn off checking for the remaining tests
00182       if (checkType == NOX::StatusTest::Minimal)
00183         checkType = NOX::StatusTest::None;
00184     }
00185 
00186   }
00187 
00188   return;
00189 }
00190 
00191 void NOX::StatusTest::SafeCombo::andOp(const Solver::Generic& problem, NOX::StatusTest::CheckType checkType)
00192 {
00193   if (checkType == NOX::StatusTest::None)
00194     status = Unevaluated;
00195   else
00196     status = Unconverged;
00197 
00198   bool isUnconverged = false;
00199 
00200   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) {
00201 
00202 
00203 #ifdef TRILINOS_6
00204     NOX::StatusTest::StatusType s = (*i)->checkStatusEfficiently(problem, checkType);
00205 #else
00206     NOX::StatusTest::StatusType s = (*i)->checkStatus(problem, checkType);
00207 #endif
00208 
00209     // If any of the tests are unconverged, then the AND test is
00210     // unconverged.
00211     if (s == Unconverged) 
00212     {
00213       isUnconverged = true;
00214       status = Unconverged;
00215 
00216       // Turn off checking for the remaining tests
00217       if (checkType == NOX::StatusTest::Minimal)
00218   checkType = NOX::StatusTest::None;
00219     }
00220 
00221     // If this is the first test and it's converged/failed, copy its
00222     // status to the combo status.
00223     if ((!isUnconverged) && (status == Unconverged)) 
00224     {
00225       status = s;
00226     }
00227 
00228   }
00229 
00230   return;
00231 }
00232 
00233 
00234 ostream& NOX::StatusTest::SafeCombo::print(std::ostream& stream, int indent) const
00235 {
00236   for (int j = 0; j < indent; j ++)
00237     stream << ' ';
00238 //   stream << setiosflags(ios::left) << setw(13) << setfill('.');
00239 //   if (status == Unconverged) 
00240 //     stream << "**";
00241 //   else if (status == Failed)
00242 //     stream << "Failed";
00243 //   else
00244 //     stream << "Converged";
00245   stream << status;
00246   stream << ((type == OR) ? "OR" : "AND");
00247   stream << " Combination";
00248   stream << " -> " << std::endl;
00249 
00250   for (vector<Teuchos::RCP<Generic> >::const_iterator i = tests.begin(); i != tests.end(); ++i) 
00251     (*i)->print(stream, indent+2);
00252     
00253   return stream;
00254 }

Site Contact