Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DistributedRuntimeSDD3D.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 * This file is based on the work on AMGCL library (version march 2026)
11 * which can be found at 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 <iomanip>
21#include <fstream>
22#include <vector>
23#include <array>
24#include <numeric>
25#include <cmath>
26
27// To remove warnings about deprecated Eigen usage.
28//#pragma GCC diagnostic ignored "-Wdeprecated-copy"
29//ragma GCC diagnostic ignored "-Wint-in-bool-context"
30
31#if defined(SOLVER_BACKEND_CUDA)
32// This seems not defined with CUDA
33namespace boost::math
34{
35class rounding_error
36{};
37} // namespace boost::math
38#endif
39
40#include <boost/scope_exit.hpp>
41#include <boost/program_options.hpp>
42
43#if defined(SOLVER_BACKEND_CUDA)
44# include "arccore/alina/CudaBackend.h"
45# include "arccore/alina/relaxation_cusparse_ilu0.h"
47#else
48# ifndef SOLVER_BACKEND_BUILTIN
49# define SOLVER_BACKEND_BUILTIN
50# endif
51#include "arccore/alina/BuiltinBackend.h"
53#endif
54
55#include "arccore/trace/ITraceMng.h"
56
57#include "arccore/alina/DistributedDirectSolverRuntime.h"
58#include "arccore/alina/DistributedSolverRuntime.h"
59#include "arccore/alina/DistributedSubDomainDeflation.h"
60#include "arccore/alina/AMG.h"
61#include "arccore/alina/CoarseningRuntime.h"
62#include "arccore/alina/RelaxationRuntime.h"
63#include "arccore/alina/Profiler.h"
64#include "AlinaSamplesCommon.h"
65
66using namespace Arcane;
67using namespace Arcane::Alina;
68
69#include "DomainPartition.h"
70
72{
73 size_t nv;
74 std::vector<double> x;
75 std::vector<double> y;
76 std::vector<double> z;
77
78 deflation_vectors(ptrdiff_t n, size_t nv = 4)
79 : nv(nv)
80 , x(n)
81 , y(n)
82 , z(n)
83 {}
84
85 size_t dim() const { return nv; }
86
87 double operator()(ptrdiff_t i, int j) const
88 {
89 switch (j) {
90 default:
91 case 0:
92 return 1;
93 case 1:
94 return x[i];
95 case 2:
96 return y[i];
97 case 3:
98 return z[i];
99 }
100 }
101};
102
103struct renumbering
104{
105 const DomainPartition<3>& part;
106 const std::vector<ptrdiff_t>& dom;
107
108 renumbering(const DomainPartition<3>& p,
109 const std::vector<ptrdiff_t>& d)
110 : part(p)
111 , dom(d)
112 {}
113
114 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j, ptrdiff_t k) const
115 {
116 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
117 std::pair<int, ptrdiff_t> v = part.index(p);
118 return dom[v.first] + v.second;
119 }
120};
121
122int main2(const Alina::SampleMainContext& ctx, int argc, char* argv[])
123{
124 auto& prof = Alina::Profiler::globalProfiler();
125 ITraceMng* tm = ctx.traceMng();
126 Alina::mpi_communicator world(MPI_COMM_WORLD);
127
128 tm->info() << "World size: " << world.size;
129
130 // Read configuration from command line
131 ptrdiff_t n = 128;
132 bool constant_deflation = false;
133
134 auto coarsening = Alina::eCoarserningType::smoothed_aggregation;
135 auto relaxation = Alina::eRelaxationType::spai0;
136 auto iterative_solver = Alina::eSolverType::bicgstabl;
137 auto direct_solver = Alina::eDistributedDirectSolverType::skyline_lu;
138
139 bool just_relax = false;
140 bool symm_dirichlet = true;
141 std::string parameter_file;
142
143 namespace po = boost::program_options;
144 po::options_description desc("Options");
145
146 desc.add_options()("help,h", "show help")(
147 "symbc",
148 po::value<bool>(&symm_dirichlet)->default_value(symm_dirichlet),
149 "Use symmetric Dirichlet conditions in laplace2d")(
150 "size,n",
151 po::value<ptrdiff_t>(&n)->default_value(n),
152 "domain size")(
153 "coarsening,c",
154 po::value<Alina::eCoarserningType>(&coarsening)->default_value(coarsening),
155 "ruge_stuben, aggregation, smoothed_aggregation, smoothed_aggr_emin")(
156 "relaxation,r",
157 po::value<Alina::eRelaxationType>(&relaxation)->default_value(relaxation),
158 "gauss_seidel, ilu0, iluk, ilut, damped_jacobi, spai0, spai1, chebyshev")(
159 "iter_solver,i",
160 po::value<Alina::eSolverType>(&iterative_solver)->default_value(iterative_solver),
161 "cg, bicgstab, bicgstabl, gmres")(
162 "dir_solver,d",
163 po::value<Alina::eDistributedDirectSolverType>(&direct_solver)->default_value(direct_solver),
164 "skyline_lu"
165#ifdef ARCCORE_ALINA_HAVE_EIGEN
166 ", eigen_splu"
167#endif
168 )(
169 "cd",
170 po::bool_switch(&constant_deflation),
171 "Use constant deflation (linear deflation is used by default)")(
172 "params,P",
173 po::value<std::string>(&parameter_file),
174 "parameter file in json format")(
175 "prm,p",
176 po::value<std::vector<std::string>>()->multitoken(),
177 "Parameters specified as name=value pairs. "
178 "May be provided multiple times. Examples:\n"
179 " -p solver.tol=1e-3\n"
180 " -p precond.coarse_enough=300")(
181 "just-relax,0",
182 po::bool_switch(&just_relax),
183 "Do not create AMG hierarchy, use relaxation as preconditioner");
184
185 po::variables_map vm;
186 po::store(po::parse_command_line(argc, argv, desc), vm);
187 po::notify(vm);
188
189 if (vm.count("help")) {
190 std::cout << desc << std::endl;
191 return 0;
192 }
193
195 if (vm.count("params"))
196 prm.read_json(parameter_file);
197
198 if (vm.count("prm")) {
199 for (const std::string& v : vm["prm"].as<std::vector<std::string>>()) {
200 prm.putKeyValue(v);
201 }
202 }
203
204 prm.put("isolver.type", iterative_solver);
205 prm.put("dsolver.type", direct_solver);
206
207 boost::array<ptrdiff_t, 3> lo = { { 0, 0, 0 } };
208 boost::array<ptrdiff_t, 3> hi = { { n - 1, n - 1, n - 1 } };
209
210 prof.tic("partition");
211 DomainPartition<3> part(lo, hi, world.size);
212 ptrdiff_t chunk = part.size(world.rank);
213
214 std::vector<ptrdiff_t> domain(world.size + 1);
215 MPI_Allgather(&chunk, 1, Alina::mpi_datatype<ptrdiff_t>(),
216 &domain[1], 1, Alina::mpi_datatype<ptrdiff_t>(), world);
217 std::partial_sum(domain.begin(), domain.end(), domain.begin());
218
219 lo = part.domain(world.rank).min_corner();
220 hi = part.domain(world.rank).max_corner();
221
222 renumbering renum(part, domain);
223
224 deflation_vectors def(chunk, constant_deflation ? 1 : 4);
225 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
226 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
227 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
228 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
229 std::pair<int, ptrdiff_t> v = part.index(p);
230
231 def.x[v.second] = (i - (lo[0] + hi[0]) / 2);
232 def.y[v.second] = (j - (lo[1] + hi[1]) / 2);
233 def.z[v.second] = (k - (lo[2] + hi[2]) / 2);
234 }
235 }
236 }
237 prof.toc("partition");
238
239 prof.tic("assemble");
240 std::vector<ptrdiff_t> ptr;
241 std::vector<ptrdiff_t> col;
242 std::vector<double> val;
243 std::vector<double> rhs;
244
245 ptr.reserve(chunk + 1);
246 col.reserve(chunk * 7);
247 val.reserve(chunk * 7);
248 rhs.reserve(chunk);
249
250 ptr.push_back(0);
251
252 const double h2i = (n - 1) * (n - 1);
253
254 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
255 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
256 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
257
258 if (!symm_dirichlet && (i == 0 || j == 0 || k == 0 || i + 1 == n || j + 1 == n || k + 1 == n)) {
259 col.push_back(renum(i, j, k));
260 val.push_back(1);
261 rhs.push_back(0);
262 }
263 else {
264 if (k > 0) {
265 col.push_back(renum(i, j, k - 1));
266 val.push_back(-h2i);
267 }
268
269 if (j > 0) {
270 col.push_back(renum(i, j - 1, k));
271 val.push_back(-h2i);
272 }
273
274 if (i > 0) {
275 col.push_back(renum(i - 1, j, k));
276 val.push_back(-h2i);
277 }
278
279 col.push_back(renum(i, j, k));
280 val.push_back(6 * h2i);
281
282 if (i + 1 < n) {
283 col.push_back(renum(i + 1, j, k));
284 val.push_back(-h2i);
285 }
286
287 if (j + 1 < n) {
288 col.push_back(renum(i, j + 1, k));
289 val.push_back(-h2i);
290 }
291
292 if (k + 1 < n) {
293 col.push_back(renum(i, j, k + 1));
294 val.push_back(-h2i);
295 }
296
297 rhs.push_back(1);
298 }
299 ptr.push_back(col.size());
300 }
301 }
302 }
303 prof.toc("assemble");
304
305 Backend::params bprm;
306
307#if defined(SOLVER_BACKEND_VEXCL)
308 vex::Context ctx(vex::Filter::Env);
309 std::cout << ctx << std::endl;
310 bprm.q = ctx;
311#elif defined(SOLVER_BACKEND_CUDA)
312 cusparseCreate(&bprm.cusparse_handle);
313#endif
314
315 auto f = Backend::copy_vector(rhs, bprm);
316 auto x = Backend::create_vector(chunk, bprm);
317
318 Alina::backend::clear(*x);
319
320 size_t iters;
321 double resid;
322
323 std::function<double(ptrdiff_t, unsigned)> def_vec = std::cref(def);
324 prm.put("num_def_vec", def.dim());
325 prm.put("def_vec", &def_vec);
326
327 if (just_relax) {
328 prm.put("local.type", relaxation);
329
330 prof.tic("setup");
334
335 SDD solve(world, std::tie(chunk, ptr, col, val), prm, bprm);
336 prof.toc("setup");
337
338 prof.tic("solve");
339 std::tie(iters, resid) = solve(*f, *x);
340 prof.toc("solve");
341 }
342 else {
343 prm.put("local.coarsening.type", coarsening);
344 prm.put("local.relax.type", relaxation);
345
346 prof.tic("setup");
350
351 SDD solve(world, std::tie(chunk, ptr, col, val), prm, bprm);
352 prof.toc("setup");
353
354 prof.tic("solve");
355 std::tie(iters, resid) = solve(*f, *x);
356 prof.toc("solve");
357 }
358
359 tm->info() << "Iterations: " << iters << "\n"
360 << "Error: " << resid << "\n\n"
361 << prof << "\n";
362 return 0;
363}
364
365int main(int argc, char* argv[])
366{
367 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
368}
Runtime wrapper for distributed direct solvers.
Distributed solver based on subdomain deflation.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Alina::detail::empty_params params
Pointwise constant deflation vectors.
Convenience wrapper around MPI_Comm.