Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
SchurOp.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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#include <alien/utils/Precomp.h>
10#include <alien/kernels/simple_csr/SimpleCSRMatrix.h>
11#include <alien/kernels/simple_csr/SimpleCSRVector.h>
12#include <alien/handlers/scalar/CSRModifierViewT.h>
13
14#include "SchurOp.h"
15#include "SchurBlock.h"
16
17/*---------------------------------------------------------------------------*/
18/*---------------------------------------------------------------------------*/
19
20namespace Alien
21{
22
23using namespace Arccore;
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
29: m_A(A)
30, m_B(B)
31{}
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
41{
42 MatrixImpl& csr_A = m_A.impl()->get<Alien::BackEnd::tag::simplecsr>(true);
43 VectorImpl& csr_B = m_B.impl()->get<Alien::BackEnd::tag::simplecsr>(true);
46
47 bool is_fixed_block_size = csr_A.block() != nullptr;
48 bool p_is_fixed_block_size = csr_pA.block() != nullptr;
49 if (is_fixed_block_size) {
50 if (p_is_fixed_block_size)
51 return _apply_schur(csr_A.block()->size(),
52 csr_A,
53 csr_B,
54 csr_pA.block()->size(),
55 csr_pA,
56 csr_pB);
57 else
58 return _apply_schur(csr_A.block()->size(),
59 csr_A,
60 csr_B,
61 csr_pA.vblock(),
62 csr_pA,
63 csr_pB);
64 }
65 else {
66 if (p_is_fixed_block_size)
67 return _apply_schur(csr_A.vblock(),
68 csr_A,
69 csr_B,
70 csr_pA.block()->size(),
71 csr_pA,
72 csr_pB);
73 else
74 return _apply_schur(csr_A.vblock(),
75 csr_A,
76 csr_B,
77 csr_pA.vblock(),
78 csr_pA,
79 csr_pB);
80 }
81}
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
86SchurOp::_apply_schur(Integer block_size,
87 MatrixImpl& A,
88 VectorImpl& B,
89 Integer p_block_size,
90 MatrixImpl& pA,
91 VectorImpl& pB) const
92{
93 pA.copyProfile(A);
94 pA.allocate();
95
96 bool is_parallel = A.isParallel();
97
98 // clang-format off
100 auto nrows = view.nrows() ;
101 auto kcol = view.kcol() ;
102 auto dcol = view.dcol() ;
103 auto cols = view.cols() ;
104 auto values = view.data() ;
105
106 CSRModifierViewT<MatrixImpl> modifier(pA);
107 auto p_nrows = modifier.nrows() ;
108 auto p_kcol = modifier.kcol() ;
109 auto p_dcol = modifier.dcol() ;
110 auto p_cols = modifier.cols() ;
111 auto p_values = modifier.data() ;
112 // clang-format on
113 if (is_parallel) {
114 }
115 else {
116 for (std::size_t irow = 0; irow < nrows; ++irow) {
117 auto diag_offset = dcol[irow];
118 }
119 }
120 return NoError;
121}
122
124SchurOp::_apply_schur(Integer block_size,
125 MatrixImpl& A,
126 VectorImpl& B,
127 VBlock const* p_vblock,
128 MatrixImpl& pA,
129 VectorImpl& pB) const
130{
131 return NoError;
132}
133
135SchurOp::_apply_schur(VBlock const* vblock,
136 MatrixImpl& A,
137 VectorImpl& B,
138 Integer p_block_size,
139 MatrixImpl& pA,
140 VectorImpl& pB) const
141{
142#ifdef ALIEN_USE_EIGEN3
143 pA.copyProfile(A);
144 pA.allocate();
145 auto p_block2d_size = p_block_size * p_block_size;
146
147 bool is_parallel = A.isParallel();
148 auto local_offset = A.getLocalOffset();
149 if (is_parallel) {
150 auto alloc_size = A.getAllocSize();
151 B.resize(alloc_size);
152 }
153
154 // clang-format off
155 CSRModifierViewT<MatrixImpl> view(A);
156 auto nrows = view.nrows() ;
157 auto kcol = view.kcol() ;
158 auto dcol = view.dcol() ;
159 auto cols = view.cols() ;
160 auto values = view.data() ;
161 auto bcols = A.getProfile().getBlockCols() ;
162 auto brows = A.getProfile().getBlockRowOffset() ;
163
164 CSRModifierViewT<MatrixImpl> modifier(pA);
165 auto p_nrows = modifier.nrows() ;
166 auto p_kcol = modifier.kcol() ;
167 auto p_dcol = modifier.dcol() ;
168 auto p_cols = modifier.cols() ;
169 auto p_values = modifier.data() ;
170 // clang-format on
171
172 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
173 auto diag_offset = dcol[irow];
174 auto irow_blk_size = vblock->size(local_offset + irow);
175 auto irow_offset = B.vblockImpl().offset(local_offset + irow);
176 if (irow_blk_size > p_block_size) {
177 Array2View<Real> diag(values + bcols[diag_offset], irow_blk_size, irow_blk_size);
178 SchurBlock2D diag2d(diag, p_block_size);
179 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
180 SchurBlock1D b1d(bv, p_block_size);
181 SchurAlgo::compute(diag2d, b1d);
182 }
183 }
184 if (is_parallel) {
185 auto& dist_struct_info = A.getDistStructInfo();
186 auto& local_row_size = dist_struct_info.m_local_row_size;
187 auto const& cols = dist_struct_info.m_cols;
188 auto const& block_sizes = dist_struct_info.m_block_sizes;
189 auto const& block_offsets = dist_struct_info.m_block_offsets;
190
191 SimpleCSRInternal::SendRecvOp<Real> op(B.data(),
192 dist_struct_info.m_send_info,
193 A.getSendPolicy(),
194 B.data(),
195 dist_struct_info.m_recv_info,
196 A.getRecvPolicy(),
197 A.getParallelMng(),
198 A.traceMng(),
199 block_sizes,
200 block_offsets);
201
202 op.start();
203
204 dist_struct_info.computeBlock2DSizesAndOffsets(kcol, dcol, bcols.data());
205 auto const& block2d_sizes = dist_struct_info.m_block2d_sizes;
206 auto const& block2d_offsets = dist_struct_info.m_block2d_offsets;
207 auto ghost_nrow = dist_struct_info.m_ghost_nrow;
208 auto ghost_diag_size = dist_struct_info.m_block2d_offsets[nrows + ghost_nrow] - dist_struct_info.m_block2d_offsets[nrows];
209 m_ghost_diag_values.resize(ghost_diag_size);
210 SimpleCSRInternal::SendRecvOp<Real> diag_op(values,
211 dist_struct_info.m_send_info,
212 A.getSendPolicy(),
213 m_ghost_diag_values.data(),
214 dist_struct_info.m_recv_info,
215 A.getRecvPolicy(),
216 A.getParallelMng(),
217 A.traceMng(),
218 block2d_sizes,
219 block2d_offsets,
220 true);
221
222 diag_op.start();
223 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
224 auto irow_blk_size = block_sizes[irow];
225 auto irow_offset = block_offsets[irow];
226 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
227 SchurBlock1D b1d(bv, p_block_size);
228 auto irow_diag_offset = dcol[irow];
229 for (int k = kcol[irow]; k < kcol[irow] + local_row_size[irow]; ++k) {
230
231 if (k == irow_diag_offset)
232 continue;
233
234 auto col = cols[k];
235 auto col_diag_offset = dcol[col];
236 auto col_blk_size = block_sizes[col];
237 auto col_offset = block_offsets[col];
238 if (col_blk_size > p_block_size) {
239 Array2View<Real> diag(values + bcols[col_diag_offset], col_blk_size, col_blk_size);
240 SchurBlock2D diag2d(diag, p_block_size);
241
242 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
243 SchurBlock1D diag_b1d(diag_bv, p_block_size);
244
245 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
246 SchurBlock2D off_diag2d(off_diag, p_block_size);
247
248 // A11_ki => A11_ki - A12_ki * A22^-1_ii A21_ii
249 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
250
251 // b1_k => b1_k - A12_k * A22^-1_i * b2_i
252 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
253 }
254 }
255 }
256 op.end();
257 diag_op.end();
258 Integer interface_nrow = dist_struct_info.m_interface_nrow;
259 ConstArrayView<Integer> row_ids = dist_struct_info.m_interface_rows;
260 for (Integer i = 0; i < interface_nrow; ++i) {
261 Integer irow = row_ids[i];
262 auto irow_blk_size = block_sizes[irow];
263 auto irow_offset = block_offsets[irow];
264 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
265 SchurBlock1D b1d(bv, p_block_size);
266 for (int k = kcol[irow] + local_row_size[irow]; k < kcol[irow + 1]; ++k) {
267
268 auto col = cols[k];
269 auto col_diag_offset = block2d_offsets[col] - block2d_offsets[nrows];
270 auto col_blk_size = block_sizes[col];
271 auto col_offset = block_offsets[col];
272
273 if (col_blk_size > p_block_size) {
274 Array2View<Real> diag(m_ghost_diag_values.data() + col_diag_offset, col_blk_size, col_blk_size);
275 SchurBlock2D diag2d(diag, p_block_size);
276
277 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
278 SchurBlock1D diag_b1d(diag_bv, p_block_size);
279
280 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
281 SchurBlock2D off_diag2d(off_diag, p_block_size);
282
283 // A11_ki => A11_ki - A12_ki * A22^-1_ii A21_ii
284 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
285
286 // b1_k => b1_k - A12_k * A22^-1_i * b2_i
287 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
288 }
289 }
290 }
291 }
292 else {
293 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
294 auto irow_blk_size = vblock->size(local_offset + irow);
295 auto irow_offset = B.vblockImpl().offset(local_offset + irow);
296 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
297 SchurBlock1D b1d(bv, p_block_size);
298 auto irow_diag_offset = dcol[irow];
299 for (int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
300
301 if (k == irow_diag_offset)
302 continue;
303
304 auto col = cols[k];
305 auto col_diag_offset = dcol[col - local_offset];
306 auto col_blk_size = vblock->size(col);
307 auto col_offset = B.vblockImpl().offset(col);
308 if (col_blk_size > p_block_size) {
309 Array2View<Real> diag(values + bcols[col_diag_offset], col_blk_size, col_blk_size);
310 SchurBlock2D diag2d(diag, p_block_size);
311
312 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
313 SchurBlock1D diag_b1d(diag_bv, p_block_size);
314
315 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
316 SchurBlock2D off_diag2d(off_diag, p_block_size);
317
318 // A11_ki => A11_ki - A12_ki * A22^-1_ii A21_ii
319 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
320
321 // b1_k => b1_k - A12_k * A22^-1_i * b2_i
322 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
323 }
324 }
325 }
326
327 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
328 auto irow_blk_size = vblock->size(local_offset + irow);
329 auto irow_offset = B.vblockImpl().offset(local_offset + irow);
330 ArrayView<Real> bv(irow_blk_size, (Real*)B.data() + irow_offset);
331 ArrayView<Real> p_bv(p_block_size, pB.data() + irow * p_block_size);
332 _copy(bv, p_bv);
333 for (int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
334
335 auto col = cols[k];
336 auto col_blk_size = vblock->size(col);
337
338 Array2View<Real> blk_values((Real*)values + bcols[k], irow_blk_size, col_blk_size);
339 Array2View<Real> pblk_values((Real*)p_values + k * p_block2d_size, p_block_size, p_block_size);
340 _copy(blk_values, pblk_values);
341 }
342 }
343 }
344#endif
345 return NoError;
346}
347
349SchurOp::_apply_schur(VBlock const* vblock,
350 MatrixImpl& A,
351 VectorImpl& B,
352 VBlock const* p_vblock,
353 MatrixImpl& pA,
354 VectorImpl& pB) const
355{
356#ifdef ALIEN_USE_EIGEN3
357 pA.copyProfile(A);
358 pA.allocate();
359 bool is_parallel = A.isParallel();
360 auto local_offset = A.getLocalOffset();
361 if (is_parallel) {
362 auto alloc_size = A.getAllocSize();
363 B.resize(alloc_size);
364 }
365
366 // clang-format off
367 CSRModifierViewT<MatrixImpl> view(A);
368 auto nrows = view.nrows() ;
369 auto kcol = view.kcol() ;
370 auto dcol = view.dcol() ;
371 auto cols = view.cols() ;
372 auto values = view.data() ;
373 auto bcols = A.getProfile().getBlockCols() ;
374 auto brows = A.getProfile().getBlockRowOffset() ;
375
376 CSRModifierViewT<MatrixImpl> modifier(pA);
377 auto p_nrows = modifier.nrows() ;
378 auto p_kcol = modifier.kcol() ;
379 auto p_dcol = modifier.dcol() ;
380 auto p_cols = modifier.cols() ;
381 auto p_values = modifier.data() ;
382 auto p_bcols = pA.getProfile().getBlockCols() ;
383 auto p_brows = pA.getProfile().getBlockRowOffset() ;
384 // clang-format on
385
386 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
387 auto diag_offset = dcol[irow];
388 auto irow_blk_size = vblock->size(local_offset + irow);
389 auto irow_p_blk_size = p_vblock->size(local_offset + irow);
390 auto irow_offset = B.vblockImpl().offset(local_offset + irow);
391 if (irow_blk_size > irow_p_blk_size) {
392 Array2View<Real> diag(values + bcols[diag_offset], irow_blk_size, irow_blk_size);
393 SchurBlock2D diag2d(diag, irow_p_blk_size);
394 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
395 SchurBlock1D b1d(bv, irow_p_blk_size);
396 SchurAlgo::compute(diag2d, b1d);
397 }
398 }
399
400 if (is_parallel) {
401 auto& dist_struct_info = A.getDistStructInfo();
402 auto& local_row_size = dist_struct_info.m_local_row_size;
403 auto const& cols = dist_struct_info.m_cols;
404 auto const& block_sizes = dist_struct_info.m_block_sizes;
405 auto const& block_offsets = dist_struct_info.m_block_offsets;
406
407 auto& p_dist_struct_info = pA.getDistStructInfo();
408 auto const& p_block_sizes = dist_struct_info.m_block_sizes;
409 auto const& p_block_offsets = dist_struct_info.m_block_offsets;
410
411 SimpleCSRInternal::SendRecvOp<Real> op(B.data(),
412 dist_struct_info.m_send_info,
413 A.getSendPolicy(),
414 B.data(),
415 dist_struct_info.m_recv_info,
416 A.getRecvPolicy(),
417 A.getParallelMng(),
418 A.traceMng(),
419 block_sizes,
420 block_offsets);
421
422 op.start();
423
424 dist_struct_info.computeBlock2DSizesAndOffsets(kcol, dcol, bcols.data());
425 auto const& block2d_sizes = dist_struct_info.m_block2d_sizes;
426 auto const& block2d_offsets = dist_struct_info.m_block2d_offsets;
427 auto ghost_nrow = dist_struct_info.m_ghost_nrow;
428 auto ghost_diag_size = dist_struct_info.m_block2d_offsets[nrows + ghost_nrow] - dist_struct_info.m_block2d_offsets[nrows];
429 m_ghost_diag_values.resize(ghost_diag_size);
430 SimpleCSRInternal::SendRecvOp<Real> diag_op(values,
431 dist_struct_info.m_send_info,
432 A.getSendPolicy(),
433 m_ghost_diag_values.data(),
434 dist_struct_info.m_recv_info,
435 A.getRecvPolicy(),
436 A.getParallelMng(),
437 A.traceMng(),
438 block2d_sizes,
439 block2d_offsets,
440 true);
441
442 diag_op.start();
443
444 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
445 auto irow_blk_size = block_sizes[irow];
446 auto irow_offset = block_offsets[irow];
447 auto irow_p_blk_size = p_vblock->size(local_offset + irow);
448 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
449 SchurBlock1D b1d(bv, irow_p_blk_size);
450 auto irow_diag_offset = dcol[irow];
451 for (int k = kcol[irow]; k < kcol[irow] + local_row_size[irow]; ++k) {
452
453 if (k == irow_diag_offset)
454 continue;
455
456 auto col = cols[k];
457 auto col_diag_offset = dcol[col];
458 auto col_blk_size = block_sizes[col];
459 auto col_offset = block_offsets[col];
460 auto col_p_blk_size = p_vblock->size(local_offset + col);
461 if (col_blk_size > col_p_blk_size) {
462 Array2View<Real> diag(values + bcols[col_diag_offset], col_blk_size, col_blk_size);
463 SchurBlock2D diag2d(diag, col_p_blk_size);
464
465 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
466 SchurBlock1D diag_b1d(diag_bv, col_p_blk_size);
467
468 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
469 SchurBlock2D off_diag2d(off_diag, irow_p_blk_size);
470
471 // A11_ki => A11_ki - A12_ki * A22^-1_ii A21_ii
472 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
473
474 // b1_k => b1_k - A12_k * A22^-1_i * b2_i
475 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
476 }
477 }
478 }
479
480 op.end();
481 diag_op.end();
482
483 Integer interface_nrow = dist_struct_info.m_interface_nrow;
484 ConstArrayView<Integer> row_ids = dist_struct_info.m_interface_rows;
485 for (Integer i = 0; i < interface_nrow; ++i) {
486 Integer irow = row_ids[i];
487 auto irow_blk_size = block_sizes[irow];
488 auto irow_offset = block_offsets[irow];
489 auto irow_p_blk_size = p_vblock->size(local_offset + irow);
490 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
491 SchurBlock1D b1d(bv, irow_p_blk_size);
492
493 for (int k = kcol[irow] + local_row_size[irow]; k < kcol[irow + 1]; ++k) {
494
495 auto col = cols[k];
496 auto col_diag_offset = block2d_offsets[col] - block2d_offsets[nrows];
497 auto col_blk_size = block_sizes[col];
498 auto col_offset = block_offsets[col];
499 auto col_p_blk_size = p_block_sizes[col];
500
501 if (col_blk_size > col_p_blk_size) {
502 Array2View<Real> diag(m_ghost_diag_values.data() + col_diag_offset, col_blk_size, col_blk_size);
503 SchurBlock2D diag2d(diag, col_p_blk_size);
504
505 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
506 SchurBlock1D diag_b1d(diag_bv, col_p_blk_size);
507
508 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
509 SchurBlock2D off_diag2d(off_diag, col_p_blk_size);
510
511 // A11_ki => A11_ki - A12_ki * A22^-1_ii A21_ii
512 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
513
514 // b1_k => b1_k - A12_k * A22^-1_i * b2_i
515 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
516 }
517 }
518 }
519 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
520 auto irow_blk_size = vblock->size(local_offset + irow);
521 auto irow_offset = B.vblockImpl().offset(local_offset + irow);
522 auto irow_p_blk_size = p_vblock->size(local_offset + irow);
523 auto irow_p_offset = pB.vblockImpl().offset(local_offset + irow);
524 ArrayView<Real> bv(irow_blk_size, (Real*)B.data() + irow_offset);
525 ArrayView<Real> p_bv(irow_p_blk_size, pB.data() + irow_p_offset);
526 _copy(bv, p_bv);
527
528 for (int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
529
530 auto col = cols[k];
531 auto col_blk_size = block_sizes[col];
532 auto col_p_blk_size = p_block_sizes[col];
533
534 Array2View<Real> blk_values(values + bcols[k], irow_blk_size, col_blk_size);
535 Array2View<Real> pblk_values(p_values + p_bcols[k], irow_p_blk_size, col_p_blk_size);
536 _copy(blk_values, pblk_values);
537 }
538 }
539 }
540 else {
541 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
542 auto irow_blk_size = vblock->size(local_offset + irow);
543 auto irow_offset = B.vblockImpl().offset(local_offset + irow);
544 auto irow_p_blk_size = p_vblock->size(local_offset + irow);
545 ArrayView<Real> bv(irow_blk_size, B.data() + irow_offset);
546 SchurBlock1D b1d(bv, irow_p_blk_size);
547 auto irow_diag_offset = dcol[irow];
548 for (int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
549
550 if (k == irow_diag_offset)
551 continue;
552
553 auto col = cols[k];
554 auto col_diag_offset = dcol[col - local_offset];
555 auto col_blk_size = vblock->size(col);
556 auto col_offset = B.vblockImpl().offset(col);
557 auto col_p_blk_size = p_vblock->size(local_offset + col);
558 if (col_blk_size > col_p_blk_size) {
559 Array2View<Real> diag(values + bcols[col_diag_offset], col_blk_size, col_blk_size);
560 SchurBlock2D diag2d(diag, col_p_blk_size);
561
562 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
563 SchurBlock1D diag_b1d(diag_bv, col_p_blk_size);
564
565 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
566 SchurBlock2D off_diag2d(off_diag, col_p_blk_size);
567
568 // A11_ki => A11_ki - A12_ki * A22^-1_ii A21_ii
569 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
570
571 // b1_k => b1_k - A12_k * A22^-1_i * b2_i
572 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
573 }
574 }
575 }
576 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
577 auto irow_blk_size = vblock->size(local_offset + irow);
578 auto irow_offset = B.vblockImpl().offset(local_offset + irow);
579 auto irow_p_blk_size = p_vblock->size(local_offset + irow);
580 auto irow_p_offset = pB.vblockImpl().offset(local_offset + irow);
581 ArrayView<Real> bv(irow_blk_size, (Real*)B.data() + irow_offset);
582 ArrayView<Real> p_bv(irow_p_blk_size, pB.data() + irow_p_offset);
583 _copy(bv, p_bv);
584
585 for (int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
586
587 auto col = cols[k];
588 auto col_blk_size = vblock->size(col);
589 auto col_p_blk_size = p_vblock->size(col);
590
591 Array2View<Real> blk_values((Real*)values + bcols[k], irow_blk_size, col_blk_size);
592 Array2View<Real> pblk_values((Real*)p_values + p_bcols[k], irow_p_blk_size, col_p_blk_size);
593 _copy(blk_values, pblk_values);
594 }
595 }
596 }
597#endif
598 return NoError;
599}
600
602SchurOp::computeSolutionFromPrimaryUnknowns(IVector const& pX, IVector& X) const
603{
604 MatrixImpl const& csr_A = m_A.impl()->get<Alien::BackEnd::tag::simplecsr>();
605
606 VectorImpl const& csr_b = m_B.impl()->get<Alien::BackEnd::tag::simplecsr>();
607 VectorImpl const& csr_px = pX.impl()->get<Alien::BackEnd::tag::simplecsr>();
608 VectorImpl& csr_x = X.impl()->get<Alien::BackEnd::tag::simplecsr>(true);
609 if (csr_A.block()) {
610 return NoError;
611 }
612 else {
613 if (csr_px.block())
614 return _compute_solution(csr_A.vblock(), csr_A, csr_b, csr_px.block()->size(), csr_px, csr_x);
615 else
616 return _compute_solution(csr_A.vblock(), csr_A, csr_b, csr_px.vblock(), csr_px, csr_x);
617 }
618}
619
621SchurOp::_compute_solution(VBlock const* vblock,
622 MatrixImpl const& A,
623 VectorImpl const& B,
624 Integer p_block_size,
625 VectorImpl const& pX,
626 VectorImpl& X) const
627{
628
629#ifdef ALIEN_USE_EIGEN3
630 auto local_offset = A.getLocalOffset();
631
632 // clang-format off
633 CSRConstViewT<MatrixImpl> view(A);
634 auto nrows = view.nrows() ;
635 auto kcol = view.kcol() ;
636 auto dcol = view.dcol() ;
637 auto cols = view.cols() ;
638 auto values = view.data() ;
639 auto bcols = A.getProfile().getBlockCols() ;
640 // clang-format on
641
642 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
643 auto diag_offset = dcol[irow];
644 auto irow_blk_size = vblock->size(local_offset + irow);
645 auto irow_offset = X.vblockImpl().offset(local_offset + irow);
646 Array2View<Real>
647 diag((Real*)values + bcols[diag_offset], irow_blk_size, irow_blk_size);
648 SchurBlock2D diag2d(diag, p_block_size);
649 ConstArrayView<Real> bb(irow_blk_size, B.data() + irow_offset);
650 ArrayView<Real> bx(irow_blk_size, X.data() + irow_offset);
651 bx.copy(bb);
652 SchurBlock1D x1d(bx, p_block_size);
653 ArrayView<Real> p_bx(irow_blk_size, (Real*)pX.data() + p_block_size * irow);
654 for (int i = 0; i < p_block_size; ++i)
655 bx[i] = p_bx[i];
656 if (irow_blk_size > p_block_size) {
657
658 // x2 = A22^-1 * b2 - A22^-1 * A21 * x1
659 x1d.block_2() = x1d.block_2() - diag2d.block_21() * x1d.block_1();
660 }
661 }
662#endif
663 return NoError;
664}
665
667SchurOp::_compute_solution(VBlock const* vblock,
668 MatrixImpl const& A,
669 VectorImpl const& B,
670 VBlock const* p_vblock,
671 VectorImpl const& pX,
672 VectorImpl& X) const
673{
674#ifdef ALIEN_USE_EIGEN3
675 auto local_offset = A.getLocalOffset();
676
677 // clang-format off
678 CSRConstViewT<MatrixImpl> view(A);
679 auto nrows = view.nrows() ;
680 auto kcol = view.kcol() ;
681 auto dcol = view.dcol() ;
682 auto cols = view.cols() ;
683 auto values = view.data() ;
684 auto bcols = A.getProfile().getBlockCols() ;
685 // clang-format on
686
687 for (int irow = 0; (std::size_t) irow < nrows; ++irow) {
688 auto diag_offset = dcol[irow];
689 auto irow_blk_size = vblock->size(local_offset + irow);
690 auto irow_offset = X.vblockImpl().offset(local_offset + irow);
691 auto irow_p_blk_size = p_vblock->size(local_offset + irow);
692 auto irow_p_offset = pX.vblockImpl().offset(local_offset + irow);
693 Array2View<Real> diag((Real*)values + bcols[diag_offset], irow_blk_size, irow_blk_size);
694 SchurBlock2D diag2d(diag, irow_p_blk_size);
695 ConstArrayView<Real> bb(irow_blk_size, B.data() + irow_offset);
696 ArrayView<Real> bx(irow_blk_size, X.data() + irow_offset);
697 bx.copy(bb);
698 SchurBlock1D x1d(bx, irow_p_blk_size);
699 ArrayView<Real> p_bx(irow_blk_size, (Real*)pX.data() + irow_p_offset);
700 for (int i = 0; i < irow_p_blk_size; ++i)
701 bx[i] = p_bx[i];
702 if (irow_blk_size > irow_p_blk_size) {
703
704 // x2 = A22^-1 * b2 - A22^-1 * A21 * x1
705 x1d.block_2() = x1d.block_2() - diag2d.block_21() * x1d.block_1();
706 }
707 }
708#endif
709 return NoError;
710}
711/*---------------------------------------------------------------------------*/
712/*---------------------------------------------------------------------------*/
713
714} // namespace Alien
715
716/*---------------------------------------------------------------------------*/
717/*---------------------------------------------------------------------------*/
MultiVectorImpl.h.
Arccore::Integer size() const
Get square block size.
Definition Block.cc:90
virtual const VBlock * vblock() const
Get block datas of the matrix.
virtual const Block * block() const
Get block datas of the matrix.
Interface for all matrices.
Definition IMatrix.h:51
virtual MultiMatrixImpl * impl()=0
Get the multimatrix implementation.
Interface for all vectors.
Definition IVector.h:51
virtual MultiVectorImpl * impl()=0
Get the multivector implementation.
const AlgebraTraits< tag >::matrix_type & get() const
Get a specific matrix implementation.
const AlgebraTraits< tag >::vector_type & get() const
Get a specific vector implementation.
SchurOp(IMatrix &A, IVector &b)
Constructor.
Definition SchurOp.cc:28
SimpleCSRMatrix< Arccore::Real > MatrixImpl
Type of the matrix implementation.
Definition SchurOp.h:41
eErrorType
Type of algorithm.
Definition SchurOp.h:35
eErrorType computePrimarySystem(IMatrix &pA, IVector &pb) const
Shur the linear system.
Definition SchurOp.cc:40
SimpleCSRVector< Arccore::Real > VectorImpl
Type of the vector implementation.
Definition SchurOp.h:43
Variable size block elements for block matrices.
Definition VBlock.h:46
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Definition BackEnd.h:17