Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DeflatedSolver.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/* DeflatedSolver.h (C) 2000-2026 */
9/* */
10/* Iterative preconditioned solver with deflation. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_DEFLATEDSOLVER_H
13#define ARCCORE_ALINA_DEFLATEDSOLVER_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/BuiltinBackend.h"
27#include "arccore/alina/AlinaUtils.h"
28#include "arccore/alina/DenseMatrixInverseImpl.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::Alina
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
41template <class Precond, class IterativeSolver>
44{
45 static_assert(backend::backends_compatible<
46 typename IterativeSolver::backend_type,
47 typename Precond::backend_type>::value,
48 "Backends for preconditioner and iterative solver should be compatible");
49
50 public:
51
52 typedef typename IterativeSolver::backend_type backend_type;
53 typedef typename backend_type::matrix matrix;
54 typedef typename backend_type::vector vector;
55
56 typedef typename backend_type::value_type value_type;
57 typedef typename backend_type::params backend_params;
58 typedef typename BuiltinBackend<value_type>::matrix build_matrix;
59
60 typedef typename math::scalar_of<value_type>::type scalar_type;
61
66 struct params
67 {
68 int nvec = 0;
69 scalar_type* vec = nullptr;
70
71 typename Precond::params precond;
72 typename IterativeSolver::params solver;
73
74 params() = default;
75
76 params(const PropertyTree& p)
77 : ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, nvec)
78 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, vec)
79 , ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, precond)
80 , ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, solver)
81 {
82 p.check_params({ "nvec", "vec", "precond", "solver" });
83 }
84
85 void get(PropertyTree& p, const std::string& path = "") const
86 {
87 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, nvec);
88 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, vec);
89 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, precond);
90 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, solver);
91 }
92 };
93
95 template <class Matrix>
97 const params& prm = params(),
98 const backend_params& bprm = backend_params())
99 : prm(prm)
100 , n(backend::nbRow(A))
101 , P(A, prm.precond, bprm)
102 , S(backend::nbRow(A), prm.solver, bprm)
103 , r(backend_type::create_vector(n, bprm))
104 , Z(prm.nvec)
105 , E(prm.nvec * prm.nvec, 0)
106 , d(prm.nvec)
107 {
108 init(A, bprm);
109 }
110
111 // Constructs the preconditioner and creates iterative solver.
112 // Takes shared pointer to the matrix in internal format.
113 DeflatedSolver(std::shared_ptr<build_matrix> A,
114 const params& prm = params(),
115 const backend_params& bprm = backend_params())
116 : prm(prm)
117 , n(backend::nbRow(*A))
118 , P(A, prm.precond, bprm)
119 , S(backend::nbRow(*A), prm.solver, bprm)
120 , r(backend_type::create_vector(n, bprm))
121 , Z(prm.nvec)
122 , E(prm.nvec * prm.nvec, 0)
123 , d(prm.nvec)
124 {
125 init(*A, bprm);
126 }
127
128 template <class Matrix>
129 void init(const Matrix& A, const backend_params& bprm)
130 {
131 precondition(prm.nvec > 0 && prm.vec != nullptr, "Deflation vectors are not set!");
132
133 for (int i = 0; i < prm.nvec; ++i) {
134 SmallSpan<scalar_type> irange(prm.vec + n * i, n);
135 Z[i] = backend_type::copy_vector(std::make_shared<numa_vector<scalar_type>>(irange), bprm);
136 }
137
138 std::vector<scalar_type> AZ(prm.nvec);
139 std::fill(E.begin(), E.end(), math::zero<scalar_type>());
140 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(n); ++i) {
141 std::fill(AZ.begin(), AZ.end(), math::zero<scalar_type>());
142 for (auto a = backend::row_begin(A, i); a; ++a) {
143 for (int j = 0; j < prm.nvec; ++j) {
144 AZ[j] += a.value() * prm.vec[j * n + a.col()];
145 }
146 }
147
148 for (int ii = 0, k = 0; ii < prm.nvec; ++ii) {
149 for (int jj = 0; jj < prm.nvec; ++jj, ++k) {
150 E[k] += prm.vec[i + ii * n] * AZ[jj];
151 }
152 }
153 }
154
155 std::vector<scalar_type> t(E.size());
156 std::vector<int> p(prm.nvec);
157 detail::inverse(prm.nvec, E.data(), t.data(), p.data());
158 }
159
177 template <class Matrix, class Vec1, class Vec2>
178 SolverResult operator()(const Matrix& A, const Vec1& rhs, Vec2&& x) const
179 {
180 project(rhs, x);
181 return S(A, *this, rhs, x);
182 }
183
192 template <class Vec1, class Vec2>
193 SolverResult operator()(const Vec1& rhs, Vec2&& x) const
194 {
195 project(rhs, x);
196 return S(*this, rhs, x);
197 }
198
199 template <class Vec1, class Vec2>
200 void apply(const Vec1& rhs, Vec2&& x) const
201 {
202 P.apply(rhs, x);
203 project(rhs, x);
204 }
205
206 template <class Vec1, class Vec2>
207 void project(const Vec1& b, Vec2& x) const
208 {
209 // x += Z^T E^{-1} Z (b - Ax)
210 backend::residual(b, P.system_matrix(), x, *r);
211 std::fill(d.begin(), d.end(), math::zero<scalar_type>());
212 for (int j = 0; j < prm.nvec; ++j) {
213 auto fj = backend::inner_product(*Z[j], *r);
214 for (int i = 0; i < prm.nvec; ++i)
215 d[i] += E[i * prm.nvec + j] * fj;
216 }
217 backend::lin_comb(prm.nvec, d, Z, 1, x);
218 }
219
221 const Precond& precond() const
222 {
223 return P;
224 }
225
227 Precond& precond()
228 {
229 return P;
230 }
231
233 const IterativeSolver& solver() const
234 {
235 return S;
236 }
237
239 std::shared_ptr<typename Precond::matrix> system_matrix_ptr() const
240 {
241 return P.system_matrix_ptr();
242 }
243
244 typename Precond::matrix const& system_matrix() const
245 {
246 return P.system_matrix();
247 }
248
251 {
252 prm.get(p);
253 }
254
256 size_t size() const
257 {
258 return n;
259 }
260
261 size_t bytes() const
262 {
263 return backend::bytes(S) + backend::bytes(P);
264 }
265
266 friend std::ostream& operator<<(std::ostream& os, const DeflatedSolver& p)
267 {
268 return os << "Solver\n======\n"
269 << p.S << std::endl
270 << "Preconditioner\n==============\n"
271 << p.P;
272 }
273
274 public:
275
276 params prm;
277
278 private:
279
280 size_t n;
281 Precond P;
282 IterativeSolver S;
283 std::shared_ptr<vector> r;
284 std::vector<std::shared_ptr<vector>> Z;
285 std::vector<scalar_type> E;
286 mutable std::vector<scalar_type> d;
287};
288
289/*---------------------------------------------------------------------------*/
290/*---------------------------------------------------------------------------*/
291
292} // namespace Arcane::Alina
293
294/*---------------------------------------------------------------------------*/
295/*---------------------------------------------------------------------------*/
296
297#endif
Precond & precond()
Returns reference to the constructed preconditioner.
void get_params(Alina::PropertyTree &p) const
Stores the parameters used during construction into the property tree p.
const Precond & precond() const
Returns reference to the constructed preconditioner.
std::shared_ptr< typename Precond::matrix > system_matrix_ptr() const
Returns the system matrix in the backend format.
SolverResult operator()(const Matrix &A, const Vec1 &rhs, Vec2 &&x) const
Computes the solution for the given system matrix.
size_t size() const
Returns the size of the system matrix.
SolverResult operator()(const Vec1 &rhs, Vec2 &&x) const
Computes the solution for the given right-hand.
const IterativeSolver & solver() const
Returns reference to the constructed iterative solver.
DeflatedSolver(const Matrix &A, const params &prm=params(), const backend_params &bprm=backend_params())
Result of a solving.
Definition AlinaUtils.h:52
Matrix class, to be used by user.
Vue d'un tableau d'éléments de type T.
Definition Span.h:801
Combined parameters of the bundled preconditioner and the iterative solver.
IterativeSolver::params solver
Iterative solver parameters.
scalar_type * vec
Deflation vectors as a [nvec x n] matrix.
Precond::params precond
Preconditioner parameters.
int nvec
The number of deflation vectors.
Metafunction that checks if two backends are compatible.