3#ifndef DUNE_PDELAB_SOLVER_LINESEARCH_HH
4#define DUNE_PDELAB_SOLVER_LINESEARCH_HH
10 class LineSearchError :
public Exception {};
13 template <
typename Domain>
29 template <
typename Solver>
33 using Domain =
typename Solver::Domain;
34 using Real =
typename Solver::Real;
39 virtual void lineSearch(Domain& solution,
const Domain& correction)
override
41 solution.axpy(-1.0, correction);
42 _solver.updateDefect(solution);
58 template <
typename Solver>
62 using Domain =
typename Solver::Domain;
63 using Real =
typename Solver::Real;
66 _solver(solver), _forceAcceptBest(forceAcceptBest) {}
69 virtual void lineSearch(Domain& solution,
const Domain& correction)
override
71 if ((_solver.result().defect < _solver.getAbsoluteLimit())){
72 solution.axpy(-1.0, correction);
73 _solver.updateDefect(solution);
77 auto verbosity = _solver.getVerbosityLevel();
80 std::cout <<
" Performing line search..." << std::endl;
82 Real bestLambda = 0.0;
83 Real bestDefect = _solver.result().defect;
84 Real previousDefect = _solver.result().defect;
85 bool converged =
false;
87 if (not _previousSolution)
88 _previousSolution = std::make_shared<Domain>(solution);
90 *_previousSolution = solution;
92 for (
unsigned int iteration = 0; iteration < _lineSearchMaxIterations; ++iteration){
94 std::cout <<
" trying line search damping factor: "
95 << std::setw(12) << std::setprecision(4) << std::scientific
99 solution.axpy(-lambda, correction);
100 _solver.updateDefect(solution);
102 if (not std::isfinite(_solver.result().defect))
103 std::cout <<
" NaNs detected" << std::endl;
106 if (_solver.result().defect <= (1.0 - lambda/4) * previousDefect){
108 std::cout <<
" line search converged" << std::endl;
113 if (_solver.result().defect < bestDefect){
114 bestDefect = _solver.result().defect;
118 lambda *= _lineSearchDampingFactor;
119 solution = *_previousSolution;
124 std::cout <<
" max line search iterations exceeded" << std::endl;
126 if (not (_acceptBest or _forceAcceptBest)){
127 solution = *_previousSolution;
128 _solver.updateDefect(solution);
130 "LineSearch::lineSearch(): line search failed, "
131 "max iteration count reached, "
132 "defect did not improve enough");
135 if (bestLambda == 0.0){
136 solution = *_previousSolution;
137 _solver.updateDefect(solution);
139 "LineSearch::lineSearch(): line search failed, "
140 "max iteration count reached, "
141 "defect did not improve in any of the iterations");
143 if (bestLambda != lambda){
144 solution = *_previousSolution;
145 solution.axpy(-bestLambda, correction);
146 _solver.updateDefect(solution);
154 std::cout <<
" line search damping factor: "
155 << std::setw(12) << std::setprecision(4) << std::scientific
156 << lambda << std::endl;
174 _lineSearchMaxIterations = parameterTree.
get<
unsigned int>(
"MaxIterations",
175 _lineSearchMaxIterations);
176 _lineSearchDampingFactor = parameterTree.
get<Real>(
"DampingFactor",
177 _lineSearchDampingFactor);
178 _acceptBest = parameterTree.
get<
bool>(
"AcceptBest", _acceptBest);
183 std::shared_ptr<Domain> _previousSolution;
186 unsigned int _lineSearchMaxIterations = 10;
187 Real _lineSearchDampingFactor = 0.5;
188 bool _acceptBest =
false;
189 bool _forceAcceptBest;
193 enum class LineSearchStrategy
197 hackbuschReuskenAcceptBest
209 LineSearchStrategy lineSearchStrategyFromString (
const std::string& name)
211 if (name ==
"noLineSearch")
212 return LineSearchStrategy::noLineSearch;
213 if (name ==
"hackbuschReusken")
214 return LineSearchStrategy::hackbuschReusken;
215 if (name ==
"hackbuschReuskenAcceptBest")
216 return LineSearchStrategy::hackbuschReuskenAcceptBest;
217 DUNE_THROW(Exception,
"Unkown line search strategy: " << name);
232 template <
typename Solver>
233 std::shared_ptr<LineSearchInterface<typename Solver::Domain>>
234 createLineSearch(Solver& solver, LineSearchStrategy strategy)
236 if (strategy == LineSearchStrategy::noLineSearch){
237 auto lineSearch = std::make_shared<LineSearchNone<Solver>> (solver);
240 if (strategy == LineSearchStrategy::hackbuschReusken){
241 auto lineSearch = std::make_shared<LineSearchHackbuschReusken<Solver>> (solver);
244 if (strategy == LineSearchStrategy::hackbuschReuskenAcceptBest){
245 auto lineSearch = std::make_shared<LineSearchHackbuschReusken<Solver>> (solver,
true);
246 std::cout <<
"Warning: linesearch hackbuschReuskenAcceptBest is deprecated and will be removed after PDELab 2.7.\n"
247 <<
" Please use 'hackbuschReusken' and add the parameter 'LineSearchAcceptBest : true'";
250 DUNE_THROW(Exception,
"Unkown line search strategy");
Hackbusch-Reusken line search.
Definition: linesearch.hh:60
virtual void setParameters(const ParameterTree ¶meterTree) override
Set parameters.
Definition: linesearch.hh:172
virtual void lineSearch(Domain &solution, const Domain &correction) override
Do line search.
Definition: linesearch.hh:69
Abstract base class describing the line search interface.
Definition: linesearch.hh:15
virtual ~LineSearchInterface()
Every abstract base class should have a virtual destructor.
Definition: linesearch.hh:18
virtual void setParameters(const ParameterTree &)=0
Set parameters.
virtual void lineSearch(Domain &, const Domain &)=0
Do line search.
Class for simply updating the solution without line search.
Definition: linesearch.hh:31
virtual void lineSearch(Domain &solution, const Domain &correction) override
Do line search (in this case just update the solution)
Definition: linesearch.hh:39
virtual void setParameters(const ParameterTree &) override
Set parameters.
Definition: linesearch.hh:45
Hierarchical structure of string parameters.
Definition: parametertree.hh:35
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: parametertree.cc:183
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216