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>
15#include "SchurBlock.h"
23using namespace Arccore;
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(),
58 return _apply_schur(csr_A.
block()->
size(),
66 if (p_is_fixed_block_size)
67 return _apply_schur(csr_A.
vblock(),
74 return _apply_schur(csr_A.
vblock(),
86SchurOp::_apply_schur(Integer block_size,
96 bool is_parallel = A.isParallel();
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() ;
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() ;
116 for (std::size_t irow = 0; irow < nrows; ++irow) {
117 auto diag_offset = dcol[irow];
124SchurOp::_apply_schur(Integer block_size,
129 VectorImpl& pB)
const
135SchurOp::_apply_schur(
VBlock const* vblock,
138 Integer p_block_size,
140 VectorImpl& pB)
const
142#ifdef ALIEN_USE_EIGEN3
145 auto p_block2d_size = p_block_size * p_block_size;
147 bool is_parallel = A.isParallel();
148 auto local_offset = A.getLocalOffset();
150 auto alloc_size = A.getAllocSize();
151 B.resize(alloc_size);
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() ;
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() ;
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);
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;
191 SimpleCSRInternal::SendRecvOp<Real> op(B.data(),
192 dist_struct_info.m_send_info,
195 dist_struct_info.m_recv_info,
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,
213 m_ghost_diag_values.data(),
214 dist_struct_info.m_recv_info,
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) {
231 if (k == irow_diag_offset)
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);
242 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
243 SchurBlock1D diag_b1d(diag_bv, p_block_size);
245 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
246 SchurBlock2D off_diag2d(off_diag, p_block_size);
249 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
252 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
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) {
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];
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);
277 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
278 SchurBlock1D diag_b1d(diag_bv, p_block_size);
280 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
281 SchurBlock2D off_diag2d(off_diag, p_block_size);
284 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
287 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
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) {
301 if (k == irow_diag_offset)
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);
312 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
313 SchurBlock1D diag_b1d(diag_bv, p_block_size);
315 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
316 SchurBlock2D off_diag2d(off_diag, p_block_size);
319 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
322 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
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);
333 for (
int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
336 auto col_blk_size = vblock->size(col);
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);
349SchurOp::_apply_schur(
VBlock const* vblock,
354 VectorImpl& pB)
const
356#ifdef ALIEN_USE_EIGEN3
359 bool is_parallel = A.isParallel();
360 auto local_offset = A.getLocalOffset();
362 auto alloc_size = A.getAllocSize();
363 B.resize(alloc_size);
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() ;
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() ;
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);
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;
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;
411 SimpleCSRInternal::SendRecvOp<Real> op(B.data(),
412 dist_struct_info.m_send_info,
415 dist_struct_info.m_recv_info,
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,
433 m_ghost_diag_values.data(),
434 dist_struct_info.m_recv_info,
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) {
453 if (k == irow_diag_offset)
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);
465 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
466 SchurBlock1D diag_b1d(diag_bv, col_p_blk_size);
468 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
469 SchurBlock2D off_diag2d(off_diag, irow_p_blk_size);
472 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
475 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
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);
493 for (
int k = kcol[irow] + local_row_size[irow]; k < kcol[irow + 1]; ++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];
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);
505 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
506 SchurBlock1D diag_b1d(diag_bv, col_p_blk_size);
508 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
509 SchurBlock2D off_diag2d(off_diag, col_p_blk_size);
512 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
515 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
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);
528 for (
int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
531 auto col_blk_size = block_sizes[col];
532 auto col_p_blk_size = p_block_sizes[col];
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);
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) {
550 if (k == irow_diag_offset)
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);
562 ArrayView<Real> diag_bv(col_blk_size, (Real*)B.data() + col_offset);
563 SchurBlock1D diag_b1d(diag_bv, col_p_blk_size);
565 Array2View<Real> off_diag(values + bcols[k], irow_blk_size, col_blk_size);
566 SchurBlock2D off_diag2d(off_diag, col_p_blk_size);
569 off_diag2d.block_11() -= off_diag2d.block_12() * diag2d.block_21();
572 b1d.block_1() -= off_diag2d.block_12() * diag_b1d.block_2();
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);
585 for (
int k = kcol[irow]; k < kcol[irow + 1]; ++k) {
588 auto col_blk_size = vblock->size(col);
589 auto col_p_blk_size = p_vblock->size(col);
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);
602SchurOp::computeSolutionFromPrimaryUnknowns(
IVector const& pX,
IVector& X)
const
604 MatrixImpl const& csr_A = m_A.impl()->get<Alien::BackEnd::tag::simplecsr>();
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);
614 return _compute_solution(csr_A.vblock(), csr_A, csr_b, csr_px.block()->size(), csr_px, csr_x);
616 return _compute_solution(csr_A.vblock(), csr_A, csr_b, csr_px.vblock(), csr_px, csr_x);
621SchurOp::_compute_solution(
VBlock const* vblock,
624 Integer p_block_size,
625 VectorImpl
const& pX,
629#ifdef ALIEN_USE_EIGEN3
630 auto local_offset = A.getLocalOffset();
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() ;
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);
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);
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)
656 if (irow_blk_size > p_block_size) {
659 x1d.block_2() = x1d.block_2() - diag2d.block_21() * x1d.block_1();
667SchurOp::_compute_solution(
VBlock const* vblock,
671 VectorImpl
const& pX,
674#ifdef ALIEN_USE_EIGEN3
675 auto local_offset = A.getLocalOffset();
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() ;
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);
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)
702 if (irow_blk_size > irow_p_blk_size) {
705 x1d.block_2() = x1d.block_2() - diag2d.block_21() * x1d.block_1();
Arccore::Integer size() const
Get square block size.
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.
virtual MultiMatrixImpl * impl()=0
Get the multimatrix implementation.
Interface for all vectors.
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.
SimpleCSRMatrix< Arccore::Real > MatrixImpl
Type of the matrix implementation.
eErrorType
Type of algorithm.
eErrorType computePrimarySystem(IMatrix &pA, IVector &pb) const
Shur the linear system.
SimpleCSRVector< Arccore::Real > VectorImpl
Type of the vector implementation.
Variable size block elements for block matrices.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --