45class CPRPreconditioner
48 "Pressure backend should have scalar value type!");
51 typename PPrecond::backend_type,
52 typename SPrecond::backend_type>::value,
53 "Backends for pressure and flow preconditioners should coincide!");
57 typedef typename SPrecond::backend_type backend_type;
58 typedef typename PPrecond::backend_type backend_type_p;
60 typedef typename backend_type::value_type value_type;
61 typedef typename backend_type::matrix matrix;
62 typedef typename backend_type::vector vector;
63 typedef typename backend_type_p::value_type value_type_p;
64 typedef typename backend_type_p::matrix matrix_p;
65 typedef typename backend_type_p::vector vector_p;
67 typedef typename backend_type::params backend_params;
69 typedef typename BuiltinBackend<value_type>::matrix build_matrix;
70 typedef typename BuiltinBackend<value_type_p>::matrix build_matrix_p;
72 typedef typename math::scalar_of<value_type>::type scalar_type;
76 typedef typename PPrecond::params pprecond_params;
77 typedef typename SPrecond::params sprecond_params;
79 pprecond_params pprecond;
80 sprecond_params sprecond;
84 Int32 active_rows = 0;
89 : ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, pprecond)
90 , ARCCORE_ALINA_PARAMS_IMPORT_CHILD(p, sprecond)
91 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, block_size)
92 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, active_rows)
94 p.check_params({
"pprecond",
"sprecond",
"block_size",
"active_rows" });
97 void get(
PropertyTree& p,
const std::string& path =
"")
const
99 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, pprecond);
100 ARCCORE_ALINA_PARAMS_EXPORT_CHILD(p, path, sprecond);
101 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, block_size);
102 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, active_rows);
106 template <
class Matrix>
110 const backend_params& bprm = backend_params())
112 , n(backend::nbRow(K))
114 init(context, std::make_shared<build_matrix>(K), bprm,
119 std::shared_ptr<build_matrix> K,
121 const backend_params& bprm = backend_params())
123 , n(backend::nbRow(*K))
125 init(context, K, bprm,
129 template <
class Vec1,
class Vec2>
130 void apply(
const Vec1& rhs, Vec2&& x)
const
132 const auto one = math::identity<scalar_type>();
133 const auto zero = math::zero<scalar_type>();
135 ARCCORE_ALINA_TIC(
"sprecond");
137 ARCCORE_ALINA_TOC(
"sprecond");
138 backend::residual(rhs, S->system_matrix(), x, *rs);
140 backend::spmv(one, *Fpp, *rs, zero, *rp);
141 ARCCORE_ALINA_TIC(
"pprecond");
143 ARCCORE_ALINA_TOC(
"pprecond");
145 backend::spmv(one, *Scatter, *xp, one, x);
148 std::shared_ptr<matrix> system_matrix_ptr()
const
150 return S->system_matrix_ptr();
153 const matrix& system_matrix()
const
155 return S->system_matrix();
158 template <
class Matrix>
159 void partial_update(
const Matrix& K,
160 bool update_transfer_ops =
true,
161 const backend_params& bprm = backend_params())
163 auto K_ptr = std::make_shared<build_matrix>(K);
165 S = std::make_shared<SPrecond>(K_ptr, prm.sprecond, bprm);
166 if (update_transfer_ops) {
171 std::integral_constant<
bool, math::static_rows<value_type>::value == 1>());
181 std::shared_ptr<PPrecond> P;
182 std::shared_ptr<SPrecond> S;
184 std::shared_ptr<matrix_p> Fpp, Scatter;
185 std::shared_ptr<vector> rs;
186 std::shared_ptr<vector_p> rp, xp;
190 std::tuple<std::shared_ptr<build_matrix_p>, std::shared_ptr<build_matrix_p>>
191 first_scalar_pass(std::shared_ptr<build_matrix> K,
bool get_app =
true)
193 typedef typename backend::row_iterator<build_matrix>::type row_iterator;
194 const int B = prm.block_size;
195 const ptrdiff_t N = (prm.active_rows ? prm.active_rows : n);
199 auto fpp = std::make_shared<build_matrix_p>();
200 fpp->set_size(np, N);
201 fpp->set_nonzeros(N);
204 std::shared_ptr<build_matrix_p> App;
207 App = std::make_shared<build_matrix>();
208 App->set_size(np, np,
true);
214 std::vector<row_iterator> k;
216 multi_array<scalar_type, 2> v(B, B);
218 for (ptrdiff_t ip = begin; ip < (begin + size); ++ip) {
219 ptrdiff_t ik = ip * B;
221 ptrdiff_t cur_col = 0;
224 for (
int i = 0; i < B; ++i) {
225 k.push_back(backend::row_begin(*K, ik + i));
227 if (k.back() && k.back().col() < N) {
228 ptrdiff_t col = k.back().col() / B;
234 cur_col = std::min(cur_col, col);
238 fpp->col[ik + i] = ik + i;
240 fpp->ptr[ip + 1] = ik + B;
246 ptrdiff_t end = (cur_col + 1) * B;
252 for (
int i = 0; i < B; ++i)
253 for (
int j = 0; j < B; ++j)
256 for (
int i = 0; i < B; ++i)
257 for (; k[i] && k[i].col() < end; ++k[i])
258 v(k[i].col() % B, i) = k[i].value();
260 invert(v.data(), &fpp->val[ik]);
268 for (
int i = 0; i < B; ++i)
269 while (k[i] && k[i].col() < end)
275 for (
int i = 0; i < B; ++i) {
276 if (k[i] && k[i].col() < N) {
277 ptrdiff_t col = k[i].col() / B;
283 cur_col = std::min(cur_col, col);
292 App->set_nonzeros(App->scan_row_sizes());
294 return std::make_tuple(fpp, App);
298 void init(
const AlinaContext& context, std::shared_ptr<build_matrix> K,
299 const backend_params bprm, std::true_type)
301 typedef typename backend::row_iterator<build_matrix>::type row_iterator;
302 const int B = prm.block_size;
303 const ptrdiff_t N = (prm.active_rows ? prm.active_rows : n);
307 std::shared_ptr<build_matrix_p> fpp, App;
308 std::tie(fpp, App) = first_scalar_pass(K);
310 auto scatter = std::make_shared<build_matrix_p>();
311 scatter->set_size(n, np);
312 scatter->set_nonzeros(np);
316 std::vector<row_iterator> k;
319 for (ptrdiff_t ip = begin; ip < (begin + size); ++ip) {
320 ptrdiff_t ik = ip * B;
321 ptrdiff_t head = App->ptr[ip];
325 value_type_p* d = &fpp->val[ik];
328 for (
int i = 0; i < B; ++i) {
329 k.push_back(backend::row_begin(*K, ik + i));
331 if (k.back() && k.back().col() < N) {
332 ptrdiff_t col = k.back().col() / B;
338 cur_col = std::min(cur_col, col);
344 ptrdiff_t end = (cur_col + 1) * B;
345 value_type_p app = 0;
347 for (
int i = 0; i < B; ++i) {
348 for (; k[i] && k[i].col() < end; ++k[i]) {
349 if (k[i].col() % B == 0) {
350 app += d[i] * k[i].value();
355 App->col[head] = cur_col;
356 App->val[head] = app;
361 for (
int i = 0; i < B; ++i) {
362 if (k[i] && k[i].col() < N) {
363 ptrdiff_t col = k[i].col() / B;
369 cur_col = std::min(cur_col, col);
375 scatter->col[ip] = ip;
376 scatter->val[ip] = math::identity<value_type_p>();
379 for (
int i = 0; i < B; ++i) {
382 scatter->ptr[ik + i + 1] = nnz;
387 for (
size_t i = N; i < n; ++i)
388 scatter->ptr[i + 1] = scatter->ptr[i];
390 ARCCORE_ALINA_TIC(
"pprecond");
391 P = std::make_shared<PPrecond>(context, App, prm.pprecond, bprm);
392 ARCCORE_ALINA_TOC(
"pprecond");
393 ARCCORE_ALINA_TIC(
"sprecond");
394 S = std::make_shared<SPrecond>(context, K, prm.sprecond, bprm);
395 ARCCORE_ALINA_TOC(
"sprecond");
397 Fpp = backend_type_p::copy_matrix(fpp, bprm);
398 Scatter = backend_type_p::copy_matrix(scatter, bprm);
400 rp = backend_type_p::create_vector(np, bprm);
401 xp = backend_type_p::create_vector(np, bprm);
402 rs = backend_type::create_vector(n, bprm);
405 void update_transfer(std::shared_ptr<build_matrix> K,
const backend_params bprm, std::true_type)
407 auto fpp = std::get<0>(first_scalar_pass(K,
false));
408 Fpp = backend_type_p::copy_matrix(fpp, bprm);
412 void init(
const AlinaContext& context, std::shared_ptr<build_matrix> K,
413 const backend_params bprm, std::false_type)
415 const int B = math::static_rows<value_type>::value;
416 const ptrdiff_t N = (prm.active_rows ? prm.active_rows : n);
420 auto fpp = std::make_shared<build_matrix_p>();
421 fpp->set_size(np, np * B);
422 fpp->set_nonzeros(np * B);
425 auto scatter = std::make_shared<build_matrix_p>();
426 scatter->set_size(np * B, np);
427 scatter->set_nonzeros(np);
430 auto App = std::make_shared<build_matrix_p>();
431 App->set_size(np, np,
true);
432 App->set_nonzeros(K->nbNonZero());
436 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
437 ptrdiff_t ik = i * B;
438 for (
int k = 0; k < B; ++k, ++ik) {
440 scatter->ptr[ik + 1] = i + 1;
443 fpp->ptr[i + 1] = ik;
445 scatter->val[i] = math::identity<value_type_p>();
447 ptrdiff_t row_beg = K->ptr[i];
448 ptrdiff_t row_end = K->ptr[i + 1];
449 App->ptr[i + 1] = row_end;
452 value_type_p* d = &fpp->val[i * B];
453 for (ptrdiff_t j = row_beg; j < row_end; ++j) {
454 if (K->col[j] == i) {
455 value_type v = math::adjoint(K->val[j]);
461 for (ptrdiff_t j = row_beg; j < row_end; ++j) {
462 value_type_p app = 0;
463 for (
int k = 0; k < B; ++k)
464 app += d[k] * K->val[j](k, 0);
466 App->col[j] = K->col[j];
472 ARCCORE_ALINA_TIC(
"pprecond");
473 P = std::make_shared<PPrecond>(context, App, prm.pprecond, bprm);
474 ARCCORE_ALINA_TOC(
"pprecond");
475 ARCCORE_ALINA_TIC(
"sprecond");
476 S = std::make_shared<SPrecond>(context, K, prm.sprecond, bprm);
477 ARCCORE_ALINA_TOC(
"sprecond");
479 Fpp = backend_type_p::copy_matrix(fpp, bprm);
480 Scatter = backend_type_p::copy_matrix(scatter, bprm);
482 rp = backend_type_p::create_vector(np, bprm);
483 xp = backend_type_p::create_vector(np, bprm);
484 rs = backend_type::create_vector(n, bprm);
487 void update_transfer(std::shared_ptr<build_matrix> K,
const backend_params bprm, std::false_type)
489 const int B = math::static_rows<value_type>::value;
490 const ptrdiff_t N = (prm.active_rows ? prm.active_rows : n);
494 auto fpp = std::make_shared<build_matrix_p>();
495 fpp->set_size(np, np * B);
496 fpp->set_nonzeros(np * B);
500 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
501 ptrdiff_t ik = i * B;
502 for (
int k = 0; k < B; ++k, ++ik) {
506 fpp->ptr[i + 1] = ik;
508 ptrdiff_t row_beg = K->ptr[i];
509 ptrdiff_t row_end = K->ptr[i + 1];
512 value_type_p* d = &fpp->val[i * B];
513 for (ptrdiff_t j = row_beg; j < row_end; ++j) {
514 if (K->col[j] == i) {
515 value_type v = math::adjoint(K->val[j]);
522 Fpp = backend_type_p::copy_matrix(fpp, bprm);
527 void invert(scalar_type* A, value_type_p* y)
529 const int B = math::static_rows<value_type>::value == 1 ? prm.block_size : math::static_rows<value_type>::value;
532 for (
int k = 0; k < B; ++k) {
533 scalar_type d = A[k * B + k];
534 assert(!math::is_zero(d));
535 for (
int i = k + 1; i < B; ++i) {
537 for (
int j = k + 1; j < B; ++j)
538 A[i * B + j] -= A[i * B + k] * A[k * B + j];
544 for (
int i = 0; i < B; ++i) {
545 value_type_p b =
static_cast<value_type_p
>(i == 0);
546 for (
int j = 0; j < i; ++j)
547 b -= A[i * B + j] * y[j];
552 for (
int i = B; i-- > 0;) {
553 for (
int j = i + 1; j < B; ++j)
554 y[i] -= A[i * B + j] * y[j];
555 y[i] /= A[i * B + i];
559 friend std::ostream& operator<<(std::ostream& os,
const CPRPreconditioner& p)
561 os <<
"CPR (two-stage preconditioner)\n"
562 "### Pressure preconditioner:\n"
564 "### Global preconditioner:\n"
565 << *p.S << std::endl;