Arcane  4.2.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DistributedBasicSolver.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 sur la bibliothèque AMGCL (version mars 2026)
11 * qui peut être trouvée à 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#include "arccore/alina/BuiltinBackend.h"
20#include "arccore/alina/MessagePassingUtils.h"
21#include "arccore/alina/DistributedPreconditionedSolver.h"
22#include "arccore/alina/DistributedPreconditioner.h"
23#include "arccore/alina/DistributedSolverRuntime.h"
24
25#include "arccore/alina/Profiler.h"
26
27#include "arccore/common/internal/ProgramOptions.h"
28
29#include "arccore/trace/ITraceMng.h"
30
31#include "AlinaSamplesCommon.h"
32#include "SampleProblemCommon.h"
33
34#include <iostream>
35#include <vector>
36#include <string>
37
38using namespace Arcane;
39
40//---------------------------------------------------------------------------
41template <class Backend, class Matrix>
42std::shared_ptr<Alina::DistributedMatrix<Backend>>
43partition(Alina::AlinaCommunicator comm, const Matrix& Astrip,
44 typename Backend::vector& rhs, const typename Backend::params& bprm,
45 Alina::eMatrixPartitionerType ptype, int block_size = 1)
46{
47 auto& prof = Alina::Profiler::globalProfiler();
48 typedef typename Backend::value_type val_type;
49 typedef typename Alina::math::rhs_of<val_type>::type rhs_type;
51
52 auto A = std::make_shared<DMatrix>(comm, Astrip);
53
54 if (comm.size == 1 || ptype == Alina::eMatrixPartitionerType::merge)
55 return A;
56
57 prof.tic("partition");
59 prm.put("type", ptype);
61
62 auto I = part(*A, block_size);
63 auto J = transpose(*I);
64 A = product(*J, *product(*A, *I));
65
66 Alina::numa_vector<rhs_type> new_rhs(J->loc_rows());
67
68 J->move_to_backend(bprm);
69
70 Alina::backend::spmv(1, *J, rhs, 0, new_rhs);
71 rhs.swap(new_rhs);
72 prof.toc("partition");
73
74 return A;
75}
76
77//---------------------------------------------------------------------------
78void solve_scalar(const Alina::AlinaContext& context,
80 ptrdiff_t chunk,
81 const std::vector<ptrdiff_t>& ptr,
82 const std::vector<ptrdiff_t>& col,
83 const std::vector<double>& val,
84 const Alina::PropertyTree& prm,
85 const std::vector<double>& f,
86 Alina::eMatrixPartitionerType ptype)
87{
88 auto& prof = Alina::Profiler::globalProfiler();
89 //using Backend = Alina::BuiltinBackend<double>;
90
91 using BackendValueType = double;
93
94 std::cout << "Using scalar solve ptr_size=" << sizeof(ptrdiff_t)
95 << " ptr_type_size=" << sizeof(Backend::ptr_type)
96 << " col_type_size=" << sizeof(Backend::col_type)
97 << " value_type_size=" << sizeof(Backend::value_type)
98 << " chunk=" << chunk
99 << "\n";
100
101 typedef Alina::DistributedMatrix<Backend> DMatrix;
102
104 using RelaxationType = Alina::DistributedSPAI0Relaxation<Backend>;
105 // Si on veut tester les backend dynamiques:
106 //using CoarseningType = Alina::DistributedCoarseningRuntime<Backend>;
107 //using RelaxationType = Alina::DistributedRelaxationRuntime<Backend>,
108
109 using AMGPrecondType = Alina::DistributedAMG<Backend, CoarseningType, RelaxationType,
112
114
115 typename Backend::params bprm;
116
118
119 auto get_distributed_matrix = [&]() {
120 auto t = prof.scoped_tic("distributed matrix");
121 std::shared_ptr<DMatrix> A;
122
123 if (ptype != Alina::eMatrixPartitionerType::merge) {
124 A = partition<Backend>(comm,
125 std::tie(chunk, ptr, col, val), rhs, bprm, ptype,
126 prm.get("precond.coarsening.aggr.block_size", 1));
127 chunk = A->loc_rows();
128 }
129 else {
130 A = std::make_shared<DMatrix>(comm, std::tie(chunk, ptr, col, val));
131 }
132
133 return A;
134 };
135
136 std::shared_ptr<DMatrix> A;
137 std::shared_ptr<Solver> solve;
138
139 {
140 auto t = prof.scoped_tic("setup");
141 A = get_distributed_matrix();
142 solve = std::make_shared<Solver>(context, comm, A, prm, bprm);
144 solve->prm.get(prm2);
145 std::cout << "SOLVER parameters=" << prm2 << "\n";
146 }
147
148 if (comm.rank == 0) {
149 std::cout << "SolverInfo:\n";
150 std::cout << *solve << std::endl;
151 }
152
153 if (prm.get("precond.allow_rebuild", false)) {
154 if (comm.rank == 0) {
155 std::cout << "Rebuilding the preconditioner..." << std::endl;
156 }
157
158 {
159 auto t = prof.scoped_tic("rebuild");
160 A = get_distributed_matrix();
161 solve->precond().rebuild(A);
162 }
163
164 if (comm.rank == 0) {
165 std::cout << *solve << std::endl;
166 }
167 }
168
170
171 prof.tic("solve");
172 Alina::SolverResult r = (*solve)(rhs, x);
173 prof.toc("solve");
174
175 if (comm.rank == 0) {
176 std::cout << "Iterations: " << r.nbIteration() << std::endl
177 << "Error: " << r.residual() << std::endl
178 << prof << std::endl;
179 }
180}
181
182//---------------------------------------------------------------------------
183int main2(const Alina::SampleMainContext& ctx, int argc, char* argv[])
184{
185 ITraceMng* tm = ctx.traceMng();
186 auto& prof = Alina::Profiler::globalProfiler();
187 Alina::AlinaContext context;
188 Alina::AlinaCommunicator comm(ctx.messagePassingMng());
189
190 tm->info() << "World size: " << comm.size;
191
192 // Lire la configuration à partir de la ligne de commande
193 namespace po = Arcane::ProgramOptions;
194 po::options_description desc("Options");
195
196 auto default_partitioner_type = Alina::eMatrixPartitionerType::merge;
197#if defined(ARCCORE_ALINA_HAVE_PARMETIS)
198 default_partitioner_type = Alina::eMatrixPartitionerType::parmetis;
199#endif
200
201 desc.add_options()("help,h", "affiche l'aide")("matrix,A",
202 po::value<std::string>(),
203 "Matrice système au format MatrixMarket. "
204 "Si non spécifié, un problème de Poisson dans un cube unitaire 3D est assemblé. ");
205 desc.add_options()("partitioner,r",
206 po::value<Alina::eMatrixPartitionerType>()->default_value(
207 default_partitioner_type),
208 "Répartition de la matrice système");
209 desc.add_options()("size,n",
210 po::value<ptrdiff_t>()->default_value(32),
211 "taille du domaine");
212 desc.add_options()("prm-file,P", po::value<std::string>(),
213 "Fichier de paramètres au format json. ");
214 desc.add_options()("prm,p",
215 po::value<std::vector<std::string>>()->multitoken(),
216 "Paramètres spécifiés sous forme de paires nom=valeur. "
217 "Peut être fourni plusieurs fois. Exemples :\n"
218 " -p solver.tol=1e-3\n"
219 " -p precond.coarse_enough=300");
220 desc.add_options()("test-rebuild",
221 po::bool_switch()->default_value(false),
222 "Lorsqu'il est spécifié, tente de reconstruire le solveur avant de résoudre. ");
223
225 p.add("prm", -1);
226
228 po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
229 po::notify(vm);
230
231 if (vm.count("help")) {
232 if (comm.rank == 0)
233 std::cout << desc << std::endl;
234 return 0;
235 }
236
238 if (vm.count("prm-file")) {
239 prm.read_json(vm["prm-file"].as<std::string>());
240 }
241
242 if (vm.count("prm")) {
243 for (const std::string& v : vm["prm"].as<std::vector<std::string>>()) {
244 tm->info() << "PUT_KEY_VALUE v=" << v;
245 prm.putKeyValue(v);
246 }
247 }
248
249 ptrdiff_t n;
250 std::vector<ptrdiff_t> ptr;
251 std::vector<ptrdiff_t> col;
252 std::vector<double> val;
253 std::vector<double> rhs;
254
255 Alina::eMatrixPartitionerType ptype = vm["partitioner"].as<Alina::eMatrixPartitionerType>();
256
257 prof.tic("assemble");
258 Int64 matrix_size = vm["size"].as<ptrdiff_t>();
259 tm->info() << "Taille de la matrice=" << matrix_size;
260 n = Alina::PoissonProblemGenerator::createDistributedMatrix(comm.rank, comm.size, matrix_size, 1, ptr, col, val, rhs);
261 prof.toc("assemble");
262
263 if (vm["test-rebuild"].as<bool>()) {
264 prm.put("precond.allow_rebuild", true);
265 }
266
267 solve_scalar(context, comm, n, ptr, col, val, prm, rhs, ptype);
268 return 0;
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
274int main(int argc, char* argv[])
275{
276 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
277}
278
279/*---------------------------------------------------------------------------*/
280/*---------------------------------------------------------------------------*/
Runtime wrapper for distributed direct solvers.
Distributed Matrix using message passing.
Iterative solver wrapper for distributed linear systems.
Classe pour stocker les paramètres sous forme d'arbre hiérarchique clé/valeur.
Definition AlinaUtils.h:113
Résultat d'une solution.
Definition AlinaUtils.h:56
NUMA-aware vector container.
Definition NumaVector.h:42
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Matrix class, to be used by user.
Constructeur d'analyseur d'arguments en ligne de commande fluide.
Décrit un ensemble d'options en ligne de commande.
Décrit les arguments positionnels (non-options).
Stocke les valeurs d'options analysées.
__host__ __device__ Real3x3 transpose(const Real3x3 &t)
Transpose la matrice.
Definition MathUtils.h:265
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Wrapper de commodité autour de MPI_Comm.
Distributed smoothed aggregation coarsening scheme.
Runtime-configurable wrapper around matrix partitioner.