Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DistributedPreconditioner.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/* DistributedPreconditioner.h (C) 2000-2026 */
9/* */
10/* Runtime wrapper around mpi preconditioners. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_MPI_DISTRIBUTEDPRECONDITIONER_H
13#define ARCCORE_ALINA_MPI_DISTRIBUTEDPRECONDITIONER_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 <iostream>
27
28#include "arccore/alina/BuiltinBackend.h"
29#include "arccore/alina/DistributedAMG.h"
30#include "arccore/alina/DistributedInnerProduct.h"
31#include "arccore/alina/DistributedCoarseningRuntime.h"
32#include "arccore/alina/DistributedRelaxationRuntime.h"
33#include "arccore/alina/DistributedDirectSolverRuntime.h"
34#include "arccore/alina/MatrixPartitionerRuntime.h"
35#include "arccore/alina/DistributedRelaxation.h"
36#include "arccore/alina/DistributedMatrix.h"
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane::Alina
42{
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
48enum class eDistributedPreconditionerType
49{
50 amg,
51 relaxation
52};
53
54inline std::ostream& operator<<(std::ostream& os, eDistributedPreconditionerType p)
55{
56 switch (p) {
57 case eDistributedPreconditionerType::amg:
58 return os << "amg";
59 case eDistributedPreconditionerType::relaxation:
60 return os << "relaxation";
61 default:
62 return os << "???";
63 }
64}
65
66inline std::istream& operator>>(std::istream& in, eDistributedPreconditionerType& p)
67{
68 std::string val;
69 in >> val;
70
71 if (val == "amg")
72 p = eDistributedPreconditionerType::amg;
73 else if (val == "relaxation")
74 p = eDistributedPreconditionerType::relaxation;
75 else
76 throw std::invalid_argument("Invalid preconditioner class. "
77 "Valid choices are: amg, relaxation");
78
79 return in;
80}
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
87template <class Backend>
88class DistributedPreconditioner
89{
90 public:
91
92 using backend_type = Backend;
93 using BackendType = Backend;
94 typedef typename backend_type::params backend_params;
95 typedef PropertyTree params;
96 typedef typename backend_type::value_type value_type;
98
99 using AMGPrecondType = DistributedAMG<Backend,
104
105 template <class Matrix>
106 DistributedPreconditioner(mpi_communicator comm,
107 const Matrix& Astrip,
108 params prm = params(),
109 const backend_params& bprm = backend_params())
110 : _class(prm.get("class", eDistributedPreconditionerType::amg))
111 , handle(0)
112 {
113 init(std::make_shared<matrix>(comm, Astrip, backend::nbRow(Astrip)), prm, bprm);
114 }
115
116 DistributedPreconditioner(mpi_communicator,
117 std::shared_ptr<matrix> A,
118 params prm = params(),
119 const backend_params& bprm = backend_params())
120 : _class(prm.get("class", eDistributedPreconditionerType::amg))
121 , handle(0)
122 {
123 init(A, prm, bprm);
124 }
125
126 ~DistributedPreconditioner()
127 {
128 switch (_class) {
129 case eDistributedPreconditionerType::amg: {
130 delete static_cast<AMGPrecondType*>(handle);
131 } break;
132 case eDistributedPreconditionerType::relaxation: {
134 Precond;
135
136 delete static_cast<Precond*>(handle);
137 } break;
138 default:
139 break;
140 }
141 }
142
143 template <class Matrix>
144 void rebuild(const Matrix& A,
145 const backend_params& bprm = backend_params())
146 {
147 switch (_class) {
148 case eDistributedPreconditionerType::amg: {
149 static_cast<AMGPrecondType*>(handle)->rebuild(A, bprm);
150 } break;
151 default:
152 std::cerr << "rebuild is a noop unless the preconditioner is AMG" << std::endl;
153 return;
154 }
155 }
156
157 template <class Vec1, class Vec2>
158 void apply(const Vec1& rhs, Vec2&& x) const
159 {
160 switch (_class) {
161 case eDistributedPreconditionerType::amg: {
162 static_cast<AMGPrecondType*>(handle)->apply(rhs, x);
163 } break;
164 case eDistributedPreconditionerType::relaxation: {
166
167 static_cast<Precond*>(handle)->apply(rhs, x);
168 } break;
169 default:
170 throw std::invalid_argument("Unsupported preconditioner class");
171 }
172 }
173
175 std::shared_ptr<matrix> system_matrix_ptr() const
176 {
177 switch (_class) {
178 case eDistributedPreconditionerType::amg: {
179 return static_cast<AMGPrecondType*>(handle)->system_matrix_ptr();
180 }
181 case eDistributedPreconditionerType::relaxation: {
183
184 return static_cast<Precond*>(handle)->system_matrix_ptr();
185 }
186 default:
187 throw std::invalid_argument("Unsupported preconditioner class");
188 }
189 }
190
191 const matrix& system_matrix() const
192 {
193 return *system_matrix_ptr();
194 }
195
196 friend std::ostream& operator<<(std::ostream& os, const DistributedPreconditioner& p)
197 {
198 switch (p._class) {
199 case eDistributedPreconditionerType::amg: {
200 return os << *static_cast<AMGPrecondType*>(p.handle);
201 }
202 case eDistributedPreconditionerType::relaxation: {
203 typedef AsDistributedPreconditioner<DistributedRelaxationRuntime<Backend>> Precond;
204
205 return os << *static_cast<Precond*>(p.handle);
206 }
207 default:
208 throw std::invalid_argument("Unsupported preconditioner class");
209 }
210 }
211
212 private:
213
214 eDistributedPreconditionerType _class;
215 void* handle;
216
217 void init(std::shared_ptr<matrix> A, params& prm, const backend_params& bprm)
218 {
219 if (!prm.erase("class"))
220 ARCCORE_ALINA_PARAM_MISSING("class");
221
222 switch (_class) {
223 case eDistributedPreconditionerType::amg: {
224 handle = static_cast<void*>(new AMGPrecondType(A->comm(), A, prm, bprm));
225 } break;
226 case eDistributedPreconditionerType::relaxation: {
227 typedef AsDistributedPreconditioner<DistributedRelaxationRuntime<Backend>> Precond;
228
229 handle = static_cast<void*>(new Precond(A->comm(), A, prm, bprm));
230 } break;
231 default:
232 throw std::invalid_argument("Unsupported preconditioner class");
233 }
234 }
235};
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
242template <class Precond>
243class DistributedBlockPreconditioner
244{
245 public:
246
247 typedef typename Precond::params params;
248 typedef typename Precond::backend_type backend_type;
249 using BackendType = backend_type;
250 typedef typename backend_type::params backend_params;
251
252 typedef typename backend_type::value_type value_type;
253 typedef typename backend_type::matrix bmatrix;
254 typedef DistributedMatrix<backend_type> matrix;
255
256 template <class Matrix>
257 DistributedBlockPreconditioner(mpi_communicator comm,
258 const Matrix& Astrip,
259 const params& prm = params(),
260 const backend_params& bprm = backend_params())
261 {
262 A = std::make_shared<matrix>(comm, Astrip, backend::nbRow(Astrip));
263 P = std::make_shared<Precond>(A->local(), prm, bprm);
264 A->set_local(P->system_matrix_ptr());
265 A->move_to_backend(bprm);
266 }
267
268 DistributedBlockPreconditioner(mpi_communicator,
269 std::shared_ptr<matrix> A,
270 const params& prm = params(),
271 const backend_params& bprm = backend_params())
272 : A(A)
273 {
274 P = std::make_shared<Precond>(A->local(), prm, bprm);
275 A->set_local(P->system_matrix_ptr());
276 A->move_to_backend(bprm);
277 }
278
279 std::shared_ptr<matrix> system_matrix_ptr() const
280 {
281 return A;
282 }
283
284 const matrix& system_matrix() const
285 {
286 return *A;
287 }
288
289 template <class Vec1, class Vec2>
290 void apply(const Vec1& rhs, Vec2&& x) const
291 {
292 P->apply(rhs, x);
293 }
294
295 private:
296
297 std::shared_ptr<matrix> A;
298 std::shared_ptr<Precond> P;
299};
300
301/*---------------------------------------------------------------------------*/
302/*---------------------------------------------------------------------------*/
303
304} // namespace Arcane::Alina
305
306/*---------------------------------------------------------------------------*/
307/*---------------------------------------------------------------------------*/
308
309#endif
Runtime wrapper for distributed direct solvers.
Distributed Matrix using message passing.
std::shared_ptr< matrix > system_matrix_ptr() const
Returns the system matrix from the finest level.
Matrix class, to be used by user.
Use a relaxation as a distributed preconditioner.
Distributed memory sparse approximate inverse relaxation scheme.
Runtime-configurable wrapper around matrix partitioner.
Convenience wrapper around MPI_Comm.