Go to the documentation of this file.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 #ifndef PLAYA_NEWTON_ARMIJO_SOLVER_IMPL_HPP
00043 #define PLAYA_NEWTON_ARMIJO_SOLVER_IMPL_HPP
00044
00045 #include "PlayaNewtonArmijoSolverDecl.hpp"
00046 #include "PlayaNonlinearOperator.hpp"
00047 #include "PlayaTabs.hpp"
00048 #include "PlayaOut.hpp"
00049 #include "Teuchos_ParameterList.hpp"
00050
00051 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00052 #include "PlayaLinearCombinationImpl.hpp"
00053 #include "PlayaLinearSolverImpl.hpp"
00054 #include "PlayaLinearOperatorImpl.hpp"
00055 #endif
00056
00057
00058 using std::setw;
00059
00060 namespace Playa
00061 {
00062
00063
00064
00065 template <class Scalar> inline
00066 NewtonArmijoSolver<Scalar>::NewtonArmijoSolver(
00067 const ParameterList& params,
00068 const LinearSolver<Scalar>& linSolver)
00069 : NonlinearSolverBase<Scalar>(params),
00070 linSolver_(linSolver),
00071 tauR_(10.0*Teuchos::ScalarTraits<Scalar>::eps()),
00072 tauA_(10.0*Teuchos::ScalarTraits<Scalar>::eps()),
00073 alpha_(1.0e-4),
00074 stepReduction_(0.5),
00075 maxIters_(20),
00076 maxLineSearch_(20),
00077 verb_(0)
00078 {
00079 if (params.isParameter("Tau Relative")) tauR_ = params.get<Scalar>("Tau Relative");
00080 if (params.isParameter("Tau Absolute")) tauA_ = params.get<Scalar>("Tau Absolute");
00081 if (params.isParameter("Alpha")) alpha_ = params.get<Scalar>("Alpha");
00082 if (params.isParameter("Step Reduction")) stepReduction_ = params.get<Scalar>("Step Reduction");
00083 if (params.isParameter("Max Iterations")) maxIters_ = params.get<int>("Max Iterations");
00084 if (params.isParameter("Max Backtracks")) maxLineSearch_ = params.get<int>("Max Backtracks");
00085 if (params.isParameter("Verbosity")) verb_ = params.get<int>("Verbosity");
00086 }
00087
00088 template <class Scalar> inline
00089 SolverState<Scalar> NewtonArmijoSolver<Scalar>::solve(const NonlinearOperator<Scalar>& F,
00090 Vector<Scalar>& soln) const
00091 {
00092 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType ScalarMag;
00093 typedef typename Teuchos::ScalarTraits<Scalar> ST;
00094
00095 Tabs tab0(0);
00096 PLAYA_MSG1(verb_, tab0 << " begin Playa::NewtonArmijoSolver::solve()");
00097
00098 soln = F.getInitialGuess().copy();
00099 Vector<Scalar> newtonStep = soln.copy();
00100
00101 F.setEvalPt(soln);
00102 Vector<Scalar> resid = F.getFunctionValue();
00103
00104 ScalarMag r0 = resid.norm2();
00105 ScalarMag normF0 = r0;
00106
00107 for (int i=0; i<maxIters_; i++)
00108 {
00109 Tabs tab1;
00110 PLAYA_MSG2(verb_, tab1 << "Newton iter #" << setw(6) << i << " |F|=" << setw(12) << normF0 << " |F|/|F0|="
00111 << setw(12) << normF0/r0);
00112
00113 if (normF0 < r0*tauR_ + tauA_)
00114 {
00115 PLAYA_MSG3(verb_, tab1 << "|F|=" << setw(12) << normF0);
00116 PLAYA_MSG3(verb_, tab1 << "Relative tolerance tauR=" << setw(12) << tauR_);
00117 PLAYA_MSG3(verb_, tab1 << "Absolute tolerance tauA=" << setw(12) << tauA_);
00118 PLAYA_MSG3(verb_, tab1 << " F0*tauR+tauA=" << setw(12) << r0*tauR_ + tauA_);
00119 PLAYA_MSG2(verb_, tab1 << "converged!");
00120 PLAYA_MSG1(verb_, tab0 << " done Playa::NewtonArmijoSolver::solve()");
00121 soln = F.currentEvalPt().copy();
00122 return SolverState<Scalar>(SolveConverged, "NewtonArmijoSolver::solve converged",
00123 i, normF0);
00124 }
00125 LinearOperator<Scalar> J = F.getJacobian();
00126
00127
00128 SolverState<Scalar> linSolverState = linSolver_.solve(J, resid, newtonStep);
00129 if (linSolverState.finalState() != SolveConverged)
00130 {
00131 PLAYA_MSG1(verb_, tab0 << " done Playa::NewtonArmijoSolver::solve()");
00132 return SolverState<Scalar>(SolveCrashed,
00133 "NewtonArmijoSolver::solve: linear solve failed with message ["
00134 + linSolverState.finalMsg() + "]", i, normF0);
00135 }
00136
00137
00138 Scalar t = ST::one();
00139
00140 bool stepAccepted = false;
00141 soln = F.currentEvalPt().copy();
00142
00143 for (int j=0; j<maxLineSearch_; j++)
00144 {
00145 Tabs tab2;
00146 Vector<Scalar> tmp = soln - t*newtonStep;
00147 F.setEvalPt( tmp );
00148 resid = F.getFunctionValue();
00149 ScalarMag normF1 = resid.norm2();
00150 PLAYA_MSG2(verb_, tab2 << "step t=" << setw(12) << t << " |F|=" << setw(12) << normF1);
00151 if (normF1 < (ST::one() - alpha_*t)*normF0)
00152 {
00153 stepAccepted = true;
00154 normF0 = normF1;
00155 break;
00156 }
00157 t = stepReduction_*t;
00158 }
00159
00160 if (!stepAccepted)
00161 {
00162 PLAYA_MSG1(verb_, tab0 << " done Playa::NewtonArmijoSolver::solve()");
00163 return SolverState<Scalar>(SolveCrashed,
00164 "NewtonArmijoSolver: line search failed",i, normF0);
00165 }
00166 }
00167
00168 PLAYA_MSG1(verb_, tab0 << " done Playa::NewtonArmijoSolver::solve()");
00169 return SolverState<Scalar>(SolveFailedToConverge, "NewtonArmijoSolver: convergence failure after "
00170 + Teuchos::toString(maxIters_) + " steps.", maxIters_, normF0);
00171 }
00172
00173 }
00174
00175
00176 #endif