ExaDG
Loading...
Searching...
No Matches
newton_solver.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef INCLUDE_SOLVERS_AND_PRECONDITIONERS_NEWTON_SOLVER_H_
23#define INCLUDE_SOLVERS_AND_PRECONDITIONERS_NEWTON_SOLVER_H_
24
25// deal.II
26#include <deal.II/base/exceptions.h>
27
28// ExaDG
29#include <exadg/solvers_and_preconditioners/newton/newton_solver_data.h>
30
31namespace ExaDG
32{
33namespace Newton
34{
35template<typename VectorType,
36 typename NonlinearOperator,
37 typename LinearOperator,
38 typename LinearSolver>
39class Solver
40{
41public:
42 Solver(SolverData const & solver_data_in,
43 NonlinearOperator & nonlinear_operator_in,
44 LinearOperator & linear_operator_in,
45 LinearSolver & linear_solver_in)
46 : solver_data(solver_data_in),
47 nonlinear_operator(nonlinear_operator_in),
48 linear_operator(linear_operator_in),
49 linear_solver(linear_solver_in)
50 {
51 }
52
53 std::tuple<unsigned int /* Newton iter */, unsigned int /* accumulated linear iter */>
54 solve(VectorType & solution, UpdateData const & update)
55 {
56 unsigned int newton_iterations = 0, linear_iterations = 0;
57
58 VectorType residual, increment, temporary;
59 residual.reinit(solution);
60 increment.reinit(solution);
61 temporary.reinit(solution);
62
63 // evaluate residual using initial guess of solution
64 nonlinear_operator.evaluate_residual(residual, solution);
65
66 double norm_r = residual.l2_norm();
67 double norm_r_0 = norm_r;
68
69 while(norm_r > this->solver_data.abs_tol and norm_r / norm_r_0 > solver_data.rel_tol and
70 newton_iterations < solver_data.max_iter)
71 {
72 // reset increment
73 increment = 0.0;
74
75 // multiply by -1.0 since the linearized problem is "linear_operator * increment = - residual"
76 residual *= -1.0;
77
78 // update linear operator (set linearization point)
79 linear_operator.set_solution_linearization(solution);
80
81 // determine whether to update the operator/preconditioner of the linearized problem
82 bool const update_now =
83 update.do_update and (newton_iterations % update.update_every_newton_iter == 0);
84
85 // update the preconditioner
86 linear_solver.update_preconditioner(update_now);
87
88 // solve linear problem
89 unsigned int const n_iter_linear = linear_solver.solve(increment, residual);
90
91 // damped Newton scheme
92 double omega = 1.0; // damping factor (begin with 1)
93 double norm_r_damp = 1.0; // norm of residual using temporary solution
94 unsigned int n_iter_damp = 0; // counts iteration of damping scheme
95 unsigned int const max_iter_damp = 10; // max iterations of damping scheme
96 double const tau = 0.5; // a parameter (has to be smaller than 1)
97 do
98 {
99 // add increment to solution vector but scale by a factor omega <= 1
100 temporary = solution;
101 temporary.add(omega, increment);
102
103 // evaluate residual using the temporary solution
104 nonlinear_operator.evaluate_residual(residual, temporary);
105
106 // calculate norm of residual (for temporary solution)
107 norm_r_damp = residual.l2_norm();
108
109 // reduce step length
110 omega = omega / 2.0;
111
112 // increment counter
113 n_iter_damp++;
114 } while(norm_r_damp >= (1.0 - tau * omega) * norm_r and n_iter_damp < max_iter_damp);
115
116 AssertThrow(norm_r_damp < (1.0 - tau * omega) * norm_r,
117 dealii::ExcMessage("Damped Newton iteration did not converge. "
118 "Maximum number of iterations exceeded!"));
119
120 // update solution and residual
121 solution = temporary;
122 norm_r = norm_r_damp;
123
124 // increment iteration counter
125 ++newton_iterations;
126 linear_iterations += n_iter_linear;
127 }
128
129 AssertThrow(norm_r <= this->solver_data.abs_tol or norm_r / norm_r_0 <= solver_data.rel_tol,
130 dealii::ExcMessage(
131 "Newton solver failed to solve nonlinear problem to given tolerance. "
132 "Maximum number of iterations exceeded!"));
133
134 if(update.do_update and update.update_once_converged)
135 {
136 // update linear operator (set linearization point)
137 linear_operator.set_solution_linearization(solution);
138 // update preconditioner
139 linear_solver.update_preconditioner(true);
140 }
141
142 return std::tuple<unsigned int, unsigned int>(newton_iterations, linear_iterations);
143 }
144
145private:
146 SolverData solver_data;
147 NonlinearOperator & nonlinear_operator;
148 LinearOperator & linear_operator;
149 LinearSolver & linear_solver;
150};
151
152} // namespace Newton
153} // namespace ExaDG
154
155#endif /* INCLUDE_SOLVERS_AND_PRECONDITIONERS_NEWTON_SOLVER_H_ */
Definition newton_solver.h:40
Definition driver.cpp:33
Definition newton_solver_data.h:36
Definition newton_solver_data.h:60