44class DistributedCPRPreconditioner
46 static_assert(std::is_same<
47 typename PPrecond::BackendType,
48 typename SPrecond::BackendType>::value,
49 "Backends for pressure and flow preconditioners should coinside!");
53 using BackendType = PPrecond::BackendType;
55 typedef BackendType::value_type value_type;
56 typedef math::scalar_of<value_type>::type scalar_type;
57 typedef BackendType::matrix bmatrix;
58 typedef BackendType::vector vector;
59 typedef BackendType::params backend_params;
62 typedef typename BuiltinBackend<value_type>::matrix build_matrix;
66 typedef typename PPrecond::params pprecond_params;
67 typedef typename SPrecond::params sprecond_params;
69 pprecond_params pprecond;
70 sprecond_params sprecond;
77 : ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, pprecond)
78 , ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, sprecond)
79 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, block_size)
81 p.check_params({
"pprecond",
"sprecond",
"block_size",
"active_rows" });
84 void get(
PropertyTree& p,
const std::string& path =
"")
const
86 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, pprecond);
87 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, sprecond);
88 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, block_size);
92 template <
class Matrix>
93 DistributedCPRPreconditioner(
const AlinaContext& context,
97 const backend_params& bprm = backend_params())
100 , n(backend::nbRow(K))
102 init(context, std::make_shared<matrix>(comm, K, backend::nbRow(K)), bprm);
107 std::shared_ptr<matrix> K,
109 const backend_params& bprm = backend_params())
114 init(context, K, bprm);
117 template <
class Vec1,
class Vec2>
118 void apply(
const Vec1& rhs, Vec2&& x)
const
120 const auto one = math::identity<scalar_type>();
121 const auto zero = math::zero<scalar_type>();
124 backend::residual(rhs, S->system_matrix(), x, *rs);
126 backend::spmv(one, *Fpp, *rs, zero, *rp);
129 backend::spmv(one, *Scatter, *xp, one, x);
132 std::shared_ptr<matrix> system_matrix_ptr()
const
134 return S->system_matrix_ptr();
137 const matrix& system_matrix()
const
139 return S->system_matrix();
148 AlinaCommunicator comm;
151 std::shared_ptr<PPrecond> P;
152 std::shared_ptr<SPrecond> S;
154 std::shared_ptr<bmatrix> Fpp, Scatter;
155 std::shared_ptr<vector> rp, xp, rs;
157 void init(
const AlinaContext& context, std::shared_ptr<matrix> K,
const backend_params& bprm)
159 typedef typename backend::row_iterator<build_matrix>::type row_iterator;
160 const int B = prm.block_size;
162 auto _K_loc = K->local();
163 auto _K_rem = K->remote();
165 auto& K_loc = *_K_loc;
166 auto& K_rem = *_K_rem;
170 auto fpp = std::make_shared<build_matrix>();
171 fpp->set_size(np, n);
172 fpp->set_nonzeros(n);
175 auto App_loc = std::make_shared<build_matrix>();
176 auto App_rem = std::make_shared<build_matrix>();
178 App_loc->set_size(np, np,
true);
179 App_rem->set_size(np, 0,
true);
184 std::vector<row_iterator> k;
186 multi_array<value_type, 2> v(B, B);
188 for (ptrdiff_t ip = begin; ip < (begin + size); ++ip) {
189 ptrdiff_t ik = ip * B;
191 ptrdiff_t cur_col = 0;
195 for (
int i = 0; i < B; ++i) {
196 k.push_back(backend::row_begin(K_loc, ik + i));
199 ptrdiff_t col = k.back().col() / B;
205 cur_col = std::min(cur_col, col);
209 fpp->col[ik + i] = ik + i;
211 fpp->ptr[ip + 1] = ik + B;
214 ++App_loc->ptr[ip + 1];
216 ptrdiff_t end = (cur_col + 1) * B;
222 for (
int i = 0; i < B; ++i)
223 for (
int j = 0; j < B; ++j)
226 for (
int i = 0; i < B; ++i)
227 for (; k[i] && k[i].col() < end; ++k[i])
228 v(k[i].col() % B, i) = k[i].value();
230 invert(v, &fpp->val[ik]);
235 for (
int i = 0; i < B; ++i)
236 while (k[i] && k[i].col() < end)
242 for (
int i = 0; i < B; ++i) {
244 ptrdiff_t col = k[i].col() / B;
250 cur_col = std::min(cur_col, col);
258 for (
int i = 0; i < B; ++i) {
259 k.push_back(backend::row_begin(K_rem, ik + i));
262 ptrdiff_t col = k.back().col() / B;
268 cur_col = std::min(cur_col, col);
274 ++App_rem->ptr[ip + 1];
276 ptrdiff_t end = (cur_col + 1) * B;
278 for (
int i = 0; i < B; ++i)
279 while (k[i] && k[i].col() < end)
284 for (
int i = 0; i < B; ++i) {
286 ptrdiff_t col = k[i].col() / B;
292 cur_col = std::min(cur_col, col);
300 App_loc->set_nonzeros(App_loc->scan_row_sizes());
301 App_rem->set_nonzeros(App_rem->scan_row_sizes());
303 auto scatter = std::make_shared<build_matrix>();
304 scatter->set_size(n, np);
305 scatter->set_nonzeros(np);
309 std::vector<row_iterator> k;
312 for (ptrdiff_t ip = begin; ip < (begin + size); ++ip) {
313 ptrdiff_t ik = ip * B;
317 value_type* d = &fpp->val[ik];
320 ptrdiff_t head = App_loc->ptr[ip];
322 for (
int i = 0; i < B; ++i) {
323 k.push_back(backend::row_begin(K_loc, ik + i));
326 ptrdiff_t col = k.back().col() / B;
332 cur_col = std::min(cur_col, col);
338 ptrdiff_t end = (cur_col + 1) * B;
341 for (
int i = 0; i < B; ++i) {
342 for (; k[i] && k[i].col() < end; ++k[i]) {
343 if (k[i].col() % B == 0) {
344 app += d[i] * k[i].value();
349 App_loc->col[head] = cur_col;
350 App_loc->val[head] = app;
355 for (
int i = 0; i < B; ++i) {
357 ptrdiff_t col = k[i].col() / B;
363 cur_col = std::min(cur_col, col);
370 head = App_rem->ptr[ip];
372 for (
int i = 0; i < B; ++i) {
373 k.push_back(backend::row_begin(K_rem, ik + i));
376 ptrdiff_t col = k.back().col() / B;
382 cur_col = std::min(cur_col, col);
388 ptrdiff_t end = (cur_col + 1) * B;
391 for (
int i = 0; i < B; ++i) {
392 for (; k[i] && k[i].col() < end; ++k[i]) {
393 if (k[i].col() % B == 0) {
394 app += d[i] * k[i].value();
399 App_rem->col[head] = cur_col;
400 App_rem->val[head] = app;
405 for (
int i = 0; i < B; ++i) {
407 ptrdiff_t col = k[i].col() / B;
413 cur_col = std::min(cur_col, col);
419 scatter->col[ip] = ip;
420 scatter->val[ip] = math::identity<value_type>();
423 for (
int i = 0; i < B; ++i) {
426 scatter->ptr[ik + i + 1] = nnz;
431 auto App = std::make_shared<matrix>(comm, App_loc, App_rem);
433 P = std::make_shared<PPrecond>(context, comm, App, prm.pprecond, bprm);
434 S = std::make_shared<SPrecond>(context, comm, K, prm.sprecond, bprm);
436 Fpp = BackendType::copy_matrix(fpp, bprm);
437 Scatter = BackendType::copy_matrix(scatter, bprm);
439 rp = BackendType::create_vector(np, bprm);
440 xp = BackendType::create_vector(np, bprm);
441 rs = BackendType::create_vector(n, bprm);
446 void invert(multi_array<value_type, 2>& A, value_type* y)
448 const int B = prm.block_size;
451 for (
int k = 0; k < B; ++k) {
452 value_type d = A(k, k);
453 assert(!math::is_zero(d));
454 for (
int i = k + 1; i < B; ++i) {
456 for (
int j = k + 1; j < B; ++j)
457 A(i, j) -= A(i, k) * A(k, j);
463 for (
int i = 0; i < B; ++i) {
464 value_type b =
static_cast<value_type
>(i == 0);
465 for (
int j = 0; j < i; ++j)
471 for (
int i = B; i-- > 0;) {
472 for (
int j = i + 1; j < B; ++j)
473 y[i] -= A(i, j) * y[j];
478 template <
class P,
class S>
479 friend std::ostream& operator<<(std::ostream& os,
const DistributedCPRPreconditioner<P, S>& cpr)
481 os <<
"CPR (two-stage preconditioner)\n"
482 "### Pressure preconditioner:\n"
484 "### Global preconditioner:\n"
485 << *cpr.S << std::endl;