3 #ifndef DUNE_PDELAB_SOLVER_NEWTONLINESEARCH_HH
4 #define DUNE_PDELAB_SOLVER_NEWTONLINESEARCH_HH
11 template <
typename Domain>
19 virtual void lineSearch(Domain&,
const Domain&) = 0;
27 template <
typename Newton>
31 using Domain =
typename Newton::Domain;
32 using Real =
typename Newton::Real;
39 solution.axpy(-1.0, correction);
40 _newton.updateDefect(solution);
56 template <
typename Newton>
60 using Domain =
typename Newton::Domain;
61 using Real =
typename Newton::Real;
68 if ((_newton.result().defect < _newton.getAbsoluteLimit())){
69 solution.axpy(-1.0, correction);
70 _newton.updateDefect(solution);
74 auto verbosity = _newton.getVerbosityLevel();
77 std::cout <<
" Performing line search..." << std::endl;
79 Real bestLambda = 0.0;
80 Real bestDefect = _newton.result().defect;
81 Real previousDefect = _newton.result().defect;
82 bool converged =
false;
84 if (not _previousSolution)
85 _previousSolution = std::make_shared<Domain>(solution);
87 *_previousSolution = solution;
89 for (
unsigned int iteration = 0; iteration < _lineSearchMaxIterations; ++iteration){
91 std::cout <<
" trying line search damping factor: "
92 << std::setw(12) << std::setprecision(4) << std::scientific
96 solution.axpy(-lambda, correction);
97 _newton.updateDefect(solution);
99 if (not std::isfinite(_newton.result().defect))
100 std::cout <<
" NaNs detected" << std::endl;
103 if (_newton.result().defect <= (1.0 - lambda/4) * previousDefect){
105 std::cout <<
" line search converged" << std::endl;
110 if (_newton.result().defect < bestDefect){
111 bestDefect = _newton.result().defect;
115 lambda *= _lineSearchDampingFactor;
116 solution = *_previousSolution;
121 std::cout <<
" max line search iterations exceeded" << std::endl;
123 if (not _acceptBest){
124 solution = *_previousSolution;
125 _newton.updateDefect(solution);
126 DUNE_THROW(NewtonLineSearchError,
127 "NewtonLineSearch::line_search(): line search failed, "
128 "max iteration count reached, "
129 "defect did not improve enough");
132 if (bestLambda == 0.0){
133 solution = *_previousSolution;
134 _newton.updateDefect(solution);
135 DUNE_THROW(NewtonLineSearchError,
136 "NewtonLineSearch::line_search(): line search failed, "
137 "max iteration count reached, "
138 "defect did not improve in any of the iterations");
140 if (bestLambda != lambda){
141 solution = *_previousSolution;
142 solution.axpy(-bestLambda, correction);
143 _newton.updateDefect(solution);
151 std::cout <<
" line search damping factor: "
152 << std::setw(12) << std::setprecision(4) << std::scientific
153 << lambda << std::endl;
171 _lineSearchMaxIterations = parameterTree.get<
unsigned int>(
"line_search_max_iterations",
172 _lineSearchMaxIterations);
173 _lineSearchDampingFactor = parameterTree.get<
Real>(
"line_search_damping_factor",
174 _lineSearchDampingFactor);
175 _acceptBest = parameterTree.get<
bool>(
"line_search_accept_best",
181 std::shared_ptr<Domain> _previousSolution;
184 unsigned int _lineSearchMaxIterations = 10;
185 Real _lineSearchDampingFactor = 0.5;
186 bool _acceptBest =
false;
205 if (name ==
"noLineSearch")
207 if (name ==
"hackbusch_reusken")
209 DUNE_THROW(
Exception,
"Unkown line search strategy: " << name);
223 template <
typename Newton>
224 std::shared_ptr<LineSearchInterface<typename Newton::Domain>>
229 auto lineSearch = std::make_shared<LineSearchNone<Newton>> (newton);
233 auto lineSearch = std::make_shared<LineSearchHackbuschReusken<Newton>> (newton);
236 DUNE_THROW(
Exception,
"Unkown line search strategy");