PRISMS-PF Manual
Loading...
Searching...
No Matches
newton_solver.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: © 2025 PRISMS Center at the University of Michigan
2// SPDX-License-Identifier: GNU Lesser General Public Version 2.1
3
4#pragma once
5
6#include <deal.II/lac/affine_constraints.h>
7#include <deal.II/lac/solver_cg.h>
8
10#include <prismspf/core/types.h>
11
15
16#include <prismspf/config.h>
17
19
20template <unsigned int dim, unsigned int degree, typename number>
21class SolveContext;
22
26template <unsigned int dim, unsigned int degree, typename number>
27class NewtonSolver : public LinearSolver<dim, degree, number>
28{
29protected:
30 using SolverBase<dim, degree, number>::solutions;
31 using SolverBase<dim, degree, number>::solve_context;
32 using SolverBase<dim, degree, number>::solve_block;
33 using LinearSolver<dim, degree, number>::do_linear_solve;
34 using LinearSolver<dim, degree, number>::normalization_value;
35 using LinearSolver<dim, degree, number>::lhs_operator;
36 using LinearSolver<dim, degree, number>::rhs_operator;
37 using LinearSolver<dim, degree, number>::rhs_vector;
38
39public:
45 const SolveContext<dim, degree, number> &_solve_context)
46 : LinearSolver<dim, degree, number>(_solve_block, _solve_context)
47 {}
48
52 void
53 init(const std::list<SolveBlock> &all_solve_blocks) override
54 {
56 newton_update.reinit(solutions.get_solution_full_vector());
57 }
58
62 void
63 reinit() override
64 {
66 newton_update.reinit(solutions.get_solution_full_vector());
67 }
68
72 void
73 solve_impl() override
74 {
75 const number newton_step_length = newton_params().step_length;
76 const number newton_tolerance =
78 unsigned int newton_max_iterations = newton_params().max_iterations;
79
80 BlockVector<number> &newton_residual = rhs_vector;
83 // TODO: setup initial guess for solution vector. Maybe use old_solution if
84 // available.
85 if (!solutions.get_primary_solutions().old_solutions.empty())
86 {
87 solutions.get_solution_full_vector() = solutions.get_old_solution_full_vector(0);
88 }
89
90 // Newton iteration loop.
91 bool newton_unconverged = true;
92 unsigned int iter = 0;
93 number l2_norm = -1.0;
94 int total_lin_iters = 0;
95 while (newton_unconverged && iter < newton_max_iterations)
96 {
97 // Apply constraints to solution vector
98 solutions.apply_constraints();
99 solutions.update_ghosts();
100
101 // Solve for Newton-residual (r)
102 Timer::start_section("Zero ghosts");
103 newton_residual.zero_out_ghost_values();
104 Timer::end_section("Zero ghosts");
105 rhs_op.compute_operator(newton_residual);
106 newton_residual.update_ghost_values();
107
108 // Check convergence.
109 l2_norm = newton_residual.l2_norm();
110 newton_unconverged = l2_norm > newton_tolerance;
111 if (!newton_unconverged || iter == newton_max_iterations)
112 {
113 continue;
114 }
115
116 // Solve for Newton update. (-dr/du|Du)
117 if (solutions.num_levels() > 1)
118 {
119 solutions.mg_transfer_down(
120 solve_context->get_dof_manager(),
121 solve_context->get_user_inputs().spatial_discretization.global_refinement,
122 false);
123 }
124 total_lin_iters += do_linear_solve(newton_residual, lhs_op, newton_update);
125 newton_update.update_ghost_values();
126
127 // Zero out the ghosts
128 solutions.get_solution_full_vector().zero_out_ghost_values();
129
130 // Perform Newton update.
131 solutions.get_solution_full_vector().add(newton_step_length, newton_update);
132
133 // Update the ghosts
134 Timer::start_section("Update ghosts");
135 solutions.update_ghosts();
136 Timer::end_section("Update ghosts");
137
138 iter++;
139 // Todo: implement some super simple backtracking. Something like if the residual
140 // increases instead of decreasing, try again with a smaller step length.
141 }
142 if (solve_context->get_user_inputs().output_parameters.should_output(
143 solve_context->get_simulation_timer().get_increment()))
144 {
146 << " Newton solve final residual : " << l2_norm / normalization_value()
147 << " Newton steps: " << iter << " Total linear steps: " << total_lin_iters
148 << "\n"
149 << std::flush;
150 }
151 if (iter >= newton_max_iterations)
152 {
154 << "[Increment " << solve_context->get_simulation_timer().get_increment()
155 << "] "
156 << "Warning: Newton solver did not converge before " << newton_max_iterations
157 << " iterations.\n\n";
158 }
159 }
160
161private:
163
164 [[nodiscard]] const NonlinearSolverParameters &
166 {
167 return solve_block.nonlinear_solver_parameters;
168 };
169};
170
171PRISMS_PF_END_NAMESPACE
static dealii::ConditionalOStream & pout_summary()
Log output stream for writing a summary.log file.
Definition conditional_ostreams.cc:35
static dealii::ConditionalOStream & pout_base()
Generic parallel output stream. Used for essential information in release and debug mode.
Definition conditional_ostreams.cc:44
MFOperator< dim, degree, number > rhs_operator
Matrix free operators.
Definition linear_solver.h:412
BlockVector< number > rhs_vector
Definition linear_solver.h:415
double normalization_value()
Definition linear_solver.h:418
int do_linear_solve(BlockVector< number > &b_vector, MFOperator< dim, degree, number > &lhs_matrix, BlockVector< number > &x_vector)
Definition linear_solver.h:354
MFOperator< dim, degree, number > lhs_operator
Definition linear_solver.h:414
void init(const std::list< SolveBlock > &all_solve_blocks) override
Initialize the solver.
Definition linear_solver.h:249
LinearSolver(SolveBlock _solve_block, const SolveContext< dim, degree, number > &_solve_context)
Constructor.
Definition linear_solver.h:240
void reinit() override
Reinitialize the solver.
Definition linear_solver.h:294
This class exists to evaluate a single user-defined operator for the matrix-free implementation of so...
Definition mf_operator.h:54
void compute_operator(BlockVector< number > &dst, const BlockVector< number > &src=BlockVector< number >()) const
Calls cell_loop on function that calls user-defined operator.
Definition mf_operator.cc:18
void reinit() override
Reinitialize the solver.
Definition newton_solver.h:63
BlockVector< number > newton_update
Definition newton_solver.h:162
void solve_impl() override
Solve for a single update step.
Definition newton_solver.h:73
const NonlinearSolverParameters & newton_params() const
Definition newton_solver.h:165
NewtonSolver(SolveBlock _solve_block, const SolveContext< dim, degree, number > &_solve_context)
Constructor.
Definition newton_solver.h:44
void init(const std::list< SolveBlock > &all_solve_blocks) override
Initialize the solver.
Definition newton_solver.h:53
Structure to hold the attributes of a solve-block.
Definition solve_block.h:59
This class provides context for a solver with ptrs to all the relevant dependencies.
Definition solve_context.h:34
SolverBase(SolveBlock _solve_block, const SolveContext< dim, degree, number > &_solve_context)
Constructor.
Definition solver_base.h:36
GroupSolutionHandler< dim, number > solutions
Solution vectors for fields handled by this solver.
Definition solver_base.h:293
const SolveContext< dim, degree, number > * solve_context
Solver context provides access to external information.
Definition solver_base.h:288
SolveBlock solve_block
Information about the solve block this handler is responsible for.
Definition solver_base.h:283
static void start_section(const char *name)
Start a new timer section.
Definition timer.cc:116
static void end_section(const char *name)
End the timer section.
Definition timer.cc:127
dealii::LinearAlgebra::distributed::BlockVector< number > BlockVector
Typedef for solution block vector.
Definition matrix_free_manager.h:32
Definition conditional_ostreams.cc:20
Struct that stores relevant nonlinear solve information of a certain field.
Definition nonlinear_solve_parameters.h:20
double step_length
Definition nonlinear_solve_parameters.h:22
double tolerance_value
Definition nonlinear_solve_parameters.h:28
unsigned int max_iterations
Definition nonlinear_solve_parameters.h:25