Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SCHURPreconditionerMixed.cc
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/*---------------------------------------------------------------------------*/
9/*
10 * Ce fichier est basé sur le travail effectué sur la bibliothèque AMGCL (version mars 2026)
11 * qui peut être trouvé à https://github.com/ddemidov/amgcl.
12 *
13 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
14 * SPDX-License-Identifier: MIT
15 */
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19// Pour Eigen
20#pragma GCC diagnostic ignored "-Wdeprecated-copy"
21#pragma GCC diagnostic ignored "-Wint-in-bool-context"
22
23#include <iostream>
24#include <string>
25
26#include <boost/preprocessor/seq/for_each.hpp>
27
28#include "arccore/alina/PreconditionedSolver.h"
29#include "arccore/alina/make_block_solver.h"
30#include "arccore/alina/StaticMatrix.h"
31#include "arccore/alina/Adapters.h"
32#include "arccore/alina/AMG.h"
33#include "arccore/alina/SolverRuntime.h"
34#include "arccore/alina/CoarseningRuntime.h"
35#include "arccore/alina/RelaxationRuntime.h"
36#include "arccore/alina/SchurPressureCorrectionPreconditioner.h"
37#include "arccore/alina/PreconditionerRuntime.h"
38#include "arccore/alina/Adapters.h"
39
40#if defined(SOLVER_BACKEND_VEXCL)
41#else
42# ifndef SOLVER_BACKEND_BUILTIN
43# define SOLVER_BACKEND_BUILTIN
44# endif
45#include "arccore/alina/BuiltinBackend.h"
46#ifdef BLOCK_TYPE_EIGEN
47#include "arccore/alina/ValueTypeEigen.h"
48template <class T, int N, int M>
49using BlockMatrix = Eigen::Matrix<T, N, M>;
50# else
51 template <class T, int N, int M>
52 using BlockMatrix = Arcane::Alina::StaticMatrix<T, N, M>;
53#endif
54template <class T> using Backend = Arcane::Alina::BuiltinBackend<T>;
55#endif
56
57#include "arccore/alina/IO.h"
58#include "arccore/alina/Profiler.h"
59#include "arccore/common/internal/ProgramOptions.h"
60
61#ifndef ARCCORE_ALINA_BLOCK_SIZES
62# define ARCCORE_ALINA_BLOCK_SIZES (3)(4)
63#endif
64
65using namespace Arcane;
66
67using Alina::precondition;
68
69//---------------------------------------------------------------------------
70template <class USolver, class PSolver, class Matrix>
71void solve_schur(const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
72{
73 auto& prof = Alina::Profiler::globalProfiler();
74 typedef Backend<double> SBackend;
75 SBackend::params bprm;
76
77 auto t1 = prof.scoped_tic("schur_complement");
78
79 prof.tic("setup");
82 solve(K, prm, bprm);
83 prof.toc("setup");
84
85 std::cout << solve << std::endl;
86
87 auto A = SBackend::copy_matrix(std::make_shared<Alina::CSRMatrix<double>>(K), bprm);
88 auto f = SBackend::copy_vector(rhs, bprm);
89 auto x = SBackend::create_vector(rhs.size(), bprm);
90 Alina::backend::clear(*x);
91
92 prof.tic("solve");
93 Alina::SolverResult r = solve(*A, *f, *x);
94 prof.toc("solve");
95
96 std::cout << "Iterations: " << r.nbIteration() << std::endl
97 << "Error: " << r.residual() << std::endl;
98}
99
100#define ARCCORE_ALINA_BLOCK_PSOLVER(z, data, B) \
101 case B: { \
102 typedef Backend<BlockMatrix<float, B, B>> BBackend; \
103 typedef ::Arcane::Alina::make_block_solver< \
104 ::Arcane::Alina::PreconditionerRuntime<BBackend>, \
105 ::Arcane::Alina::SolverRuntime<BBackend> > \
106 PSolver; \
107 solve_schur<USolver, PSolver>(K, rhs, prm); \
108 } break;
109
110//---------------------------------------------------------------------------
111template <class USolver, class Matrix>
112void solve_schur(int pb, const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
113{
114 switch (pb) {
115 case 1: {
118 solve_schur<USolver, PSolver>(K, rhs, prm);
119 } break;
120#if defined(SOLVER_BACKEND_BUILTIN)
121 BOOST_PP_SEQ_FOR_EACH(ARCCORE_ALINA_BLOCK_PSOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
122#endif
123 default:
124 precondition(false, "Taille de bloc non prise en charge pour la pression");
125 }
126}
127
128#define ARCCORE_ALINA_BLOCK_USOLVER(z, data, B) \
129 case B: { \
130 typedef Backend<BlockMatrix<float, B, B>> BBackend; \
131 typedef ::Arcane::Alina::make_block_solver< \
132 ::Arcane::Alina::PreconditionerRuntime<BBackend>, \
133 ::Arcane::Alina::SolverRuntime<BBackend>> \
134 USolver; \
135 solve_schur<USolver>(pb, K, rhs, prm); \
136 } break;
137
138//---------------------------------------------------------------------------
139template <class Matrix>
140void solve_schur(int ub, int pb, const Matrix& K, const std::vector<double>& rhs, Alina::PropertyTree& prm)
141{
142 switch (ub) {
143 case 1: {
146 solve_schur<USolver>(pb, K, rhs, prm);
147 } break;
148#if defined(SOLVER_BACKEND_BUILTIN) || defined(SOLVER_BACKEND_VEXCL)
149 BOOST_PP_SEQ_FOR_EACH(ARCCORE_ALINA_BLOCK_USOLVER, ~, ARCCORE_ALINA_BLOCK_SIZES)
150#endif
151 default:
152 precondition(false, "Taille de bloc non prise en charge pour le flux");
153 }
154}
155
156//---------------------------------------------------------------------------
157int main(int argc, char* argv[])
158{
159 auto& prof = Alina::Profiler::globalProfiler();
160 using std::string;
161 using std::vector;
162
163 namespace po = Arcane::ProgramOptions;
164 namespace io = Alina::IO;
165
166 po::options_description desc("Options");
167
168 desc.add_options()("help,h", "affiche l'aide")(
169 "binary,B",
170 po::bool_switch()->default_value(false),
171 "Lorsqu'il est spécifié, traitez les fichiers d'entrée comme binaires plutôt que comme MatrixMarket. "
172 "Il est supposé que les fichiers ont été convertis au format binaire avec l'utilitaire mm2bin. ")(
173 "scale,s",
174 po::bool_switch()->default_value(false),
175 "Mettre à l'échelle la matrice de sorte que la diagonale soit unitaire. ")(
176 "matrix,A",
177 po::value<string>()->required(),
178 "La matrice du système au format MatrixMarket")(
179 "rhs,f",
180 po::value<string>(),
181 "Le côté droit en format MatrixMarket")(
182 "pmask,m",
183 po::value<string>(),
184 "Le masque de pression au format MatrixMarket. Ou, si le paramètre a la forme '%n:m', alors chaque variable (n+i*m)-ième est traitée comme une pression.")(
185 "ub",
186 po::value<int>()->default_value(1),
187 "Taille de bloc de la partie 'flux'/'non-pression' de la matrice")(
188 "pb",
189 po::value<int>()->default_value(1),
190 "Taille de bloc de la partie 'pression' de la matrice")(
191 "params,P",
192 po::value<string>(),
193 "fichier de paramètres au format json")(
194 "prm,p",
195 po::value<vector<string>>()->multitoken(),
196 "Paramètres spécifiés sous forme de paires nom=valeur. "
197 "Peut être fourni plusieurs fois. Exemples :\n"
198 " -p solver.tol=1e-3\n"
199 " -p precond.coarse_enough=300");
200
202 po::store(po::parse_command_line(argc, argv, desc), vm);
203
204 if (vm.count("help")) {
205 std::cout << desc << std::endl;
206 return 0;
207 }
208
209 po::notify(vm);
210
212 if (vm.count("params"))
213 prm.read_json(vm["params"].as<string>());
214
215 if (vm.count("prm")) {
216 for (const string& v : vm["prm"].as<vector<string>>()) {
217 prm.putKeyValue(v);
218 }
219 }
220
221 size_t rows;
222 vector<ptrdiff_t> ptr, col;
223 vector<double> val, rhs;
224 std::vector<char> pm;
225
226 {
227 auto t = prof.scoped_tic("reading");
228
229 string Afile = vm["matrix"].as<string>();
230 bool binary = vm["binary"].as<bool>();
231
232 if (binary) {
233 io::read_crs(Afile, rows, ptr, col, val);
234 }
235 else {
236 size_t cols;
237 std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
238 precondition(rows == cols, "Matrice de système non carrée");
239 }
240
241 if (vm.count("rhs")) {
242 string bfile = vm["rhs"].as<string>();
243
244 size_t n, m;
245
246 if (binary) {
247 io::read_dense(bfile, n, m, rhs);
248 }
249 else {
250 std::tie(n, m) = io::mm_reader(bfile)(rhs);
251 }
252
253 precondition(n == rows && m == 1, "Le vecteur du côté droit a une taille incorrecte");
254 }
255 else {
256 rhs.resize(rows, 1.0);
257 }
258
259 if (vm.count("pmask")) {
260 std::string pmask = vm["pmask"].as<string>();
261 prm.put("precond.pmask_size", rows);
262
263 switch (pmask[0]) {
264 case '%':
265 case '<':
266 case '>':
267 prm.put("precond.pmask_pattern", pmask);
268 break;
269 default: {
270 size_t n, m;
271 std::tie(n, m) = Alina::IO::mm_reader(pmask)(pm);
272 precondition(n == rows && m == 1, "Le fichier de masque a une taille incorrecte");
273 prm.put("precond.pmask", static_cast<void*>(&pm[0]));
274 }
275 }
276 }
277 }
278
279 if (vm["scale"].as<bool>()) {
280 std::vector<double> dia(rows, 1.0);
281
282 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
283 double d = 1.0;
284 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
285 if (col[j] == i) {
286 d = 1 / sqrt(val[j]);
287 }
288 }
289 if (!std::isnan(d))
290 dia[i] = d;
291 }
292
293 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(rows); ++i) {
294 rhs[i] *= dia[i];
295 for (ptrdiff_t j = ptr[i], e = ptr[i + 1]; j < e; ++j) {
296 val[j] *= dia[i] * dia[col[j]];
297 }
298 }
299 }
300
301 solve_schur(vm["ub"].as<int>(), vm["pb"].as<int>(),
302 std::tie(rows, ptr, col, val), rhs, prm);
303
304 std::cout << prof << std::endl;
305}
Matrix market reader.
Definition IO.h:54
Convenience class that bundles together a preconditioner and an iterative solver.
Classe pour stocker les paramètres sous forme d'arbre hiérarchique clé/valeur.
Definition AlinaUtils.h:112
Résultat d'une solution.
Definition AlinaUtils.h:53
Matrix class, to be used by user.
Décrit un ensemble d'options en ligne de commande.
Stocke les valeurs d'options analysées.
apfloat sqrt(apfloat v)
Racine carrée de v.
Definition MathApfloat.h:65
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Matrice creuse stockée au format CSR (Compressed Sparse Row).
Definition CSRMatrix.h:98
Runtime-configurable wrappers around iterative solvers.