version 3.11-dev
Loading...
Searching...
No Matches
newtonsolver_linesearch_cubicbacktracking.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_NEWTON_SOLVER_LINESEARCH_CUBIC_BACKTRACKING_HH
13#define DUMUX_NEWTON_SOLVER_LINESEARCH_CUBIC_BACKTRACKING_HH
14
15#include <algorithm>
16#include <cmath>
17#include <memory>
18#include <string>
19
21#include <dumux/io/format.hh>
23
24namespace Dumux {
25
47template <class Assembler, class LinearSolver,
48 class Reassembler = PartialReassembler<Assembler>,
49 class Comm = Dune::Communication<Dune::MPIHelper::MPICommunicator> >
51: public NewtonSolver<Assembler, LinearSolver, Reassembler, Comm>
52{
54 using Scalar = typename Assembler::Scalar;
55
56protected:
57 using Backend = typename ParentType::Backend;
60
61public:
62 using typename ParentType::Variables;
63 using Communication = Comm;
64
66 std::shared_ptr<LinearSolver> linearSolver,
67 const Communication& comm = Dune::MPIHelper::getCommunication(),
68 const std::string& paramGroup = "",
69 const std::string& paramGroupName = "Newton",
70 int verbosity = 2)
71 : ParentType(assembler, linearSolver, comm, paramGroup, paramGroupName, verbosity)
72 {
73 this->setUseLineSearch(true);
74 minRelaxationFactor_ = getParamFromGroup<Scalar>(paramGroup, paramGroupName + ".LineSearchMinRelaxationFactor", 0.125);
75 armijoC1_ = getParamFromGroup<Scalar>(paramGroup, paramGroupName + ".LineSearchArmijoC1", 1e-4);
76 }
77
78private:
80 const SolutionVector& uLastIter,
81 const ResidualVector& deltaU) override
82 {
83 using std::isfinite;
84
85 const Scalar residualNorm0 = this->lastReduction_*this->initialResidual_;
86 const Scalar g0 = 0.5*residualNorm0*residualNorm0;
87 // g'(0) = -r^T J deltaU = -|r|^2 because the Newton update solves J deltaU = r
88 const Scalar slope = -residualNorm0*residualNorm0;
89
90 Scalar lambda = 1.0;
91 Scalar lambdaPrev = 0.0;
92 Scalar gPrev = 0.0;
93 bool hasPrevTrial = false;
94 auto uCurrentIter = uLastIter;
95 while (true)
96 {
97 Backend::axpy(-lambda, deltaU, uCurrentIter);
98 this->solutionChanged_(vars, uCurrentIter);
99 this->computeResidualReduction_(vars);
100
101 const Scalar g = 0.5*this->residualNorm_*this->residualNorm_;
102 if (g <= g0 + armijoC1_*lambda*slope || lambda <= minRelaxationFactor_)
103 {
104 this->endIterMsgStream_ << Fmt::format(", residual reduction {:.4e}->{:.4e}@lambda={:.4f}", this->lastReduction_, this->reduction_, lambda);
105 return;
106 }
107
108 Scalar lambdaNext = 0.5*lambda;
109 if (isfinite(g))
110 {
111 const Scalar lambdaModel = hasPrevTrial ? cubicMinimizer_(g0, slope, lambda, g, lambdaPrev, gPrev)
112 : quadraticMinimizer_(g0, slope, lambda, g);
113 if (isfinite(lambdaModel))
114 lambdaNext = lambdaModel;
115
116 lambdaPrev = lambda;
117 gPrev = g;
118 hasPrevTrial = true;
119 }
120
121 lambda = std::max<Scalar>(std::clamp<Scalar>(lambdaNext, 0.1*lambda, 0.5*lambda), minRelaxationFactor_);
122 uCurrentIter = uLastIter;
123 }
124 }
125
126 // minimizer of the quadratic q with q(0) = g0, q'(0) = slope, q(lambda) = g
127 static Scalar quadraticMinimizer_(Scalar g0, Scalar slope, Scalar lambda, Scalar g)
128 { return -slope*lambda*lambda/(2.0*(g - g0 - slope*lambda)); }
129
130 // minimizer of the cubic c with c(0) = g0, c'(0) = slope, c(lambda) = g, c(lambdaPrev) = gPrev
131 static Scalar cubicMinimizer_(Scalar g0, Scalar slope, Scalar lambda, Scalar g, Scalar lambdaPrev, Scalar gPrev)
132 {
133 using std::sqrt;
134 const Scalar t = (g - g0 - slope*lambda)/(lambda*lambda);
135 const Scalar tPrev = (gPrev - g0 - slope*lambdaPrev)/(lambdaPrev*lambdaPrev);
136 const Scalar a = (t - tPrev)/(lambda - lambdaPrev);
137 const Scalar b = (lambda*tPrev - lambdaPrev*t)/(lambda - lambdaPrev);
138 if (a == 0.0)
139 return -slope/(2.0*b);
140
141 const Scalar discriminant = b*b - 3.0*a*slope;
142 if (discriminant < 0.0)
143 return 0.5*lambda;
144 else if (b <= 0.0)
145 return (-b + sqrt(discriminant))/(3.0*a);
146 else // same root as above without cancellation
147 return -slope/(b + sqrt(discriminant));
148 }
149
150 Scalar minRelaxationFactor_;
151 Scalar armijoC1_;
152};
153
154} // end namespace Dumux
155
156#endif
Base class for linear solvers.
Definition solver.hh:27
typename Assembler::ResidualType ResidualVector
Definition nonlinear/newtonsolver.hh:189
const std::string & paramGroup() const
Returns the parameter group.
Definition nonlinear/newtonsolver.hh:826
Scalar reduction_
Definition nonlinear/newtonsolver.hh:895
int verbosity() const
Return the verbosity level.
Definition nonlinear/newtonsolver.hh:808
NewtonSolver(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, const Communication &comm=Dune::MPIHelper::getCommunication(), const std::string &paramGroup="", const std::string &paramGroupName="Newton", int verbosity=2)
Definition nonlinear/newtonsolver.hh:209
virtual void solutionChanged_(Variables &vars, const SolutionVector &uCurrentIter)
Update solution-dependent quantities like grid variables after the solution has changed.
Definition nonlinear/newtonsolver.hh:860
Scalar initialResidual_
Definition nonlinear/newtonsolver.hh:898
Scalar lastReduction_
Definition nonlinear/newtonsolver.hh:897
void setUseLineSearch(bool val=true)
Specify whether line search is enabled or not.
Definition nonlinear/newtonsolver.hh:814
std::ostringstream endIterMsgStream_
message stream to be displayed at the end of iterations
Definition nonlinear/newtonsolver.hh:905
typename Backend::DofVector SolutionVector
Definition nonlinear/newtonsolver.hh:188
const Communication & comm() const
the communicator for parallel runs
Definition nonlinear/newtonsolver.hh:239
VariablesBackend< typename ParentType::Variables > Backend
Definition nonlinear/newtonsolver.hh:187
void computeResidualReduction_(const Variables &vars)
Definition nonlinear/newtonsolver.hh:868
Scalar residualNorm_
Definition nonlinear/newtonsolver.hh:896
NewtonSolverLinesearchCubicbacktracking(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, const Communication &comm=Dune::MPIHelper::getCommunication(), const std::string &paramGroup="", const std::string &paramGroupName="Newton", int verbosity=2)
Definition newtonsolver_linesearch_cubicbacktracking.hh:65
typename ParentType::SolutionVector SolutionVector
Definition newtonsolver_linesearch_cubicbacktracking.hh:58
Comm Communication
Definition newtonsolver_linesearch_cubicbacktracking.hh:63
void lineSearchUpdate_(Variables &vars, const SolutionVector &uLastIter, const ResidualVector &deltaU) override
Use a line search update based on simple backtracking.
Definition newtonsolver_linesearch_cubicbacktracking.hh:79
typename ParentType::Backend Backend
Definition newtonsolver_linesearch_cubicbacktracking.hh:57
typename ParentType::ResidualVector ResidualVector
Definition newtonsolver_linesearch_cubicbacktracking.hh:59
const LinearSolver & linearSolver() const
Definition common/pdesolver.hh:133
const Assembler & assembler() const
Definition common/pdesolver.hh:121
Detail::PDESolver::AssemblerVariables< Assembler > Variables
Definition common/pdesolver.hh:71
detects which entries in the Jacobian have to be recomputed
Definition partialreassembler.hh:418
Formatting based on the fmt-library which implements std::format of C++20.
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
Definition adapt.hh:17
Reference implementation of a Newton solver.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.