Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DistributedRuntimeBP.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 <iostream>
20#include <vector>
21#include <string>
22#include <utility>
23#include <numeric>
24
25#include <boost/range/iterator_range.hpp>
26#include <boost/scope_exit.hpp>
27
28#include "arccore/alina/BuiltinBackend.h"
29#include "arccore/alina/PreconditionerRuntime.h"
30#include "arccore/alina/Adapters.h"
31#include "arccore/alina/DistributedPreconditionedSolver.h"
32#include "arccore/alina/DistributedSolverRuntime.h"
33#include "arccore/alina/DistributedPreconditioner.h"
34#include "arccore/alina/Profiler.h"
35#include "arccore/alina/AlinaUtils.h"
36
37// Uniquement pour le test de compilation
38#include "arccore/alina/DistributedSolver.h"
39
40// Uniquement pour le test de compilation
41#include "arccore/alina/DistributedRelaxationRuntime.h"
42
43#include "arccore/common/internal/ProgramOptions.h"
44
45#include "DomainPartition.h"
46
47using namespace Arcane;
48using namespace Arcane::Alina;
49
50using Alina::precondition;
51
52//---------------------------------------------------------------------------
53struct renumbering
54{
55 const DomainPartition<2>& part;
56 const std::vector<ptrdiff_t>& dom;
57
58 renumbering(const DomainPartition<2>& p,
59 const std::vector<ptrdiff_t>& d)
60 : part(p)
61 , dom(d)
62 {}
63
64 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j) const
65 {
66 boost::array<ptrdiff_t, 2> p = { { i, j } };
67 std::pair<int, ptrdiff_t> v = part.index(p);
68 return dom[v.first] + v.second;
69 }
70};
71
72//---------------------------------------------------------------------------
73
74template <template <class> class Precond, class Matrix>
76solve(const Alina::mpi_communicator& comm,
77 const Alina::PropertyTree& prm,
78 const Matrix& A)
79{
80 auto& prof = Alina::Profiler::globalProfiler();
81
82 typedef Alina::BuiltinBackend<double> Backend;
83
85
86 const size_t n = Alina::backend::nbRow(A);
87
88 std::vector<double> rhs(n, 1), x(n, 0);
89
90 prof.tic("setup");
91 Solver solve(comm, A, prm);
92 prof.toc("setup");
93
94 {
95 auto t2 = prof.scoped_tic("solve");
96 return solve(rhs, x);
97 }
98}
99
100//---------------------------------------------------------------------------
101
102int main(int argc, char* argv[])
103{
104 auto& prof = Alina::Profiler::globalProfiler();
105 namespace po = Arcane::ProgramOptions;
106
107 using std::string;
108 using std::vector;
109
110 po::options_description desc("Options");
111
112 desc.add_options()("help,h", "Show this help.")("prm-file,P",
113 po::value<string>(),
114 "Fichier de paramètres au format json. ")(
115 "prm,p",
116 po::value<vector<string>>()->multitoken(),
117 "Paramètres spécifiés sous forme de paires nom=valeur. "
118 "Peut être fourni plusieurs fois. Exemples:\n"
119 " -p solver.tol=1e-3\n"
120 " -p precond.coarse_enough=300")(
121 "size,n",
122 po::value<int>()->default_value(1024),
123 "La taille du problème de Poisson à résoudre. "
124 "Spécifié comme le nombre de nœuds de grille le long de chaque dimension d'un carré unité. "
125 "Le système résultant aura n*n inconnues. ")(
126 "single-level,1",
127 po::bool_switch()->default_value(false),
128 "Lorsqu'il est spécifié, la hiérarchie AMG n'est pas construite. "
129 "Au lieu de cela, le problème est résolu à l'aide d'un lisseur à niveau unique comme préconditionneur. ")(
130 "initial,x",
131 po::value<double>()->default_value(0),
132 "Valeur à utiliser comme approximation initiale. ");
133
135 po::store(po::parse_command_line(argc, argv, desc), vm);
136 po::notify(vm);
137
138 if (vm.count("help")) {
139 std::cout << desc << std::endl;
140 return 0;
141 }
142
144 if (vm.count("prm-file")) {
145 prm.read_json(vm["prm-file"].as<string>());
146 }
147
148 if (vm.count("prm")) {
149 for (const string& v : vm["prm"].as<vector<string>>()) {
150 prm.putKeyValue(v);
151 }
152 }
153
154 MPI_Init(&argc, &argv);
155 BOOST_SCOPE_EXIT(void)
156 {
157 MPI_Finalize();
158 }
159 BOOST_SCOPE_EXIT_END
160
161 Alina::mpi_communicator world(MPI_COMM_WORLD);
162
163 if (world.rank == 0)
164 std::cout << "World size: " << world.size << std::endl;
165
166 const ptrdiff_t n = vm["size"].as<int>();
167 const double h2i = (n - 1) * (n - 1);
168
169 boost::array<ptrdiff_t, 2> lo = { { 0, 0 } };
170 boost::array<ptrdiff_t, 2> hi = { { n - 1, n - 1 } };
171
172 prof.tic("partition");
173 DomainPartition<2> part(lo, hi, world.size);
174 ptrdiff_t chunk = part.size(world.rank);
175
176 std::vector<ptrdiff_t> domain(world.size + 1);
177 ConstArrayView<ptrdiff_t> send_buf(1,&chunk);
178 ArrayView<ptrdiff_t> receive_buf(world.size, &domain[1]);
179 mpAllGather(world.m_message_passing_mng.get(),send_buf,receive_buf);
180 std::partial_sum(domain.begin(), domain.end(), domain.begin());
181
182 lo = part.domain(world.rank).min_corner();
183 hi = part.domain(world.rank).max_corner();
184 prof.toc("partition");
185
186 renumbering renum(part, domain);
187
188 prof.tic("assemble");
189 std::vector<ptrdiff_t> ptr;
190 std::vector<ptrdiff_t> col;
191 std::vector<double> val;
192 std::vector<double> rhs;
193
194 ptr.reserve(chunk + 1);
195 col.reserve(chunk * 5);
196 val.reserve(chunk * 5);
197
198 ptr.push_back(0);
199
200 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
201 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
202 if (j > 0) {
203 col.push_back(renum(i, j - 1));
204 val.push_back(-h2i);
205 }
206
207 if (i > 0) {
208 col.push_back(renum(i - 1, j));
209 val.push_back(-h2i);
210 }
211
212 col.push_back(renum(i, j));
213 val.push_back(4 * h2i);
214
215 if (i + 1 < n) {
216 col.push_back(renum(i + 1, j));
217 val.push_back(-h2i);
218 }
219
220 if (j + 1 < n) {
221 col.push_back(renum(i, j + 1));
222 val.push_back(-h2i);
223 }
224
225 ptr.push_back(col.size());
226 }
227 }
228 prof.toc("assemble");
229
230 bool single_level = vm["single-level"].as<bool>();
231
232 if (single_level)
233 prm.put("precond.class", "relaxation");
234
235 Alina::SolverResult r = solve<Alina::PreconditionerRuntime>(world, prm, std::tie(chunk, ptr, col, val));
236
237 if (world.rank == 0) {
238 std::cout << "Itérations: " << r.nbIteration() << std::endl
239 << "Erreur: " << r.residual() << std::endl
240 << std::endl
241 << prof << std::endl;
242 }
243}
Iterative solver wrapper for distributed linear systems.
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
Vue modifiable d'un tableau d'un type T.
Vue constante d'un tableau de type T.
Matrix class, to be used by user.
Décrit un ensemble d'options en ligne de commande.
Stocke les valeurs d'options analysées.
void mpAllGather(IMessagePassingMng *pm, const ISerializer *send_serializer, ISerializer *receive_serialize)
Message allGather() pour une sérialisation.
Definition Messages.cc:308
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Wrapper de commodité autour de MPI_Comm.