00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "NOX_LineSearch_Backtrack.H"
00043
00044 #include "NOX_Common.H"
00045 #include "NOX_Abstract_Vector.H"
00046 #include "NOX_Abstract_Group.H"
00047 #include "NOX_Solver_Generic.H"
00048 #include "Teuchos_ParameterList.hpp"
00049 #include "NOX_Utils.H"
00050 #include "NOX_MeritFunction_Generic.H"
00051 #include "NOX_StatusTest_FiniteValue.H"
00052 #include "NOX_GlobalData.H"
00053
00054 NOX::LineSearch::Backtrack::
00055 Backtrack(const Teuchos::RCP<NOX::GlobalData>& gd,
00056 Teuchos::ParameterList& params)
00057 {
00058 reset(gd, params);
00059 }
00060
00061 NOX::LineSearch::Backtrack::~Backtrack()
00062 {
00063
00064 }
00065
00066 bool NOX::LineSearch::Backtrack::
00067 reset(const Teuchos::RCP<NOX::GlobalData>& gd,
00068 Teuchos::ParameterList& params)
00069 {
00070 utils = gd->getUtils();
00071 meritFunctionPtr = gd->getMeritFunction();
00072
00073 Teuchos::ParameterList& p = params.sublist("Backtrack");
00074
00075 minStep = p.get("Minimum Step", 1.0e-12);
00076 defaultStep = p.get("Default Step", 1.0);
00077 recoveryStep = p.get("Recovery Step", defaultStep);
00078 maxIters = p.get("Max Iters", 100);
00079
00080 reductionFactor = p.get("Reduction Factor", 0.5);
00081 if ((reductionFactor <= 0.0) || (reductionFactor >= 1.0)) {
00082 utils->err() << "NOX::LineSearch::Backtrack::reset - Invalid choice \""
00083 << reductionFactor << "\" for \"Reduction Factor\"! "
00084 << "Value must be greater than zero and less than 1.0."
00085 << endl;
00086 throw "NOX Error";
00087 }
00088
00089 return true;
00090 }
00091
00092 bool NOX::LineSearch::Backtrack::
00093 compute(NOX::Abstract::Group& grp, double& step,
00094 const NOX::Abstract::Vector& dir,
00095 const NOX::Solver::Generic& s)
00096 {
00097 const Abstract::Group& oldGrp = s.getPreviousSolutionGroup();
00098 double oldF = meritFunctionPtr->computef(oldGrp);
00099 double newF;
00100 bool isFailed = false;
00101
00102 step = defaultStep;
00103 grp.computeX(oldGrp, dir, step);
00104
00105 NOX::Abstract::Group::ReturnType rtype;
00106
00107 rtype = grp.computeF();
00108 if (rtype != NOX::Abstract::Group::Ok)
00109 {
00110 utils->err() << "NOX::LineSearch::BackTrack::compute - Unable to compute F"
00111 << endl;
00112 throw "NOX Error";
00113 }
00114
00115 newF = meritFunctionPtr->computef(grp);
00116 int nIters = 1;
00117
00118 if (utils->isPrintType(Utils::InnerIteration))
00119 {
00120 utils->out() << "\n" << Utils::fill(72) << "\n"
00121 << "-- Backtrack Line Search -- \n";
00122 }
00123
00124 NOX::StatusTest::FiniteValue checkNAN;
00125
00126 while ( ((newF >= oldF) || (checkNAN.finiteNumberTest(newF) !=0))
00127 && (!isFailed))
00128 {
00129
00130 if (utils->isPrintType(Utils::InnerIteration))
00131 {
00132 utils->out() << setw(3) << nIters << ":";
00133 utils->out() << " step = " << utils->sciformat(step);
00134 utils->out() << " old f = " << utils->sciformat(oldF);
00135 utils->out() << " new f = " << utils->sciformat(newF);
00136 utils->out() << endl;
00137 }
00138
00139 nIters ++;
00140 step = step * reductionFactor;
00141
00142 if ((step < minStep) || (nIters > maxIters))
00143 {
00144 isFailed = true;
00145 step = recoveryStep;
00146 }
00147
00148 grp.computeX(oldGrp, dir, step);
00149
00150 rtype = grp.computeF();
00151 if (rtype != NOX::Abstract::Group::Ok)
00152 {
00153 utils->err() << "NOX::LineSearch::BackTrack::compute - Unable to compute F" << endl;
00154 throw "NOX Error";
00155 }
00156
00157 newF = meritFunctionPtr->computef(grp);
00158 }
00159
00160 if (utils->isPrintType(Utils::InnerIteration))
00161 {
00162 utils->out() << setw(3) << nIters << ":";
00163 utils->out() << " step = " << utils->sciformat(step);
00164 utils->out() << " old f = " << utils->sciformat(oldF);
00165 utils->out() << " new f = " << utils->sciformat(newF);
00166 if (isFailed)
00167 utils->out() << " (USING RECOVERY STEP!)" << endl;
00168 else
00169 utils->out() << " (STEP ACCEPTED!)" << endl;
00170 utils->out() << Utils::fill(72) << "\n" << endl;
00171 }
00172
00173 return (!isFailed);
00174 }
00175