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