Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
DistributedSubDomainDeflation.h
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/* DistributedSubDomainDeflation.h (C) 2000-2026 */
9/* */
10/* Distributed solver based on subdomain deflation. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_DISTRIBUTEDSUBDOMAINDEFLATION_H
13#define ARCCORE_ALINA_DISTRIBUTEDSUBDOMAINDEFLATION_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16/*
17 * This file is based on the work on AMGCL library (version march 2026)
18 * which can be found at https://github.com/ddemidov/amgcl.
19 *
20 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
21 * SPDX-License-Identifier: MIT
22 */
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26#include "arccore/alina/BuiltinBackend.h"
27#include "arccore/alina/Adapters.h"
28#include "arccore/alina/MessagePassingUtils.h"
29#include "arccore/alina/DistributedSkylineLUDirectSolver.h"
30#include "arccore/alina/DistributedInnerProduct.h"
31#include "arccore/alina/DistributedMatrix.h"
32
33#include <vector>
34#include <algorithm>
35#include <numeric>
36#include <memory>
37#include <functional>
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42namespace Arcane::Alina
43{
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
50{
51 const int block_size;
57 constant_deflation(int block_size = 1)
58 : block_size(block_size)
59 {}
60
61 int dim() const
62 {
63 return block_size;
64 }
65
66 int operator()(ptrdiff_t row, int j) const
67 {
68 return row % block_size == j;
69 }
70};
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75template <class SDD, class Matrix>
76struct sdd_projected_matrix
77{
78 typedef typename SDD::value_type value_type;
79
80 const SDD& S;
81 const Matrix& A;
82
83 sdd_projected_matrix(const SDD& S, const Matrix& A)
84 : S(S)
85 , A(A)
86 {}
87
88 template <class T, class Vec1, class Vec2>
89 void mul(T alpha, const Vec1& x, T beta, Vec2& y) const
90 {
91 ARCCORE_ALINA_TIC("top/spmv");
92 backend::spmv(alpha, A, x, beta, y);
93 ARCCORE_ALINA_TOC("top/spmv");
94
95 S.project(y);
96 }
97
98 template <class Vec1, class Vec2, class Vec3>
99 void residual(const Vec1& f, const Vec2& x, Vec3& r) const
100 {
101 ARCCORE_ALINA_TIC("top/residual");
102 backend::residual(f, A, x, r);
103 ARCCORE_ALINA_TOC("top/residual");
104
105 S.project(r);
106 }
107};
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
111
112template <class SDD, class Matrix>
113sdd_projected_matrix<SDD, Matrix> make_sdd_projected_matrix(const SDD& S, const Matrix& A)
114{
116}
117
118/*---------------------------------------------------------------------------*/
119/*---------------------------------------------------------------------------*/
120
126template <class LocalPrecond,
127 class IterativeSolver,
128 class DirectSolver = DistributedSkylineLUDirectSolver<typename LocalPrecond::backend_type>>
129class DistributedSubDomainDeflation
130{
131 public:
132
133 typedef typename LocalPrecond::backend_type backend_type;
134 typedef typename backend_type::params backend_params;
135
136 struct params
137 {
138 typename LocalPrecond::params local;
139 typename IterativeSolver::params isolver;
140 typename DirectSolver::params dsolver;
141
142 // Number of deflation vectors.
143 Int32 num_def_vec = 0;
144
145 // Value of deflation vector at the given row and column.
146 std::function<double(ptrdiff_t, unsigned)> def_vec;
147
148 params() {}
149
150 params(const PropertyTree& p)
151 : ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, local)
152 , ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, isolver)
153 , ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, dsolver)
154 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, num_def_vec)
155 {
156 void* ptr = 0;
157 ptr = p.get("def_vec", ptr);
158
159 precondition(ptr, "Error in subdomain_deflation parameters: def_vec is not set");
160
161 def_vec = *static_cast<std::function<double(ptrdiff_t, unsigned)>*>(ptr);
162
163 p.check_params({ "local", "isolver", "dsolver", "num_def_vec", "def_vec" });
164 }
165
166 void get(PropertyTree& p, const std::string& path) const
167 {
168 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, local);
169 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, isolver);
170 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, dsolver);
171 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, num_def_vec);
172 }
173 };
174
175 typedef typename backend_type::value_type value_type;
176 typedef typename math::scalar_of<value_type>::type scalar_type;
177 typedef typename backend_type::matrix bmatrix;
178 using col_type = backend_type::col_type;
179 using ptr_type = backend_type::ptr_type;
180 typedef typename backend_type::vector vector;
181 typedef DistributedMatrix<backend_type> matrix;
182
183 template <class Matrix>
184 DistributedSubDomainDeflation(const AlinaContext& context,
186 const Matrix& Astrip,
187 const params& prm = params(),
188 const backend_params& bprm = backend_params())
189 : comm(comm)
190 , nrows(backend::nbRow(Astrip))
191 , ndv(prm.num_def_vec)
192 , dv_start(comm.size + 1, 0)
193 , Z(ndv)
194 , q(backend_type::create_vector(nrows, bprm))
195 , S(context, nrows, prm.isolver, bprm, DistributedInnerProduct(comm))
196 {
197 A = std::make_shared<matrix>(comm, Astrip, nrows);
198 init(context, prm, bprm);
199 }
200
203 std::shared_ptr<matrix> A,
204 const params& prm = params(),
205 const backend_params& bprm = backend_params())
206 : comm(comm)
207 , nrows(A->loc_rows())
208 , ndv(prm.num_def_vec)
209 , A(A)
210 , dv_start(comm.size + 1, 0)
211 , Z(ndv)
212 , q(backend_type::create_vector(nrows, bprm))
213 , S(context, nrows, prm.isolver, bprm, DistributedInnerProduct(comm))
214 {
215 init(context, prm, bprm);
216 }
217
218 void init(const AlinaContext& context,
219 const params& prm = params(),
220 const backend_params& bprm = backend_params())
221 {
222 ARCCORE_ALINA_TIC("setup deflation");
223 using build_matrix = CSRMatrix<value_type, col_type, ptr_type>;
224
225 // Lets see how many deflation vectors are there.
226 std::vector<ptrdiff_t> dv_size(comm.size);
227
228 {
229 ConstArrayView<ptrdiff_t> send_buf(1, &ndv);
230 ArrayView<ptrdiff_t> receive_buf(comm.size, &dv_size[0]);
231
232 mpAllGather(comm.m_message_passing_mng.get(), send_buf, receive_buf);
233 }
234
235 std::partial_sum(dv_size.begin(), dv_size.end(), dv_start.begin() + 1);
236 nz = dv_start.back();
237
238 df.resize(ndv);
239 dx.resize(ndv);
240 dd = backend_type::create_vector(ndv, bprm);
241
242 auto az_loc = std::make_shared<build_matrix>();
243 auto az_rem = std::make_shared<build_matrix>();
244
245 auto a_loc = A->local();
246 auto a_rem = A->remote();
247
248 const CommunicationPattern<backend_type>& Acp = A->cpat();
249
250 // Fill deflation vectors.
251 ARCCORE_ALINA_TIC("copy deflation vectors");
252 {
253 std::vector<value_type> z(nrows);
254 for (int j = 0; j < ndv; ++j) {
255 arccoreParallelFor(0, nrows, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
256 for (ptrdiff_t i = begin; i < (begin + size); ++i)
257 z[i] = prm.def_vec(i, j);
258 });
259 Z[j] = backend_type::copy_vector(z, bprm);
260 }
261 }
262 ARCCORE_ALINA_TOC("copy deflation vectors");
263
264 ARCCORE_ALINA_TIC("first pass");
265 az_loc->set_size(nrows, ndv, true);
266 az_loc->set_nonzeros(nrows * dv_size[comm.rank]);
267 az_rem->set_size(nrows, 0, true);
268 // 1. Build local part of AZ matrix.
269 // 2. Count remote nonzeros
270 arccoreParallelFor(0, nrows, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
271 std::vector<ptrdiff_t> marker(Acp.recv.nbr.size(), -1);
272
273 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
274 ptrdiff_t az_loc_head = i * ndv;
275 az_loc->ptr[i + 1] = az_loc_head + ndv;
276
277 for (ptrdiff_t j = 0; j < ndv; ++j) {
278 az_loc->col[az_loc_head + j] = j;
279 az_loc->val[az_loc_head + j] = math::zero<value_type>();
280 }
281
282 for (ptrdiff_t j = a_loc->ptr[i], e = a_loc->ptr[i + 1]; j < e; ++j) {
283 ptrdiff_t c = a_loc->col[j];
284 value_type v = a_loc->val[j];
285
286 for (ptrdiff_t j = 0; j < ndv; ++j)
287 az_loc->val[az_loc_head + j] += v * prm.def_vec(c, j);
288 }
289
290 for (ptrdiff_t j = a_rem->ptr[i], e = a_rem->ptr[i + 1]; j < e; ++j) {
291 int d = Acp.domain(a_rem->col[j]);
292
293 if (marker[d] != i) {
294 marker[d] = i;
295 az_rem->ptr[i + 1] += dv_size[d];
296 }
297 }
298 }
299 });
300
301 az_rem->set_nonzeros(az_rem->scan_row_sizes());
302 ARCCORE_ALINA_TOC("first pass");
303
304 // Create local preconditioner.
305 ARCCORE_ALINA_TIC("local preconditioner");
306 P = std::make_shared<LocalPrecond>(context, *a_loc, prm.local, bprm);
307 ARCCORE_ALINA_TOC("local preconditioner");
308
309 A->set_local(P->system_matrix_ptr());
310 A->move_to_backend(bprm);
311
312 ARCCORE_ALINA_TIC("remote(A*Z)");
313 /* Construct remote part of AZ */
314 // Exchange deflation vectors
315 std::vector<ptrdiff_t> zrecv_ptr(Acp.recv.nbr.size() + 1, 0);
316 std::vector<ptrdiff_t> zcol_ptr;
317 zcol_ptr.reserve(Acp.recv.count() + 1);
318 zcol_ptr.push_back(0);
319
320 for (size_t i = 0; i < Acp.recv.nbr.size(); ++i) {
321 ptrdiff_t ncols = Acp.recv.ptr[i + 1] - Acp.recv.ptr[i];
322 ptrdiff_t nvecs = dv_size[Acp.recv.nbr[i]];
323 ptrdiff_t size = nvecs * ncols;
324 zrecv_ptr[i + 1] = zrecv_ptr[i] + size;
325
326 for (ptrdiff_t j = 0; j < ncols; ++j)
327 zcol_ptr.push_back(zcol_ptr.back() + nvecs);
328 }
329
330 std::vector<value_type> zrecv(zrecv_ptr.back());
331 std::vector<value_type> zsend(Acp.send.count() * ndv);
332
333 for (size_t i = 0; i < Acp.recv.nbr.size(); ++i) {
334 ptrdiff_t begin = zrecv_ptr[i];
335 ptrdiff_t size = zrecv_ptr[i + 1] - begin;
336
337 Acp.recv.req[i] = comm.doIReceive(&zrecv[begin], size, Acp.recv.nbr[i], tag_exc_vals);
338 }
339
340 for (size_t i = 0, k = 0; i < Acp.send.count(); ++i)
341 for (ptrdiff_t j = 0; j < ndv; ++j, ++k)
342 zsend[k] = prm.def_vec(Acp.send.col[i], j);
343
344 for (size_t i = 0; i < Acp.send.nbr.size(); ++i)
345 Acp.send.req[i] = comm.doISend(&zsend[ndv * Acp.send.ptr[i]], ndv * (Acp.send.ptr[i + 1] - Acp.send.ptr[i]),
346 Acp.send.nbr[i], tag_exc_vals);
347
348 comm.waitAll(Acp.recv.req);
349 comm.waitAll(Acp.send.req);
350
351 arccoreParallelFor(0, nrows, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
352 std::vector<ptrdiff_t> marker(nz, -1);
353
354 // AZ_rem = Arem * Z
355 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
356 ptrdiff_t az_rem_head = az_rem->ptr[i];
357 ptrdiff_t az_rem_tail = az_rem_head;
358
359 for (auto a = backend::row_begin(*a_rem, i); a; ++a) {
360 ptrdiff_t c = a.col();
361 value_type v = a.value();
362
363 // Domain the column belongs to
364 ptrdiff_t d = Acp.recv.nbr[std::upper_bound(Acp.recv.ptr.begin(), Acp.recv.ptr.end(), c) -
365 Acp.recv.ptr.begin() - 1];
366
367 value_type* zval = &zrecv[zcol_ptr[c]];
368 for (ptrdiff_t j = 0, k = dv_start[d]; j < dv_size[d]; ++j, ++k) {
369 if (marker[k] < az_rem_head) {
370 marker[k] = az_rem_tail;
371 az_rem->col[az_rem_tail] = k;
372 az_rem->val[az_rem_tail] = v * zval[j];
373 ++az_rem_tail;
374 }
375 else {
376 az_rem->val[marker[k]] += v * zval[j];
377 }
378 }
379 }
380 }
381 });
382 ARCCORE_ALINA_TOC("remote(A*Z)");
383
384 /* Build solver for the deflated matrix E. */
385 ARCCORE_ALINA_TIC("assemble E");
386
387 // Count nonzeros in E.
388 std::vector<int> nbrs; // processes we are talking to
389 nbrs.reserve(1 + Acp.send.nbr.size() + Acp.recv.nbr.size());
390 std::set_union(
391 Acp.send.nbr.begin(), Acp.send.nbr.end(),
392 Acp.recv.nbr.begin(), Acp.recv.nbr.end(),
393 std::back_inserter(nbrs));
394 nbrs.push_back(comm.rank);
395
396 build_matrix E;
397 E.set_size(ndv, nz, false);
398
399 {
400 ptrdiff_t nnz = 0;
401 for (int j : nbrs)
402 nnz += dv_size[j];
403 for (int k = 0; k <= ndv; ++k)
404 E.ptr[k] = k * nnz;
405 }
406 E.setNbNonZero(E.ptr[ndv]);
407 E.set_nonzeros(E.ptr[ndv]);
408
409 // Build local strip of E.
410 int nthreads = ConcurrencyBase::maxAllowedThread();
411 multi_array<value_type, 3> erow(nthreads, ndv, nz);
412 std::fill_n(erow.data(), erow.size(), 0);
413
414 {
415 ptrdiff_t dv_offset = dv_start[comm.rank];
416 arccoreParallelFor(0, nrows, ForLoopRunInfo{}, [&](Int32 begin, Int32 size) {
417 const int tid = TaskFactory::currentTaskThreadIndex();
418 std::vector<value_type> z(ndv);
419
420 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
421 for (ptrdiff_t j = 0; j < ndv; ++j)
422 z[j] = prm.def_vec(i, j);
423
424 for (ptrdiff_t k = az_loc->ptr[i], e = az_loc->ptr[i + 1]; k < e; ++k) {
425 ptrdiff_t c = az_loc->col[k] + dv_offset;
426 value_type v = az_loc->val[k];
427
428 for (ptrdiff_t j = 0; j < ndv; ++j)
429 erow(tid, j, c) += v * z[j];
430 }
431
432 for (ptrdiff_t k = az_rem->ptr[i], e = az_rem->ptr[i + 1]; k < e; ++k) {
433 ptrdiff_t c = az_rem->col[k];
434 value_type v = az_rem->val[k];
435
436 for (ptrdiff_t j = 0; j < ndv; ++j)
437 erow(tid, j, c) += v * z[j];
438 }
439 }
440 });
441 }
442
443 for (int i = 0; i < ndv; ++i) {
444 int row_head = E.ptr[i];
445 for (int j : nbrs) {
446 for (int k = 0; k < dv_size[j]; ++k) {
447 int c = dv_start[j] + k;
448 value_type v = math::zero<value_type>();
449 for (int t = 0; t < nthreads; ++t)
450 v += erow(t, i, c);
451
452 E.col[row_head] = c;
453 E.val[row_head] = v;
454
455 ++row_head;
456 }
457 }
458 }
459 ARCCORE_ALINA_TOC("assemble E");
460
461 ARCCORE_ALINA_TIC("factorize E");
462 this->E = std::make_shared<DirectSolver>(comm, E, prm.dsolver);
463 ARCCORE_ALINA_TOC("factorize E");
464
465 ARCCORE_ALINA_TIC("finish(A*Z)");
466 AZ = std::make_shared<matrix>(comm, az_loc, az_rem);
467 AZ->move_to_backend(bprm);
468 ARCCORE_ALINA_TOC("finish(A*Z)");
469 ARCCORE_ALINA_TOC("setup deflation");
470 }
471
472 template <class Vec1, class Vec2>
473 void apply(const Vec1& rhs, Vec2&& x) const
474 {
475 size_t iters;
476 double error;
477 backend::clear(x);
478 std::tie(iters, error) = (*this)(rhs, x);
479 }
480
481 std::shared_ptr<matrix> system_matrix_ptr() const
482 {
483 return A;
484 }
485
486 const matrix& system_matrix() const
487 {
488 return *A;
489 }
490
491 template <class Matrix, class Vec1, class Vec2>
492 std::tuple<size_t, value_type> operator()(
493 const Matrix& A, const Vec1& rhs, Vec2&& x) const
494 {
495 std::tuple<size_t, value_type> cnv = S(make_sdd_projected_matrix(*this, A), *P, rhs, x);
496 postprocess(rhs, x);
497 return cnv;
498 }
499
500 template <class Vec1, class Vec2>
501 std::tuple<size_t, value_type>
502 operator()(const Vec1& rhs, Vec2&& x) const
503 {
504 std::tuple<size_t, value_type> cnv = S(make_sdd_projected_matrix(*this, *A), *P, rhs, x);
505 postprocess(rhs, x);
506 return cnv;
507 }
508
509 size_t size() const
510 {
511 return nrows;
512 }
513
514 template <class Vector>
515 void project(Vector& x) const
516 {
517 const auto one = math::identity<scalar_type>();
518
519 ARCCORE_ALINA_TIC("project");
520
521 ARCCORE_ALINA_TIC("local inner product");
522 for (ptrdiff_t j = 0; j < ndv; ++j)
523 df[j] = backend::inner_product(x, *Z[j]);
524 ARCCORE_ALINA_TOC("local inner product");
525
526 coarse_solve(df, dx);
527
528 ARCCORE_ALINA_TIC("spmv");
529 backend::copy(dx, *dd);
530 backend::spmv(-one, *AZ, *dd, one, x);
531 ARCCORE_ALINA_TOC("spmv");
532
533 ARCCORE_ALINA_TOC("project");
534 }
535
536 private:
537
538 static const int tag_exc_vals = 2011;
539 static const int tag_exc_dmat = 3011;
540 static const int tag_exc_dvec = 4011;
541 static const int tag_exc_lnnz = 5011;
542
543 AlinaCommunicator comm;
544 ptrdiff_t nrows, ndv, nz;
545
546 std::shared_ptr<matrix> A, AZ;
547 std::shared_ptr<LocalPrecond> P;
548
549 mutable std::vector<value_type> df, dx;
550 std::vector<ptrdiff_t> dv_start;
551
552 std::vector<std::shared_ptr<vector>> Z;
553
554 std::shared_ptr<DirectSolver> E;
555
556 std::shared_ptr<vector> q;
557 std::shared_ptr<vector> dd;
558
559 IterativeSolver S;
560
561 void coarse_solve(std::vector<value_type>& f, std::vector<value_type>& x) const
562 {
563 ARCCORE_ALINA_TIC("coarse solve");
564 (*E)(f, x);
565 ARCCORE_ALINA_TOC("coarse solve");
566 }
567
568 template <class Vec1, class Vec2>
569 void postprocess(const Vec1& rhs, Vec2& x) const
570 {
571 const auto one = math::identity<scalar_type>();
572
573 ARCCORE_ALINA_TIC("postprocess");
574
575 // q = rhs - Ax
576 backend::copy(rhs, *q);
577 backend::spmv(-one, *A, x, one, *q);
578
579 // df = transp(Z) * (rhs - Ax)
580 ARCCORE_ALINA_TIC("local inner product");
581 for (ptrdiff_t j = 0; j < ndv; ++j)
582 df[j] = backend::inner_product(*q, *Z[j]);
583 ARCCORE_ALINA_TOC("local inner product");
584
585 // dx = inv(E) * df
586 coarse_solve(df, dx);
587
588 // x += Z * dx
589 backend::lin_comb(ndv, dx, Z, one, x);
590
591 ARCCORE_ALINA_TOC("postprocess");
592 }
593};
594
595/*---------------------------------------------------------------------------*/
596/*---------------------------------------------------------------------------*/
597
598} // namespace Arcane::Alina
599
600/*---------------------------------------------------------------------------*/
601/*---------------------------------------------------------------------------*/
602
603namespace Arcane::Alina::backend
604{
605
606template <class SDD, class Matrix,
607 class Alpha, class Beta, class Vec1, class Vec2>
608struct spmv_impl<Alpha, sdd_projected_matrix<SDD, Matrix>, Vec1, Beta, Vec2>
609{
611
612 static void apply(Alpha alpha, const M& A, const Vec1& x, Beta beta, Vec2& y)
613 {
614 A.mul(alpha, x, beta, y);
615 }
616};
617
618template <class SDD, class Matrix, class Vec1, class Vec2, class Vec3>
619struct residual_impl<sdd_projected_matrix<SDD, Matrix>, Vec1, Vec2, Vec3>
620{
622
623 static void apply(const Vec1& rhs, const M& A, const Vec2& x, Vec3& r)
624 {
625 A.residual(rhs, x, r);
626 }
627};
628
629/*---------------------------------------------------------------------------*/
630/*---------------------------------------------------------------------------*/
631
632} // namespace Arcane::Alina::backend
633
634/*---------------------------------------------------------------------------*/
635/*---------------------------------------------------------------------------*/
636
637#endif
Distributed Matrix using message passing.
Distributed solver based on subdomain deflation.
Class to store parameters as a hierarchical key/value tree.
Definition AlinaUtils.h:113
Modifiable view of an array of type T.
static Int32 maxAllowedThread()
Maximum number of allowed threads for multi-threading.
Constant view of an array of type T.
Matrix class, to be used by user.
static Int32 currentTaskThreadIndex()
Index (between 0 and nbAllowedThread()-1) of the thread executing the current task.
void mpAllGather(IMessagePassingMng *pm, const ISerializer *send_serializer, ISerializer *receive_serialize)
allGather() message for serialization
Definition Messages.cc:319
void arccoreParallelFor(const ComplexForLoopRanges< RankValue, IndexType_ > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applies the lambda function lambda_function concurrently over the iteration interval given by loop_ra...
Definition ParallelFor.h:86
std::int32_t Int32
Signed integer type of 32 bits.
Convenience wrapper around MPI_Comm.
Inner product for distributed vectors.
Implementation for residual error compuatation.
Implementation for matrix-vector product.
constant_deflation(int block_size=1)
Constructor.