Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
PreconditionerRuntime.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* PreconditionerRuntime.h (C) 2000-2026 */
9/* */
10/* Runtime-configurable preconditioners. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_PRECONDITIONERRUNTIME_H
13#define ARCCORE_ALINA_PRECONDITIONERRUNTIME_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16/*
17 * This file is based on the work on AMGCL library (version march 2026)
18 * which can be found at https://github.com/ddemidov/amgcl.
19 *
20 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
21 * SPDX-License-Identifier: MIT
22 */
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26#include "arccore/alina/AlinaUtils.h"
27#include "arccore/alina/SolverRuntime.h"
28#include "arccore/alina/CoarseningRuntime.h"
29#include "arccore/alina/RelaxationRuntime.h"
30#include "arccore/alina/Relaxation.h"
31#include "arccore/alina/DummyPreconditioner.h"
32#include "arccore/alina/PreconditionedSolver.h"
33#include "arccore/alina/AMG.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane::Alina
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
45enum class ePreconditionerType
46{
47 amg,
48 relaxation,
49 dummy,
50 nested
51};
52
53inline std::ostream& operator<<(std::ostream& os, ePreconditionerType p)
54{
55 switch (p) {
56 case ePreconditionerType::amg:
57 return os << "amg";
58 case ePreconditionerType::relaxation:
59 return os << "relaxation";
60 case ePreconditionerType::dummy:
61 return os << "dummy";
62 case ePreconditionerType::nested:
63 return os << "nested";
64 default:
65 return os << "???";
66 }
67}
68
69inline std::istream& operator>>(std::istream& in, ePreconditionerType& p)
70{
71 std::string val;
72 in >> val;
73
74 if (val == "amg")
75 p = ePreconditionerType::amg;
76 else if (val == "relaxation")
77 p = ePreconditionerType::relaxation;
78 else if (val == "dummy")
79 p = ePreconditionerType::dummy;
80 else if (val == "nested")
81 p = ePreconditionerType::nested;
82 else
83 throw std::invalid_argument("Invalid preconditioner class. Valid choices are: "
84 "amg, relaxation, dummy, nested");
85
86 return in;
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
94template <class Backend>
95class PreconditionerRuntime
96{
97 public:
98
99 using backend_type = Backend;
100 using BackendType = Backend;
101
102 typedef typename Backend::value_type value_type;
103 typedef typename Backend::matrix matrix;
104 typedef typename Backend::vector vector;
105 typedef typename Backend::params backend_params;
106
107 typedef Alina::PropertyTree params;
108
109 template <class Matrix>
110 PreconditionerRuntime(const Alina::AlinaContext& context,
111 const Matrix& A,
112 params prm = params(),
113 const backend_params& bprm = backend_params())
114 : _class(prm.get("class", ePreconditionerType::amg))
115 , handle(0)
116 {
117 if (!prm.erase("class"))
118 ARCCORE_ALINA_PARAM_MISSING("class");
119 std::cout << "PreconditionerClass=" << _class << "\n";
120 switch (_class) {
121 case ePreconditionerType::amg: {
123 handle = new Precond(context, A, prm, bprm);
124 } break;
125 case ePreconditionerType::relaxation: {
127 handle = new Precond(context, A, prm, bprm);
128 } break;
129 case ePreconditionerType::dummy: {
131 handle = new Precond(context, A, prm, bprm);
132 } break;
133 case ePreconditionerType::nested: {
135 handle = new Precond(context, A, prm, bprm);
136 } break;
137 default:
138 ARCCORE_FATAL("Unsupported preconditioner class '{0}'", _class);
139 }
140 }
141
142 ~PreconditionerRuntime()
143 {
144 switch (_class) {
145 case ePreconditionerType::amg: {
147 delete static_cast<Precond*>(handle);
148 } break;
149 case ePreconditionerType::relaxation: {
151 delete static_cast<Precond*>(handle);
152 } break;
153 case ePreconditionerType::dummy: {
155 delete static_cast<Precond*>(handle);
156 } break;
157 case ePreconditionerType::nested: {
159 delete static_cast<Precond*>(handle);
160 } break;
161 default:
162 break;
163 }
164 }
165
166 template <class Matrix>
167 void rebuild(const Matrix& A, const backend_params& bprm = backend_params())
168 {
169 switch (_class) {
170 case ePreconditionerType::amg: {
172 static_cast<Precond*>(handle)->rebuild(A, bprm);
173 } break;
174 default:
175 std::cerr << "rebuild is a noop unless the preconditioner is AMG" << std::endl;
176 return;
177 }
178 }
179
180 template <class Vec1, class Vec2>
181 void apply(const Vec1& rhs, Vec2& x) const
182 {
183 switch (_class) {
184 case ePreconditionerType::amg: {
186 static_cast<Precond*>(handle)->apply(rhs, x);
187 } break;
188 case ePreconditionerType::relaxation: {
190 static_cast<Precond*>(handle)->apply(rhs, x);
191 } break;
192 case ePreconditionerType::dummy: {
194 static_cast<Precond*>(handle)->apply(rhs, x);
195 } break;
196 case ePreconditionerType::nested: {
198 static_cast<Precond*>(handle)->apply(rhs, x);
199 } break;
200 default:
201 throw std::invalid_argument("Unsupported preconditioner class");
202 }
203 }
204
205 std::shared_ptr<matrix> system_matrix_ptr() const
206 {
207 switch (_class) {
208 case ePreconditionerType::amg: {
210 return static_cast<Precond*>(handle)->system_matrix_ptr();
211 }
212 case ePreconditionerType::relaxation: {
214 return static_cast<Precond*>(handle)->system_matrix_ptr();
215 }
216 case ePreconditionerType::dummy: {
218 return static_cast<Precond*>(handle)->system_matrix_ptr();
219 }
220 case ePreconditionerType::nested: {
222 return static_cast<Precond*>(handle)->system_matrix_ptr();
223 }
224 default:
225 throw std::invalid_argument("Unsupported preconditioner class");
226 }
227 }
228
229 const matrix& system_matrix() const
230 {
231 return *system_matrix_ptr();
232 }
233
234 size_t size() const
235 {
236 return backend::nbRow(system_matrix());
237 }
238
239 size_t bytes() const
240 {
241 switch (_class) {
242 case ePreconditionerType::amg: {
244 return backend::bytes(*static_cast<Precond*>(handle));
245 }
246 case ePreconditionerType::relaxation: {
248 return backend::bytes(*static_cast<Precond*>(handle));
249 }
250 case ePreconditionerType::dummy: {
252 return backend::bytes(*static_cast<Precond*>(handle));
253 }
254 case ePreconditionerType::nested: {
256 return backend::bytes(*static_cast<Precond*>(handle));
257 }
258 default:
259 throw std::invalid_argument("Unsupported preconditioner class");
260 }
261 }
262
263 friend std::ostream& operator<<(std::ostream& os, const PreconditionerRuntime& p)
264 {
265 switch (p._class) {
266 case ePreconditionerType::amg: {
268 return os << *static_cast<Precond*>(p.handle);
269 }
270 case ePreconditionerType::relaxation: {
272 return os << *static_cast<Precond*>(p.handle);
273 }
274 case ePreconditionerType::dummy: {
276 return os << *static_cast<Precond*>(p.handle);
277 }
278 case ePreconditionerType::nested: {
280 return os << *static_cast<Precond*>(p.handle);
281 }
282 default:
283 throw std::invalid_argument("Unsupported preconditioner class");
284 }
285 }
286
287 private:
288
289 const ePreconditionerType _class;
290
291 void* handle = nullptr;
292};
293
294/*---------------------------------------------------------------------------*/
295/*---------------------------------------------------------------------------*/
296
297} // namespace Arcane::Alina
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
301
302#endif
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Algebraic multigrid method.
Definition AMG.h:71
Convenience class that bundles together a preconditioner and an iterative solver.
Class to store parameters as a hierarchical key/value tree.
Definition AlinaUtils.h:113
Allows to use an AMG smoother as standalone preconditioner.
Definition Relaxation.h:144
Dummy preconditioner using identity matrix.
Matrix class, to be used by user.