PRISMS-PF Manual
Loading...
Searching...
No Matches
linear_solve_parameters.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/base/exceptions.h>
7#include <deal.II/base/parameter_handler.h>
8#include <deal.II/lac/precondition.h>
9#include <deal.II/lac/solver_selector.h>
10
13#include <prismspf/core/types.h>
14
15#include <prismspf/config.h>
16
17#include <map>
18
20
25{
26 // Solver type. richardson|cg|bicgstab|gmres|fgmres|minres
27 std::string solver_type = "cg";
28
29 // Solver tolerance
31
32 // Solver tolerance type
34
35 // Max number of iterations for the linear solve
37
38 // Preconditioner
40
41 dealii::PreconditionChebyshev<>::AdditionalData chebyshev_parameters;
42
43 dealii::SolverRichardson<>::AdditionalData richardson_parameters;
44 dealii::SolverBicgstab<>::AdditionalData bicgstab_parameters;
45 dealii::SolverGMRES<>::AdditionalData gmres_parameters;
46
47 // MinRes and CG do not have additional parameters, so we do not need to store them here
48 // dealii::SolverMinRes<>::AdditionalData minres_parameters;
49 // dealii::SolverCG<>::AdditionalData cg_parameters;
50 // FGMRES additional parameters are a subset of GMRES parameters, so we can just use
51 // gmres_parameters for both solvers
52 // dealii::SolverFGMRES<>::AdditionalData fgmres_parameters;
53
54 // The multigrid depth
55 unsigned int mg_depth = 1;
56};
57
62{
66 void
67 validate();
68
72 void
74
78 void
79 declare_parameters(dealii::ParameterHandler &parameter_handler,
80 unsigned int max_criteria = 5) const;
81
85 void
86 assign_parameters(dealii::ParameterHandler &parameter_handler,
87 unsigned int max_criteria = 5);
88
89 // Map of linear solve parameters for fields that require them
90 std::map<unsigned int, LinearSolverParameters> linear_solvers;
91};
92
93inline void
95{
96 // Nothing to do here for now
97}
98
99inline void
101{
102 if (!linear_solvers.empty())
103 {
105 << "================================================\n"
106 << " Linear Solve Parameters\n"
107 << "================================================\n";
108
109 for (const auto &[index, linear_solver_parameters] : linear_solvers)
110 {
112 << "Index: " << index << "\n"
113 << " Tolerance: " << linear_solver_parameters.tolerance << "\n"
114 << " Type: " << to_string(linear_solver_parameters.tolerance_type) << "\n"
115 << " Max iterations: " << linear_solver_parameters.max_iterations << "\n"
116 << " Preconditioner: " << to_string(linear_solver_parameters.preconditioner)
117 << "\n";
118
119 if (linear_solver_parameters.preconditioner == PreconditionerType::GMG)
120 {
121 // ConditionalOStreams::pout_summary();
122 }
123 }
124
125 ConditionalOStreams::pout_summary() << "\n" << std::flush;
126 }
127}
128
129inline void
130LinearSolveParameters::declare_parameters(dealii::ParameterHandler &parameter_handler,
131 unsigned int max_criteria) const
132{
133 for (unsigned int criterion_id = 0; criterion_id < max_criteria; criterion_id++)
134 {
135 // For linear solves
136 std::string subsection_text =
137 "linear solver parameters: " + std::to_string(criterion_id);
138 parameter_handler.enter_subsection(subsection_text);
139 {
140 parameter_handler.declare_entry(
141 "solver_ids",
142 "",
143 dealii::Patterns::Anything(),
144 "The ids of the solvers that will use these settings.");
145 parameter_handler.declare_entry(
146 "solver type",
147 "cg",
148 dealii::Patterns::Selection(dealii::SolverSelector<>::get_solver_names()),
149 "The type of iterative solver to use for linear solves.");
150 parameter_handler.declare_entry(
151 "tolerance type",
152 "AbsoluteResidual",
153 dealii::Patterns::Selection("AbsoluteResidual|RMSEPerField|IntegratedPerField|"
154 "RMSETotal|IntegratedTotal"),
155 "The tolerance type for the linear solver.");
156 parameter_handler.declare_entry("tolerance value",
157 "1.0e-10",
158 dealii::Patterns::Double(DBL_MIN, DBL_MAX),
159 "The value of for the linear solver tolerance.");
160 parameter_handler.declare_entry(
161 "max iterations",
162 "100",
163 dealii::Patterns::Integer(1, INT_MAX),
164 "The maximum number of linear solver iterations before the loop "
165 "is stopped.");
166 parameter_handler.declare_entry(
167 "preconditioner type",
168 "None",
169 dealii::Patterns::Selection(
170 "|None|Chebyshev|GMG|none|chebyshev|gmg|MG|mg|multigrid"),
171 "The preconditioner type for the linear solver.");
172 parameter_handler.enter_subsection("Chebyshev");
173 {
174 parameter_handler.declare_entry("smoothing range",
175 "15.0",
176 dealii::Patterns::Double(DBL_MIN, DBL_MAX),
177 "The smoothing range for eigenvalues.");
178 parameter_handler.declare_entry("smoother degree",
179 "5",
180 dealii::Patterns::Integer(1, INT_MAX),
181 "The smoother polynomial degree.");
182 parameter_handler.declare_entry(
183 "eigenvalue cg iterations",
184 "10",
185 dealii::Patterns::Integer(1, INT_MAX),
186 "The maximum number of CG iterations used to find the maximum eigenvalue.");
187 }
188 parameter_handler.leave_subsection();
189 parameter_handler.enter_subsection("Richardson");
190 {
191 parameter_handler.declare_entry("omega",
192 "1.0",
193 dealii::Patterns::Double(),
194 "Damping factor.");
195 parameter_handler.declare_entry("use preconditioned residual",
196 "false",
197 dealii::Patterns::Bool(),
198 "Whether to use the preconditioned residual l2 "
199 "norm in the stopping criterion.");
200 }
201 parameter_handler.leave_subsection();
202 parameter_handler.enter_subsection("BiCGStab");
203 {
204 parameter_handler.declare_entry("exact residual",
205 "true",
206 dealii::Patterns::Bool(),
207 "Flag for exact computation of residual.");
208 parameter_handler.declare_entry("breakdown",
209 std::to_string(
210 std::numeric_limits<double>::min()),
211 dealii::Patterns::Double(),
212 "Breakdown threshold.");
213 }
214 parameter_handler.leave_subsection();
215 parameter_handler.enter_subsection("GMRES");
216 {
217 parameter_handler.declare_entry(
218 "max basis size",
219 "30",
220 dealii::Patterns::Integer(1, INT_MAX),
221 "The maximum size of the Krylov basis used in GMRES before restarting.");
222 parameter_handler.declare_entry(
223 "orthogonalization strategy",
224 "delayed_classical_gram_schmidt",
225 dealii::Patterns::Selection("classical_gram_schmidt|modified_gram_schmidt|"
226 "delayed_classical_gram_schmidt"),
227 "The orthogonalization strategy to use in GMRES.");
228 parameter_handler.declare_entry("right preconditioning",
229 "false",
230 dealii::Patterns::Bool(),
231 "Whether to use right preconditioning.");
232 parameter_handler.declare_entry(
233 "use default residual",
234 "true",
235 dealii::Patterns::Bool(),
236 "Whether to use the default residual computation in GMRES.");
237 parameter_handler.declare_entry(
238 "force re-orthogonalization",
239 "false",
240 dealii::Patterns::Bool(),
241 "Whether to force re-orthogonalization of the Krylov basis in GMRES.");
242 parameter_handler.declare_entry("batched mode",
243 "false",
244 dealii::Patterns::Bool(),
245 "Whether to use batched mode in GMRES.");
246 }
247 parameter_handler.leave_subsection();
248
249 parameter_handler.declare_entry("mg depth",
250 "1",
251 dealii::Patterns::Integer(1, INT_MAX),
252 "The depth of the multigrid hierarchy.");
253
254 parameter_handler.declare_alias("tolerance value", "tolerance");
255 parameter_handler.declare_alias("solver_ids", "solve blocks");
256 parameter_handler.declare_alias("solver_ids", "solve_blocks");
257 parameter_handler.declare_alias("solver_ids", "solve block ids");
258 parameter_handler.declare_alias("solver_ids", "solve_block_ids");
259 parameter_handler.declare_alias("solver type", "solver_type");
260 parameter_handler.declare_alias("solver type", "linear solver type");
261 parameter_handler.declare_alias("solver type", "linear_solver_type");
262 parameter_handler.declare_alias("solver type", "linear solver");
263 parameter_handler.declare_alias("solver type", "linear_solver");
264 parameter_handler.declare_alias("solver type", "type");
265 parameter_handler.declare_alias("preconditioner type", "preconditioner_type");
266 parameter_handler.declare_alias("preconditioner type", "preconditioner");
267 parameter_handler.declare_alias("mg depth", "mg_depth");
268 }
269 parameter_handler.leave_subsection();
270 }
271}
272
273inline void
274LinearSolveParameters::assign_parameters(dealii::ParameterHandler &parameter_handler,
275 unsigned int max_criteria)
276{
277 for (unsigned int criterion_id = 0; criterion_id < max_criteria; criterion_id++)
278 {
279 // For linear solves
280 std::string subsection_text =
281 "linear solver parameters: " + std::to_string(criterion_id);
282 parameter_handler.enter_subsection(subsection_text);
283 {
284 std::vector<int> solver_ids = dealii::Utilities::string_to_int(
285 dealii::Utilities::split_string_list(parameter_handler.get("solver_ids")));
286
287 LinearSolverParameters linear_solver_parameters;
288
289 // Set the linear solver type
290 linear_solver_parameters.solver_type = parameter_handler.get("solver type");
291
292 // Set the tolerance type
293 static const std::map<std::string, SolverToleranceType> tolerance_types = {
294 {"AbsoluteResidual", AbsoluteResidual },
295 {"RMSEPerField", RMSEPerField },
296 {"IntegratedPerField", IntegratedPerField},
297 {"RMSETotal", RMSETotal },
298 {"IntegratedTotal", IntegratedTotal },
299 };
300 const std::string type_string = parameter_handler.get("tolerance type");
301 const auto &iter = tolerance_types.find(type_string);
302 if (iter != tolerance_types.end())
303 {
304 linear_solver_parameters.tolerance_type = iter->second;
305 }
306 else
307 {
308 AssertThrow(false,
309 dealii::ExcMessage("Invalid tolerance type: " + type_string));
310 }
311
312 // Set the tolerance value
313 linear_solver_parameters.tolerance =
314 parameter_handler.get_double("tolerance value");
315
316 // Set the maximum number of iterations
317 linear_solver_parameters.max_iterations =
318 static_cast<unsigned int>(parameter_handler.get_integer("max iterations"));
319
320 // Set preconditioner type and related parameters
321 static const std::map<std::string, PreconditionerType> preconditioner_map = {
322 {"None", None },
323 {"none", None },
324 {"", None },
325 {"Chebyshev", Chebyshev},
326 {"chebyshev", Chebyshev},
327 {"GMG", GMG },
328 {"gmg", GMG },
329 {"MG", GMG },
330 {"mg", GMG },
331 {"multigrid", GMG }
332 };
333 linear_solver_parameters.preconditioner =
334 preconditioner_map.at(parameter_handler.get("preconditioner type"));
335
336 parameter_handler.enter_subsection("Chebyshev");
337 {
338 linear_solver_parameters.chebyshev_parameters.degree =
339 static_cast<unsigned int>(parameter_handler.get_integer("smoother degree"));
340
341 linear_solver_parameters.chebyshev_parameters.smoothing_range =
342 parameter_handler.get_double("smoothing range");
343
344 linear_solver_parameters.chebyshev_parameters.eig_cg_n_iterations =
345 static_cast<unsigned int>(
346 parameter_handler.get_integer("eigenvalue cg iterations"));
347 }
348 parameter_handler.leave_subsection();
349 parameter_handler.enter_subsection("Richardson");
350 {
351 linear_solver_parameters.richardson_parameters.omega =
352 parameter_handler.get_double("omega");
353 linear_solver_parameters.richardson_parameters.use_preconditioned_residual =
354 parameter_handler.get_bool("use preconditioned residual");
355 }
356 parameter_handler.leave_subsection();
357 parameter_handler.enter_subsection("BiCGStab");
358 {
359 linear_solver_parameters.bicgstab_parameters.exact_residual =
360 parameter_handler.get_bool("exact residual");
361 linear_solver_parameters.bicgstab_parameters.breakdown =
362 parameter_handler.get_double("breakdown");
363 }
364 parameter_handler.leave_subsection();
365 parameter_handler.enter_subsection("GMRES");
366 {
367 using OStrat = dealii::LinearAlgebra::OrthogonalizationStrategy;
368 static const std::map<std::string, OStrat> orthogonalization_strategy_names = {
369 {"classical_gram_schmidt", OStrat::classical_gram_schmidt },
370 {"modified_gram_schmidt", OStrat::modified_gram_schmidt },
371 {"delayed_classical_gram_schmidt", OStrat::delayed_classical_gram_schmidt}
372 };
373 linear_solver_parameters.gmres_parameters.orthogonalization_strategy =
374 orthogonalization_strategy_names.at(
375 parameter_handler.get("orthogonalization strategy"));
376 linear_solver_parameters.gmres_parameters.right_preconditioning =
377 parameter_handler.get_bool("right preconditioning");
378 linear_solver_parameters.gmres_parameters.use_default_residual =
379 parameter_handler.get_bool("use default residual");
380 linear_solver_parameters.gmres_parameters.force_re_orthogonalization =
381 parameter_handler.get_bool("force re-orthogonalization");
382 linear_solver_parameters.gmres_parameters.batched_mode =
383 parameter_handler.get_bool("batched mode");
384 }
385 parameter_handler.leave_subsection();
386
387 linear_solver_parameters.mg_depth =
388 static_cast<unsigned int>(parameter_handler.get_integer("mg depth"));
389 for (auto solver_id : solver_ids)
390 {
391 linear_solvers[static_cast<unsigned int>(solver_id)] =
392 linear_solver_parameters;
393 }
394 }
395 parameter_handler.leave_subsection();
396 }
397}
398
399PRISMS_PF_END_NAMESPACE
static dealii::ConditionalOStream & pout_summary()
Log output stream for writing a summary.log file.
Definition conditional_ostreams.cc:35
static const unsigned int iterations
Default iterations.
Definition types.h:67
static const double tolerance
Default tolerance.
Definition types.h:57
Definition conditional_ostreams.cc:20
Struct that holds linear solver parameters.
Definition linear_solve_parameters.h:62
void validate()
Postprocess and validate parameters.
Definition linear_solve_parameters.h:94
std::map< unsigned int, LinearSolverParameters > linear_solvers
Definition linear_solve_parameters.h:90
void assign_parameters(dealii::ParameterHandler &parameter_handler, unsigned int max_criteria=5)
Assign the parameters read from an input file to this object.
Definition linear_solve_parameters.h:274
void print_parameter_summary() const
Print parameters to summary.log.
Definition linear_solve_parameters.h:100
void declare_parameters(dealii::ParameterHandler &parameter_handler, unsigned int max_criteria=5) const
Declare the parameters to be read from an input file.
Definition linear_solve_parameters.h:130
Struct that stores relevant linear solve information of a certain solve block.
Definition linear_solve_parameters.h:25
unsigned int max_iterations
Definition linear_solve_parameters.h:36
double tolerance
Definition linear_solve_parameters.h:30
dealii::SolverGMRES ::AdditionalData gmres_parameters
Definition linear_solve_parameters.h:45
SolverToleranceType tolerance_type
Definition linear_solve_parameters.h:33
dealii::PreconditionChebyshev ::AdditionalData chebyshev_parameters
Definition linear_solve_parameters.h:41
PreconditionerType preconditioner
Definition linear_solve_parameters.h:39
std::string solver_type
Definition linear_solve_parameters.h:27
dealii::SolverBicgstab ::AdditionalData bicgstab_parameters
Definition linear_solve_parameters.h:44
dealii::SolverRichardson ::AdditionalData richardson_parameters
Definition linear_solve_parameters.h:43
unsigned int mg_depth
Definition linear_solve_parameters.h:55
SolverToleranceType
Solver tolerance type.
Definition type_enums.h:112
@ RMSEPerField
The mean local error averaged over each field is lower than the tolerance.
Definition type_enums.h:124
@ IntegratedTotal
The sum of the integrated errors of each field is lower than the tolerance.
Definition type_enums.h:136
@ AbsoluteResidual
Legacy.
Definition type_enums.h:116
@ RMSETotal
The sum of the average local errors of each field is lower than the tolerance.
Definition type_enums.h:132
@ IntegratedPerField
The integrated error averaged over each field is lower than the tolerance.
Definition type_enums.h:128
std::string to_string(ElasticityModel type)
Enum to string for ElasticityModel.
Definition type_enums.h:164
PreconditionerType
Preconditioner type.
Definition type_enums.h:143
@ Chebyshev
Definition type_enums.h:145
@ None
Definition type_enums.h:144
@ GMG
Definition type_enums.h:146