Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
DistributedRuntimeSDD.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 <numeric>
24#include <cmath>
25#include <stdexcept>
26
27#if defined(SOLVER_BACKEND_CUDA)
28// This seems not defined with CUDA
29namespace boost::math
30{
31class rounding_error
32{};
33} // namespace boost::math
34#endif
35
36#include "DomainPartition.h"
37
38#include "MBA.h"
39
40#include <memory>
41
42#include <boost/multi_array.hpp>
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/alina/PreconditionedSolver.h"
56#include "arccore/alina/AMG.h"
57#include "arccore/alina/CoarseningRuntime.h"
58#include "arccore/alina/RelaxationRuntime.h"
59#include "arccore/alina/PreconditionerRuntime.h"
60#include "arccore/alina/DistributedDirectSolverRuntime.h"
61#include "arccore/alina/DistributedSolverRuntime.h"
62#include "arccore/alina/DistributedSubDomainDeflation.h"
63#include "arccore/alina/Adapters.h"
64#include "arccore/alina/Profiler.h"
65
66#include "arccore/common/internal/ProgramOptions.h"
67
68#include "AlinaSamplesCommon.h"
69
70using namespace Arcane;
71
72struct partitioned_deflation
73{
74 unsigned nparts;
75 std::vector<unsigned> domain;
76
77 partitioned_deflation(boost::array<ptrdiff_t, 2> LO,
78 boost::array<ptrdiff_t, 2> HI,
79 unsigned nparts)
80 : nparts(nparts)
81 {
82 DomainPartition<2> part(LO, HI, nparts);
83
84 ptrdiff_t nx = HI[0] - LO[0] + 1;
85 ptrdiff_t ny = HI[1] - LO[1] + 1;
86
87 domain.resize(nx * ny);
88 for (unsigned p = 0; p < nparts; ++p) {
89 boost::array<ptrdiff_t, 2> lo = part.domain(p).min_corner();
90 boost::array<ptrdiff_t, 2> hi = part.domain(p).max_corner();
91
92 for (int j = lo[1]; j <= hi[1]; ++j) {
93 for (int i = lo[0]; i <= hi[0]; ++i) {
94 domain[(j - LO[1]) * nx + (i - LO[0])] = p;
95 }
96 }
97 }
98 }
99
100 size_t dim() const { return nparts; }
101
102 double operator()(ptrdiff_t i, unsigned j) const
103 {
104 return domain[i] == j;
105 }
106};
107
108struct linear_deflation
109{
110 std::vector<double> x;
111 std::vector<double> y;
112
113 linear_deflation(ptrdiff_t chunk,
114 boost::array<ptrdiff_t, 2> lo,
115 boost::array<ptrdiff_t, 2> hi)
116 {
117 double hx = 1.0 / (hi[0] - lo[0]);
118 double hy = 1.0 / (hi[1] - lo[1]);
119
120 ptrdiff_t nx = hi[0] - lo[0] + 1;
121 ptrdiff_t ny = hi[1] - lo[1] + 1;
122
123 x.reserve(chunk);
124 y.reserve(chunk);
125
126 for (ptrdiff_t j = 0; j < ny; ++j) {
127 for (ptrdiff_t i = 0; i < nx; ++i) {
128 x.push_back(i * hx - 0.5);
129 y.push_back(j * hy - 0.5);
130 }
131 }
132 }
133
134 size_t dim() const { return 3; }
135
136 double operator()(ptrdiff_t i, unsigned j) const
137 {
138 switch (j) {
139 default:
140 case 0:
141 return 1;
142 case 1:
143 return x[i];
144 case 2:
145 return y[i];
146 }
147 }
148};
149
150struct bilinear_deflation
151{
152 size_t nv, chunk;
153 std::vector<double> v;
154
155 bilinear_deflation(ptrdiff_t n,
156 ptrdiff_t chunk,
157 boost::array<ptrdiff_t, 2> lo,
158 boost::array<ptrdiff_t, 2> hi)
159 : nv(0)
160 , chunk(chunk)
161 {
162 // See which neighbors we have.
163 int neib[2][2] = {
164 { lo[0] > 0 || lo[1] > 0, hi[0] + 1 < n || lo[1] > 0 },
165 { lo[0] > 0 || hi[1] + 1 < n, hi[0] + 1 < n || hi[1] + 1 < n }
166 };
167
168 for (int j = 0; j < 2; ++j)
169 for (int i = 0; i < 2; ++i)
170 if (neib[j][i])
171 ++nv;
172
173 if (nv == 0) {
174 // Single MPI process?
175 nv = 1;
176 v.resize(chunk, 1);
177 return;
178 }
179
180 v.resize(chunk * nv, 0);
181
182 double* dv = v.data();
183
184 ptrdiff_t nx = hi[0] - lo[0] + 1;
185 ptrdiff_t ny = hi[1] - lo[1] + 1;
186
187 double hx = 1.0 / (nx - 1);
188 double hy = 1.0 / (ny - 1);
189
190 for (int j = 0; j < 2; ++j) {
191 for (int i = 0; i < 2; ++i) {
192 if (!neib[j][i])
193 continue;
194
195 boost::multi_array_ref<double, 2> V(dv, boost::extents[ny][nx]);
196
197 for (ptrdiff_t jj = 0; jj < ny; ++jj) {
198 double y = jj * hy;
199 double b = std::abs((1 - j) - y);
200 for (ptrdiff_t ii = 0; ii < nx; ++ii) {
201 double x = ii * hx;
202
203 double a = std::abs((1 - i) - x);
204 V[jj][ii] = a * b;
205 }
206 }
207
208 dv += chunk;
209 }
210 }
211 }
212
213 size_t dim() const { return nv; }
214
215 double operator()(ptrdiff_t i, unsigned j) const
216 {
217 return v[j * chunk + i];
218 }
219};
220
221#ifndef SOLVER_BACKEND_CUDA
222struct mba_deflation
223{
224 size_t chunk, nv;
225 std::vector<double> v;
226
227 mba_deflation(ptrdiff_t n,
228 ptrdiff_t chunk,
229 boost::array<ptrdiff_t, 2> lo,
230 boost::array<ptrdiff_t, 2> hi)
231 : chunk(chunk)
232 , nv(1)
233 {
234 // See which neighbors we have.
235 int neib[2][2] = {
236 { lo[0] > 0 || lo[1] > 0, hi[0] + 1 < n || lo[1] > 0 },
237 { lo[0] > 0 || hi[1] + 1 < n, hi[0] + 1 < n || hi[1] + 1 < n }
238 };
239
240 for (int j = 0; j < 2; ++j)
241 for (int i = 0; i < 2; ++i)
242 if (neib[j][i])
243 ++nv;
244
245 v.resize(chunk * nv, 0);
246
247 double* dv = v.data();
248 std::fill(dv, dv + chunk, 1.0);
249 dv += chunk;
250
251 ptrdiff_t nx = hi[0] - lo[0] + 1;
252 ptrdiff_t ny = hi[1] - lo[1] + 1;
253
254 double hx = 1.0 / (nx - 1);
255 double hy = 1.0 / (ny - 1);
256
257 std::array<double, 2> cmin = { -0.01, -0.01 };
258 std::array<double, 2> cmax = { 1.01, 1.01 };
259 std::array<size_t, 2> grid = { 3, 3 };
260
261 std::array<std::array<double, 2>, 4> coo;
262 std::array<double, 4> val;
263
264 for (int j = 0, idx = 0; j < 2; ++j) {
265 for (int i = 0; i < 2; ++i, ++idx) {
266 coo[idx][0] = i;
267 coo[idx][1] = j;
268 }
269 }
270
271 for (int j = 0, idx = 0; j < 2; ++j) {
272 for (int i = 0; i < 2; ++i, ++idx) {
273 if (!neib[j][i])
274 continue;
275
276 std::fill(val.begin(), val.end(), 0.0);
277 val[idx] = 1.0;
278
279 mba::MBA<2> interp(cmin, cmax, grid, coo, val, 8, 1e-8, 0.5, zero);
280
281 boost::multi_array_ref<double, 2> V(dv, boost::extents[ny][nx]);
282
283 for (int jj = 0; jj < ny; ++jj)
284 for (int ii = 0; ii < nx; ++ii) {
285 std::array<double, 2> p = { ii * hx, jj * hy };
286 V[jj][ii] = interp(p);
287 }
288
289 dv += chunk;
290 }
291 }
292 }
293
294 size_t dim() const { return nv; }
295
296 double operator()(ptrdiff_t i, unsigned j) const
297 {
298 return v[j * chunk + i];
299 }
300
301 static double zero(const std::array<double, 2>&)
302 {
303 return 0;
304 }
305};
306#endif
307
308struct harmonic_deflation
309{
310 size_t nv, chunk;
311 std::vector<double> v;
312
313 harmonic_deflation(ptrdiff_t n,
314 ptrdiff_t chunk,
315 boost::array<ptrdiff_t, 2> lo,
316 boost::array<ptrdiff_t, 2> hi)
317 : nv(0)
318 , chunk(chunk)
319 {
320 Alina::AlinaContext context;
321
322 // See which neighbors we have.
323 int neib[2][2] = {
324 { lo[0] > 0 || lo[1] > 0, hi[0] + 1 < n || lo[1] > 0 },
325 { lo[0] > 0 || hi[1] + 1 < n, hi[0] + 1 < n || hi[1] + 1 < n }
326 };
327
328 for (int j = 0; j < 2; ++j)
329 for (int i = 0; i < 2; ++i)
330 if (neib[j][i])
331 ++nv;
332
333 if (nv == 0) {
334 // Single MPI process?
335 nv = 1;
336 v.resize(chunk, 1);
337 return;
338 }
339
340 v.resize(chunk * nv, 0);
341 double* dv = v.data();
342
343 ptrdiff_t nx = hi[0] - lo[0] + 1;
344 ptrdiff_t ny = hi[1] - lo[1] + 1;
345
346 std::vector<Int32> ptr;
347 std::vector<Int32> col;
348 std::vector<double> val;
349 std::vector<double> rhs(chunk, 0.0);
350
351 ptr.reserve(chunk + 1);
352 col.reserve(chunk * 5);
353 val.reserve(chunk * 5);
354
355 ptr.push_back(0);
356
357 for (int j = 0, k = 0; j < ny; ++j) {
358 for (int i = 0; i < nx; ++i, ++k) {
359 if (
360 (i == 0 && j == 0) ||
361 (i == 0 && j == ny - 1) ||
362 (i == nx - 1 && j == 0) ||
363 (i == nx - 1 && j == ny - 1)) {
364 col.push_back(k);
365 val.push_back(1);
366 }
367 else {
368 col.push_back(k);
369 val.push_back(1.0);
370
371 if (j == 0) {
372 col.push_back(k + nx);
373 val.push_back(-0.5);
374 }
375 else if (j == ny - 1) {
376 col.push_back(k - nx);
377 val.push_back(-0.5);
378 }
379 else {
380 col.push_back(k - nx);
381 val.push_back(-0.25);
382
383 col.push_back(k + nx);
384 val.push_back(-0.25);
385 }
386
387 if (i == 0) {
388 col.push_back(k + 1);
389 val.push_back(-0.5);
390 }
391 else if (i == nx - 1) {
392 col.push_back(k - 1);
393 val.push_back(-0.5);
394 }
395 else {
396 col.push_back(k - 1);
397 val.push_back(-0.25);
398
399 col.push_back(k + 1);
400 val.push_back(-0.25);
401 }
402 }
403
404 ptr.push_back(col.size());
405 }
406 }
407
413 solve(context, Alina::adapter::zero_copy(chunk, ptr.data(), col.data(), val.data()));
414
415 for (int j = 0; j < 2; ++j) {
416 for (int i = 0; i < 2; ++i) {
417 if (!neib[j][i])
418 continue;
419
420 ptrdiff_t idx = i * (nx - 1) + j * (ny - 1) * nx;
421 rhs[idx] = 1.0;
422
423 SmallSpan<double> x(dv, chunk);
424 solve(rhs, x);
425
426 rhs[idx] = 0.0;
427
428 dv += chunk;
429 }
430 }
431 }
432
433 size_t dim() const { return nv; }
434
435 double operator()(ptrdiff_t i, unsigned j) const
436 {
437 return v[j * chunk + i];
438 }
439};
440
441struct renumbering
442{
443 const DomainPartition<2>& part;
444 const std::vector<ptrdiff_t>& dom;
445
446 renumbering(const DomainPartition<2>& p,
447 const std::vector<ptrdiff_t>& d)
448 : part(p)
449 , dom(d)
450 {}
451
452 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j) const
453 {
454 boost::array<ptrdiff_t, 2> p = { { i, j } };
455 std::pair<int, ptrdiff_t> v = part.index(p);
456 return dom[v.first] + v.second;
457 }
458};
459
460int main2(const Alina::SampleMainContext& ctx, int argc, char* argv[])
461{
462 auto& prof = Alina::Profiler::globalProfiler();
463
464 Alina::AlinaCommunicator world(ctx.messagePassingMng());
465 if (world.rank == 0)
466 std::cout << "World size: " << world.size << std::endl;
467 Alina::AlinaContext context;
468
469 // Read configuration from command line
470 ptrdiff_t n = 1024;
471 std::string deflation_type = "bilinear";
472
473 auto coarsening = Alina::eCoarserningType::smoothed_aggregation;
474 auto relaxation = Alina::eRelaxationType::spai0;
475 auto iterative_solver = Alina::eSolverType::bicgstabl;
476 auto direct_solver = Alina::eDistributedDirectSolverType::skyline_lu;
477
478 bool just_relax = false;
479 bool symm_dirichlet = true;
480 std::string problem = "laplace2d";
481 std::string parameter_file;
482 std::string out_file;
483
484 namespace po = Arcane::ProgramOptions;
485 po::options_description desc("Options");
486
487 desc.add_options()("help,h", "show help")(
488 "problem",
489 po::value<std::string>(&problem)->default_value(problem),
490 "laplace2d, recirc2d")(
491 "symbc",
492 po::value<bool>(&symm_dirichlet)->default_value(symm_dirichlet),
493 "Use symmetric Dirichlet conditions in laplace2d")(
494 "size,n",
495 po::value<ptrdiff_t>(&n)->default_value(n),
496 "domain size")(
497 "coarsening,c",
498 po::value<Alina::eCoarserningType>(&coarsening)->default_value(coarsening),
499 "ruge_stuben, aggregation, smoothed_aggregation, smoothed_aggr_emin")(
500 "relaxation,r",
501 po::value<Alina::eRelaxationType>(&relaxation)->default_value(relaxation),
502 "gauss_seidel, ilu0, iluk, ilut, damped_jacobi, spai0, spai1, chebyshev")(
503 "iter_solver,i",
504 po::value<Alina::eSolverType>(&iterative_solver)->default_value(iterative_solver),
505 "cg, bicgstab, bicgstabl, gmres")(
506 "dir_solver,d",
507 po::value<Alina::eDistributedDirectSolverType>(&direct_solver)->default_value(direct_solver),
508 "skyline_lu"
509#ifdef ARCCORE_ALINA_HAVE_PASTIX
510 ", pastix"
511#endif
512 )(
513 "deflation,v",
514 po::value<std::string>(&deflation_type)->default_value(deflation_type),
515 "constant, partitioned, linear, bilinear, mba, harmonic")(
516 "subparts",
517 po::value<int>()->default_value(16),
518 "number of partitions for partitioned deflation")(
519 "params,P",
520 po::value<std::string>(&parameter_file),
521 "parameter file in json format")(
522 "prm,p",
523 po::value<std::vector<std::string>>()->multitoken(),
524 "Parameters specified as name=value pairs. "
525 "May be provided multiple times. Examples:\n"
526 " -p solver.tol=1e-3\n"
527 " -p precond.coarse_enough=300")(
528 "just-relax,0",
529 po::bool_switch(&just_relax),
530 "Do not create AMG hierarchy, use relaxation as preconditioner")(
531 "out,o",
532 po::value<std::string>(&out_file),
533 "out file");
534
536 po::store(po::parse_command_line(argc, argv, desc), vm);
537 po::notify(vm);
538
539 if (vm.count("help")) {
540 std::cout << desc << std::endl;
541 return 0;
542 }
543
545 if (vm.count("params"))
546 prm.read_json(parameter_file);
547
548 if (vm.count("prm")) {
549 for (const std::string& v : vm["prm"].as<std::vector<std::string>>()) {
550 prm.putKeyValue(v);
551 }
552 }
553
554 prm.put("isolver.type", iterative_solver);
555 prm.put("dsolver.type", direct_solver);
556
557 const ptrdiff_t n2 = n * n;
558 const double hinv = (n - 1);
559 const double h2i = (n - 1) * (n - 1);
560 const double h = 1 / hinv;
561
562 boost::array<ptrdiff_t, 2> lo = { { 0, 0 } };
563 boost::array<ptrdiff_t, 2> hi = { { n - 1, n - 1 } };
564
565 prof.tic("partition");
566 DomainPartition<2> part(lo, hi, world.size);
567 ptrdiff_t chunk = part.size(world.rank);
568
569 std::vector<ptrdiff_t> domain(world.size + 1);
570 ConstArrayView<ptrdiff_t> send_buf(1, &chunk);
571 ArrayView<ptrdiff_t> receive_buf(world.size, &domain[1]);
572 mpAllGather(world.m_message_passing_mng.get(), send_buf, receive_buf);
573 std::partial_sum(domain.begin(), domain.end(), domain.begin());
574
575 lo = part.domain(world.rank).min_corner();
576 hi = part.domain(world.rank).max_corner();
577 prof.toc("partition");
578
579 renumbering renum(part, domain);
580
581 prof.tic("deflation");
582 std::function<double(ptrdiff_t, unsigned)> dv;
583 Int32 ndv = 1;
584
585 if (deflation_type == "constant") {
587 }
588 else if (deflation_type == "partitioned") {
589 ndv = vm["subparts"].as<int>();
590 dv = partitioned_deflation(lo, hi, ndv);
591 }
592 else if (deflation_type == "linear") {
593 ndv = 3;
594 dv = linear_deflation(chunk, lo, hi);
595 }
596 else if (deflation_type == "bilinear") {
597 bilinear_deflation bld(n, chunk, lo, hi);
598 ndv = bld.dim();
599 dv = bld;
600#ifndef SOLVER_BACKEND_CUDA
601 }
602 else if (deflation_type == "mba") {
603 mba_deflation mba(n, chunk, lo, hi);
604 ndv = mba.dim();
605 dv = mba;
606#endif
607 }
608 else if (deflation_type == "harmonic") {
609 harmonic_deflation hd(n, chunk, lo, hi);
610 ndv = hd.dim();
611 dv = hd;
612 }
613 else {
614 throw std::runtime_error("Unsupported deflation type");
615 }
616
617 prm.put("num_def_vec", ndv);
618 prm.put("def_vec", &dv);
619 prof.toc("deflation");
620
621 prof.tic("assemble");
622 std::vector<ptrdiff_t> ptr;
623 std::vector<ptrdiff_t> col;
624 std::vector<double> val;
625 std::vector<double> rhs;
626
627 ptr.reserve(chunk + 1);
628 col.reserve(chunk * 5);
629 val.reserve(chunk * 5);
630 rhs.reserve(chunk);
631
632 ptr.push_back(0);
633
634 if (problem == "recirc2d") {
635 const double eps = 1e-5;
636
637 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
638 double y = h * j;
639 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
640 double x = h * i;
641
642 if (i == 0 || j == 0 || i + 1 == n || j + 1 == n) {
643 col.push_back(renum(i, j));
644 val.push_back(1);
645 rhs.push_back(
646 sin(M_PI * x) + sin(M_PI * y) +
647 sin(13 * M_PI * x) + sin(13 * M_PI * y));
648 }
649 else {
650 double a = -sin(M_PI * x) * cos(M_PI * y) * hinv;
651 double b = sin(M_PI * y) * cos(M_PI * x) * hinv;
652
653 if (j > 0) {
654 col.push_back(renum(i, j - 1));
655 val.push_back(-eps * h2i - std::max(b, 0.0));
656 }
657
658 if (i > 0) {
659 col.push_back(renum(i - 1, j));
660 val.push_back(-eps * h2i - std::max(a, 0.0));
661 }
662
663 col.push_back(renum(i, j));
664 val.push_back(4 * eps * h2i + fabs(a) + fabs(b));
665
666 if (i + 1 < n) {
667 col.push_back(renum(i + 1, j));
668 val.push_back(-eps * h2i + std::min(a, 0.0));
669 }
670
671 if (j + 1 < n) {
672 col.push_back(renum(i, j + 1));
673 val.push_back(-eps * h2i + std::min(b, 0.0));
674 }
675
676 rhs.push_back(1.0);
677 }
678 ptr.push_back(col.size());
679 }
680 }
681 }
682 else {
683 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
684 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
685 if (!symm_dirichlet && (i == 0 || j == 0 || i + 1 == n || j + 1 == n)) {
686 col.push_back(renum(i, j));
687 val.push_back(1);
688 rhs.push_back(0);
689 }
690 else {
691 if (j > 0) {
692 col.push_back(renum(i, j - 1));
693 val.push_back(-h2i);
694 }
695
696 if (i > 0) {
697 col.push_back(renum(i - 1, j));
698 val.push_back(-h2i);
699 }
700
701 col.push_back(renum(i, j));
702 val.push_back(4 * h2i);
703
704 if (i + 1 < n) {
705 col.push_back(renum(i + 1, j));
706 val.push_back(-h2i);
707 }
708
709 if (j + 1 < n) {
710 col.push_back(renum(i, j + 1));
711 val.push_back(-h2i);
712 }
713
714 rhs.push_back(1);
715 }
716 ptr.push_back(col.size());
717 }
718 }
719 }
720 prof.toc("assemble");
721
722 Backend::params bprm;
723
724#if defined(SOLVER_BACKEND_CUDA)
725 cusparseCreate(&bprm.cusparse_handle);
726#endif
727
728 auto f = Backend::copy_vector(rhs, bprm);
729 auto x = Backend::create_vector(chunk, bprm);
730
731 Alina::backend::clear(*x);
732
733 if (just_relax) {
734 prm.put("local.class", "relaxation");
735 prm.put("local.type", relaxation);
736 }
737 else {
738 prm.put("local.coarsening.type", coarsening);
739 prm.put("local.relax.type", relaxation);
740 }
741
742 prof.tic("setup");
746
747 SDD solve(context, world, std::tie(chunk, ptr, col, val), prm, bprm);
748 prof.toc("setup");
749
750 prof.tic("solve");
751 Alina::SolverResult r = solve(*f, *x);
752 prof.toc("solve");
753
754 if (world.rank == 0) {
755 std::cout << "Iterations: " << r.nbIteration() << std::endl
756 << "Error: " << r.residual() << std::endl
757 << prof << std::endl;
758 }
759 return 0;
760}
761
762int main(int argc, char* argv[])
763{
764 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
765}
Runtime wrapper for distributed direct solvers.
Distributed solver based on subdomain deflation.
Generalized Minimal Residual (GMRES) method.
Convenience class that bundles together a preconditioner and an iterative solver.
Class to store parameters as a hierarchical key/value tree.
Definition AlinaUtils.h:113
Result of a solution.
Definition AlinaUtils.h:56
Modifiable view of an array of type T.
Constant view of an array of type T.
Describes a set of command-line options.
Stores parsed option values.
View of an array of elements of type T.
Definition Span.h:803
void mpAllGather(IMessagePassingMng *pm, const ISerializer *send_serializer, ISerializer *receive_serialize)
allGather() message for serialization
Definition Messages.cc:319
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Convenience wrapper around MPI_Comm.
Gauss-Seidel relaxation.
Definition Relaxation.h:512
Smoothed aggregation coarsening.
Pointwise constant deflation vectors.