Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
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 Matrix& A,
98 const params& prm = params(),
99 const backend_params& bprm = backend_params())
100 : prm(prm)
101 , n(backend::nbRow(A))
102 , P(context, A, prm.precond, bprm)
103 , S(context, backend::nbRow(A), prm.solver, bprm)
104 , r(backend_type::create_vector(n, bprm))
105 , Z(prm.nvec)
106 , E(prm.nvec * prm.nvec, 0)
107 , d(prm.nvec)
108 {
109 init(A, bprm);
110 }
111
112 // Constructs the preconditioner and creates iterative solver.
113 // Takes shared pointer to the matrix in internal format.
114 DeflatedSolver(const AlinaContext& context,
115 std::shared_ptr<build_matrix> A,
116 const params& prm = params(),
117 const backend_params& bprm = backend_params())
118 : prm(prm)
119 , n(backend::nbRow(*A))
120 , P(context, A, prm.precond, bprm)
121 , S(context, backend::nbRow(*A), prm.solver, bprm)
122 , r(backend_type::create_vector(n, bprm))
123 , Z(prm.nvec)
124 , E(prm.nvec * prm.nvec, 0)
125 , d(prm.nvec)
126 {
127 init(*A, bprm);
128 }
129
130 template <class Matrix>
131 void init(const Matrix& A, const backend_params& bprm)
132 {
133 precondition(prm.nvec > 0 && prm.vec != nullptr, "Deflation vectors are not set!");
134
135 for (int i = 0; i < prm.nvec; ++i) {
136 SmallSpan<scalar_type> irange(prm.vec + n * i, n);
137 Z[i] = backend_type::copy_vector(std::make_shared<numa_vector<scalar_type>>(irange), bprm);
138 }
139
140 std::vector<scalar_type> AZ(prm.nvec);
141 std::fill(E.begin(), E.end(), math::zero<scalar_type>());
142 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(n); ++i) {
143 std::fill(AZ.begin(), AZ.end(), math::zero<scalar_type>());
144 for (auto a = backend::row_begin(A, i); a; ++a) {
145 for (int j = 0; j < prm.nvec; ++j) {
146 AZ[j] += a.value() * prm.vec[j * n + a.col()];
147 }
148 }
149
150 for (int ii = 0, k = 0; ii < prm.nvec; ++ii) {
151 for (int jj = 0; jj < prm.nvec; ++jj, ++k) {
152 E[k] += prm.vec[i + ii * n] * AZ[jj];
153 }
154 }
155 }
156
157 std::vector<scalar_type> t(E.size());
158 std::vector<int> p(prm.nvec);
159 detail::inverse(prm.nvec, E.data(), t.data(), p.data());
160 }
161
179 template <class Matrix, class Vec1, class Vec2>
180 SolverResult operator()(const Matrix& A, const Vec1& rhs, Vec2&& x) const
181 {
182 project(rhs, x);
183 return S(A, *this, rhs, x);
184 }
185
194 template <class Vec1, class Vec2>
195 SolverResult operator()(const Vec1& rhs, Vec2&& x) const
196 {
197 project(rhs, x);
198 return S(*this, rhs, x);
199 }
200
201 template <class Vec1, class Vec2>
202 void apply(const Vec1& rhs, Vec2&& x) const
203 {
204 P.apply(rhs, x);
205 project(rhs, x);
206 }
207
208 template <class Vec1, class Vec2>
209 void project(const Vec1& b, Vec2& x) const
210 {
211 // x += Z^T E^{-1} Z (b - Ax)
212 backend::residual(b, P.system_matrix(), x, *r);
213 std::fill(d.begin(), d.end(), math::zero<scalar_type>());
214 for (int j = 0; j < prm.nvec; ++j) {
215 auto fj = backend::inner_product(*Z[j], *r);
216 for (int i = 0; i < prm.nvec; ++i)
217 d[i] += E[i * prm.nvec + j] * fj;
218 }
219 backend::lin_comb(prm.nvec, d, Z, 1, x);
220 }
221
223 const Precond& precond() const
224 {
225 return P;
226 }
227
229 Precond& precond()
230 {
231 return P;
232 }
233
235 const IterativeSolver& solver() const
236 {
237 return S;
238 }
239
241 std::shared_ptr<typename Precond::matrix> system_matrix_ptr() const
242 {
243 return P.system_matrix_ptr();
244 }
245
246 typename Precond::matrix const& system_matrix() const
247 {
248 return P.system_matrix();
249 }
250
253 {
254 prm.get(p);
255 }
256
258 size_t size() const
259 {
260 return n;
261 }
262
263 size_t bytes() const
264 {
265 return backend::bytes(S) + backend::bytes(P);
266 }
267
268 friend std::ostream& operator<<(std::ostream& os, const DeflatedSolver& p)
269 {
270 return os << "Solver\n======\n"
271 << p.S << std::endl
272 << "Preconditioner\n==============\n"
273 << p.P;
274 }
275
276 public:
277
278 params prm;
279
280 private:
281
282 size_t n;
283 Precond P;
284 IterativeSolver S;
285 std::shared_ptr<vector> r;
286 std::vector<std::shared_ptr<vector>> Z;
287 std::vector<scalar_type> E;
288 mutable std::vector<scalar_type> d;
289};
290
291/*---------------------------------------------------------------------------*/
292/*---------------------------------------------------------------------------*/
293
294} // namespace Arcane::Alina
295
296/*---------------------------------------------------------------------------*/
297/*---------------------------------------------------------------------------*/
298
299#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.
DeflatedSolver(const AlinaContext &context, const Matrix &A, const params &prm=params(), const backend_params &bprm=backend_params())
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.
Class to store parameters as a hierarchical key/value tree.
Definition AlinaUtils.h:113
Result of a solution.
Definition AlinaUtils.h:56
Matrix class, to be used by user.
View of an array of elements of type T.
Definition Span.h:803
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.