9#include <kernel/solver/base.hpp>
10#include <kernel/adjacency/graph.hpp>
11#include <kernel/lafem/dense_vector.hpp>
12#include <kernel/lafem/dense_vector_blocked.hpp>
13#include <kernel/lafem/power_vector.hpp>
14#include <kernel/lafem/tuple_vector.hpp>
15#include <kernel/lafem/sparse_matrix_csr.hpp>
16#include <kernel/lafem/sparse_matrix_bcsr.hpp>
17#include <kernel/lafem/power_diag_matrix.hpp>
18#include <kernel/lafem/power_full_matrix.hpp>
19#include <kernel/lafem/power_row_matrix.hpp>
20#include <kernel/lafem/power_col_matrix.hpp>
21#include <kernel/lafem/power_full_matrix.hpp>
22#include <kernel/lafem/saddle_point_matrix.hpp>
23#include <kernel/util/stop_watch.hpp>
50 template<
typename Vector_>
69 template<
typename Matrix_>
72 template<
typename DT_,
typename IT_>
73 class VankaVector<LAFEM::DenseVector<DT_, IT_>>
76 typedef LAFEM::DenseVector<DT_, IT_> VectorType;
77 static constexpr int dim = 1;
83 explicit VankaVector(VectorType& vec_cor) :
84 _vec_cor(vec_cor.elements())
88 IT_ gather_def(DT_* x,
const VectorType& vec,
const IT_* idx,
const IT_ n,
const IT_ off)
const
90 const DT_* vdef = vec.elements();
92 for(IT_ i(0); i < n; ++i)
94 x[off+i] = vdef[idx[i]];
99 IT_ scatter_cor(
const DT_ omega,
const DT_* x,
const IT_* idx,
const IT_ n,
const IT_ off)
101 for(IT_ i(0); i < n; ++i)
103 _vec_cor[idx[i]] += omega * x[off+i];
109 template<
typename DT_,
typename IT_,
int dim_>
110 class VankaVector<LAFEM::DenseVectorBlocked<DT_, IT_, dim_>>
113 typedef LAFEM::DenseVectorBlocked<DT_, IT_, dim_> VectorType;
114 typedef typename VectorType::ValueType ValueType;
115 static constexpr int dim = dim_;
121 explicit VankaVector(VectorType& vec_cor) :
122 _vec_cor(vec_cor.elements())
126 IT_ gather_def(DT_* x,
const VectorType& vec,
const IT_* idx,
const IT_ n,
const IT_ off)
const
128 const ValueType* vdef = vec.elements();
130 for(IT_ i(0); i < n; ++i)
132 const ValueType& vi = vdef[idx[i]];
133 for(
int j(0); j < dim; ++j)
135 x[off + i*IT_(dim) + IT_(j)] = vi[j];
138 return off + IT_(dim)*n;
141 IT_ scatter_cor(
const DT_ omega,
const DT_* x,
const IT_* idx,
const IT_ n,
const IT_ off)
143 for(IT_ i(0); i < n; ++i)
145 ValueType& vi = _vec_cor[idx[i]];
146 for(
int j(0); j < dim; ++j)
148 vi[j] += omega * x[off + i*IT_(dim) + IT_(j)];
151 return off + IT_(dim)*n;
155 template<
typename SubVector_,
int dim_>
156 class VankaVector<LAFEM::PowerVector<SubVector_, dim_>>
159 typedef LAFEM::PowerVector<SubVector_, dim_> VectorType;
160 typedef VankaVector<SubVector_> FirstClass;
161 typedef VankaVector<LAFEM::PowerVector<SubVector_, dim_-1>> RestClass;
163 static constexpr int dim = FirstClass::dim + RestClass::dim;
170 explicit VankaVector(VectorType& vec_cor) :
171 _first(vec_cor.first()),
172 _rest(vec_cor.
rest())
176 template<
typename DT_,
typename IT_>
177 IT_ gather_def(DT_* x,
const VectorType& vec,
const IT_* idx,
const IT_ n,
const IT_ off)
const
179 IT_ noff = _first.gather_def(x, vec.first(), idx, n, off);
180 return _rest.gather_def(x, vec.rest(), idx, n, noff);
183 template<
typename DT_,
typename IT_>
184 IT_ scatter_cor(
const DT_ omega,
const DT_* x,
const IT_* idx,
const IT_ n,
const IT_ off)
186 IT_ noff = _first.scatter_cor(omega, x, idx, n, off);
187 return _rest.scatter_cor(omega, x, idx, n, noff);
191 template<
typename SubVector_>
192 class VankaVector<LAFEM::PowerVector<SubVector_, 1>>
195 typedef LAFEM::PowerVector<SubVector_, 1> VectorType;
196 typedef VankaVector<SubVector_> FirstClass;
198 static constexpr int dim = FirstClass::dim;
204 explicit VankaVector(VectorType& vec_cor) :
205 _first(vec_cor.first())
209 template<
typename DT_,
typename IT_>
210 IT_ gather_def(DT_* x,
const VectorType& vec,
const IT_* idx,
const IT_ n,
const IT_ off)
const
212 return _first.gather_def(x, vec.first(), idx, n, off);
215 template<
typename DT_,
typename IT_>
216 IT_ scatter_cor(
const DT_ omega,
const DT_* x,
const IT_* idx,
const IT_ n,
const IT_ off)
218 return _first.scatter_cor(omega, x, idx, n, off);
222 template<
typename DT_,
typename IT_>
223 class VankaMatrix<LAFEM::SparseMatrixCSR<DT_, IT_>>
226 typedef LAFEM::SparseMatrixCSR<DT_, IT_> MatrixType;
227 typedef LAFEM::DenseVector<DT_, IT_> VectorTypeR;
229 static constexpr int row_dim = 1;
230 static constexpr int col_dim = 1;
238 explicit VankaMatrix(
const MatrixType& matrix) :
239 _row_ptr(matrix.row_ptr()),
240 _col_idx(matrix.col_ind()),
241 _mat_val(matrix.val())
245 std::pair<IT_, IT_> gather_full(
246 DT_* data,
const IT_* ridx,
const IT_* cidx,
247 const IT_ m,
const IT_ n,
const IT_ stride,
248 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
251 if(_mat_val ==
nullptr)
252 return std::make_pair(mo+m, no+n);
255 for(IT_ i(0); i < m; ++i)
258 const IT_ ri = ridx[i];
264 for(IT_ ai = _row_ptr[ri]; ai < _row_ptr[ri+1]; ++ai)
267 const IT_ rj = _col_idx[ai];
270 while((j < n) && (cidx[j] < rj))
275 if((j < n) && (cidx[j] == rj))
278 data[(mo + i) * stride + no + j] = _mat_val[ai];
282 return std::make_pair(mo+m, no+n);
285 IT_ gather_diag(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
288 for(IT_ i(0); i < m; ++i)
291 const IT_ ri = idx[i];
294 for(IT_ ai = _row_ptr[ri]; ai < _row_ptr[ri+1]; ++ai)
297 if(_col_idx[ai] == ri)
299 data[mo+i] = _mat_val[ai];
307 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
309 if(_mat_val ==
nullptr)
312 const DT_* v = vec_cor.elements();
315 for(IT_ i(0); i < m; ++i)
317 const IT_ vi = idx[i];
321 for(IT_ k = _row_ptr[vi]; k < _row_ptr[vi+1]; ++k)
323 r += _mat_val[k] * v[_col_idx[k]];
325 x[off+i] += alpha * r;
335 template<
typename DT_,
typename IT_,
int row_dim_,
int col_dim_>
336 class VankaMatrix<LAFEM::SparseMatrixBCSR<DT_, IT_, row_dim_, col_dim_>>
339 typedef LAFEM::SparseMatrixBCSR<DT_, IT_, row_dim_, col_dim_> MatrixType;
341 typedef typename MatrixType::ValueType MatVal;
343 static constexpr int row_dim = row_dim_;
344 static constexpr int col_dim = col_dim_;
349 const MatVal* _mat_val;
352 explicit VankaMatrix(
const MatrixType& matrix) :
353 _row_ptr(matrix.row_ptr()),
354 _col_idx(matrix.col_ind()),
355 _mat_val(matrix.val())
359 std::pair<IT_, IT_> gather_full(
360 DT_* data,
const IT_* ridx,
const IT_* cidx,
361 const IT_ m,
const IT_ n,
const IT_ stride,
362 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
365 XASSERTM(_mat_val !=
nullptr,
"Vanka: invalid empty BCSR matrix");
368 for(IT_ i(0); i < m; ++i)
371 const IT_ ri = ridx[i];
377 for(IT_ ai = _row_ptr[ri]; ai < _row_ptr[ri+1]; ++ai)
380 const IT_ rj = _col_idx[ai];
383 while((j < n) && (cidx[j] < rj))
388 if((j < n) && (cidx[j] == rj))
391 const MatVal& mv = _mat_val[ai];
394 for(
int ii(0); ii < row_dim; ++ii)
397 const IT_ lro = (mo + i * IT_(row_dim) + IT_(ii)) * stride + no + j * IT_(col_dim);
400 for(
int jj(0); jj < col_dim; ++jj)
402 data[lro + IT_(jj)] = mv[ii][jj];
408 return std::make_pair(mo + IT_(row_dim)*m, no + IT_(col_dim)*n);
411 IT_ gather_diag(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
414 for(IT_ i(0); i < m; ++i)
417 const IT_ ri = idx[i];
420 for(IT_ ai = _row_ptr[ri]; ai < _row_ptr[ri+1]; ++ai)
423 if(_col_idx[ai] == ri)
425 const MatVal& mv = _mat_val[ai];
428 for(
int k(0); k < row_dim; ++k)
430 data[mo + i*IT_(row_dim) + IT_(k)] = mv[k][k];
439 IT_ mult_cor(DT_* x,
const DT_ alpha,
const LAFEM::DenseVectorBlocked<DT_, IT_, col_dim_>& vec_cor,
440 const IT_* idx,
const IT_ m,
const IT_ off)
const
442 if(_mat_val ==
nullptr)
445 typedef LAFEM::DenseVectorBlocked<DT_, IT_, col_dim_> VectorType;
446 typedef typename VectorType::ValueType VecVal;
447 const VecVal* v = vec_cor.elements();
450 for(IT_ i(0); i < m; ++i)
452 const IT_ vi = idx[i];
455 for(IT_ k = _row_ptr[vi]; k < _row_ptr[vi+1]; ++k)
458 const MatVal& mv = _mat_val[k];
459 const VecVal& vv = v[_col_idx[k]];
462 for(
int ii(0); ii < row_dim; ++ii)
466 for(
int jj(0); jj < col_dim; ++jj)
468 r += mv[ii][jj] * vv[jj];
470 x[off + i*IT_(row_dim) + IT_(ii)] += alpha * r;
474 return off + m* IT_(row_dim);
477 IT_ mult_cor(DT_* x,
const DT_ alpha,
const LAFEM::DenseVector<DT_, IT_>& vec_cor,
478 const IT_* idx,
const IT_ m,
const IT_ off)
const
480 if(_mat_val ==
nullptr)
483 const DT_* v = vec_cor.elements();
486 for(IT_ i(0); i < m; ++i)
488 const IT_ vi = idx[i];
491 for(IT_ k = _row_ptr[vi]; k < _row_ptr[vi+1]; ++k)
494 const MatVal& mv = _mat_val[k];
498 const IT_ vo = _col_idx[k] * IT_(col_dim);
501 for(
int ii(0); ii < row_dim; ++ii)
505 for(
int jj(0); jj < col_dim; ++jj)
507 r += mv[ii][jj] * v[vo + IT_(jj)];
509 x[off + i*IT_(row_dim) + IT_(ii)] += alpha * r;
513 return off + m* IT_(row_dim);
521 template<
typename SubMatrix_,
int dim_>
522 class VankaMatrix<LAFEM::PowerDiagMatrix<SubMatrix_, dim_>>
525 typedef LAFEM::PowerDiagMatrix<SubMatrix_, dim_> MatrixType;
526 typedef typename MatrixType::VectorTypeR VectorTypeR;
527 typedef VankaMatrix<SubMatrix_> FirstClass;
528 typedef VankaMatrix<LAFEM::PowerDiagMatrix<SubMatrix_, dim_-1>> RestClass;
530 static constexpr int row_dim = FirstClass::row_dim + RestClass::row_dim;
531 static constexpr int col_dim = FirstClass::col_dim + RestClass::col_dim;
538 explicit VankaMatrix(
const MatrixType& matrix) :
539 _first(matrix.first()),
544 template<
typename DT_,
typename IT_>
545 std::pair<IT_, IT_> gather_full(
546 DT_* data,
const IT_* ridx,
const IT_* cidx,
547 const IT_ m,
const IT_ n,
const IT_ stride,
548 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
550 std::pair<IT_, IT_> mn = _first.gather_full(data, ridx, cidx, m, n, stride, mo, no);
551 return _rest.gather_full(data, ridx, cidx, m, n, stride, mn.first, mn.second);
554 template<
typename DT_,
typename IT_>
555 IT_ gather_diag(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
557 IT_ mno = _first.gather_diag(data, idx, m, mo);
558 return _rest.gather_diag(data, idx, m, mno);
561 template<
typename DT_,
typename IT_>
562 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
564 IT_ noff = _first.mult_cor(x, alpha, vec_cor.first(), idx, m, off);
565 return _rest.mult_cor(x, alpha, vec_cor.rest(), idx, m, noff);
569 template<
typename SubMatrix_>
570 class VankaMatrix<LAFEM::PowerDiagMatrix<SubMatrix_, 1>>
573 typedef LAFEM::PowerDiagMatrix<SubMatrix_, 1> MatrixType;
574 typedef typename MatrixType::VectorTypeR VectorTypeR;
575 typedef VankaMatrix<SubMatrix_> FirstClass;
577 static constexpr int row_dim = FirstClass::row_dim;
578 static constexpr int col_dim = FirstClass::col_dim;
584 explicit VankaMatrix(
const MatrixType& matrix) :
585 _first(matrix.first())
589 template<
typename DT_,
typename IT_>
590 std::pair<IT_, IT_> gather_full(
591 DT_* data,
const IT_* ridx,
const IT_* cidx,
592 const IT_ m,
const IT_ n,
const IT_ stride,
593 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
595 return _first.gather_full(data, ridx, cidx, m, n, stride, mo, no);
598 template<
typename DT_,
typename IT_>
599 IT_ gather_diag(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
601 return _first.gather_diag(data, idx, m, mo);
604 template<
typename DT_,
typename IT_>
605 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
607 return _first.mult_cor(x, alpha, vec_cor.first(), idx, m, off);
611 template<
typename SubMatrix_,
int dim_>
612 class VankaMatrix<LAFEM::PowerColMatrix<SubMatrix_, dim_>>
615 typedef LAFEM::PowerColMatrix<SubMatrix_, dim_> MatrixType;
616 typedef typename MatrixType::VectorTypeR VectorTypeR;
617 typedef VankaMatrix<SubMatrix_> FirstClass;
618 typedef VankaMatrix<LAFEM::PowerColMatrix<SubMatrix_, dim_-1>> RestClass;
620 static constexpr int row_dim = FirstClass::row_dim + RestClass::row_dim;
621 static constexpr int col_dim = FirstClass::col_dim;
628 explicit VankaMatrix(
const MatrixType& matrix) :
629 _first(matrix.first()),
634 template<
typename DT_,
typename IT_>
635 std::pair<IT_, IT_> gather_full(
636 DT_* data,
const IT_* ridx,
const IT_* cidx,
637 const IT_ m,
const IT_ n,
const IT_ stride,
638 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
640 std::pair<IT_, IT_> mno = _first.gather_full(data, ridx, cidx, m, n, stride, mo, no);
641 return _rest.gather_full(data, ridx, cidx, m, n, stride, mno.first, no);
644 template<
int ro_,
int co_,
typename DT_,
typename IT_>
645 IT_ gather_diag_pfm(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
647 IT_ mno = _first.template gather_diag_pfm<ro_, co_>(data, idx, m, mo);
648 return _rest.template gather_diag_pfm<ro_+1, co_>(data, idx, m, mno);
651 template<
typename DT_,
typename IT_>
652 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
654 IT_ noff = _first.mult_cor(x, alpha, vec_cor, idx, m, off);
655 return _rest.mult_cor(x, alpha, vec_cor, idx, m, noff);
659 template<
typename SubMatrix_>
660 class VankaMatrix<LAFEM::PowerColMatrix<SubMatrix_, 1>>
663 typedef LAFEM::PowerColMatrix<SubMatrix_, 1> MatrixType;
664 typedef typename MatrixType::VectorTypeR VectorTypeR;
665 typedef VankaMatrix<SubMatrix_> FirstClass;
667 static constexpr int row_dim = FirstClass::row_dim;
668 static constexpr int col_dim = FirstClass::col_dim;
671 VankaMatrix<SubMatrix_> _first;
674 explicit VankaMatrix(
const MatrixType& matrix) :
675 _first(matrix.first())
679 template<
typename DT_,
typename IT_>
680 std::pair<IT_, IT_> gather_full(
681 DT_* data,
const IT_* ridx,
const IT_* cidx,
682 const IT_ m,
const IT_ n,
const IT_ stride,
683 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
685 return _first.gather_full(data, ridx, cidx, m, n, stride, mo, no);
688 template<
int ro_,
int co_,
typename DT_,
typename IT_>
689 IT_ gather_diag_pfm(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
691 return _first.template gather_diag_pfm<ro_, co_>(data, idx, m, mo);
694 template<
typename DT_,
typename IT_>
695 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
697 return _first.mult_cor(x, alpha, vec_cor, idx, m, off);
701 template<
typename SubMatrix_,
int dim_>
702 class VankaMatrix<LAFEM::PowerRowMatrix<SubMatrix_, dim_>>
705 typedef LAFEM::PowerRowMatrix<SubMatrix_, dim_> MatrixType;
706 typedef typename MatrixType::VectorTypeR VectorTypeR;
707 typedef VankaMatrix<SubMatrix_> FirstClass;
708 typedef VankaMatrix<LAFEM::PowerRowMatrix<SubMatrix_, dim_-1>> RestClass;
710 static constexpr int row_dim = FirstClass::row_dim;
711 static constexpr int col_dim = FirstClass::col_dim + RestClass::col_dim;
718 explicit VankaMatrix(
const MatrixType& matrix) :
719 _first(matrix.first()),
724 template<
typename DT_,
typename IT_>
725 std::pair<IT_, IT_> gather_full(
726 DT_* data,
const IT_* ridx,
const IT_* cidx,
727 const IT_ m,
const IT_ n,
const IT_ stride,
728 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
730 std::pair<IT_, IT_> mno = _first.gather_full(data, ridx, cidx, m, n, stride, mo, no);
731 return _rest.gather_full(data, ridx, cidx, m, n, stride, mo, mno.second);
734 template<
int ro_,
int co_,
typename DT_,
typename IT_>
735 IT_ gather_diag_pfm(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
738 return _first.gather_diag(data, idx, m, mo);
740 return _rest.template gather_diag_pfm<ro_, co_+1>(data, idx, m, mo);
743 template<
typename DT_,
typename IT_>
744 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
746 _first.mult_cor(x, alpha, vec_cor.first(), idx, m, off);
747 return _rest.mult_cor(x, alpha, vec_cor.rest(), idx, m, off);
751 template<
typename SubMatrix_>
752 class VankaMatrix<LAFEM::PowerRowMatrix<SubMatrix_, 1>>
755 typedef LAFEM::PowerRowMatrix<SubMatrix_, 1> MatrixType;
756 typedef VankaMatrix<SubMatrix_> FirstClass;
757 typedef typename MatrixType::VectorTypeR VectorTypeR;
759 static constexpr int row_dim = FirstClass::row_dim;
760 static constexpr int col_dim = FirstClass::col_dim;
766 explicit VankaMatrix(
const MatrixType& matrix) :
767 _first(matrix.first())
771 template<
typename DT_,
typename IT_>
772 std::pair<IT_, IT_> gather_full(
773 DT_* data,
const IT_* ridx,
const IT_* cidx,
774 const IT_ m,
const IT_ n,
const IT_ stride,
775 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
777 return _first.gather_full(data, ridx, cidx, m, n, stride, mo, no);
780 template<
int ro_,
int co_,
typename DT_,
typename IT_>
781 IT_ gather_diag_pfm(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
784 return _first.gather_diag(data, idx, m, mo);
789 template<
typename DT_,
typename IT_>
790 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
792 return _first.mult_cor(x, alpha, vec_cor.first(), idx, m, off);
796 template<
typename SubMatrix_,
int dim_w_,
int dim_h_>
797 class VankaMatrix<LAFEM::PowerFullMatrix<SubMatrix_, dim_w_, dim_h_>>
800 typedef LAFEM::PowerFullMatrix<SubMatrix_, dim_w_, dim_h_> MatrixType;
801 typedef typename MatrixType::VectorTypeR VectorTypeR;
802 typedef VankaMatrix<typename MatrixType::ContClass> ContClass;
804 static constexpr int row_dim = ContClass::row_dim;
805 static constexpr int col_dim = ContClass::col_dim;
811 explicit VankaMatrix(
const MatrixType& matrix) :
812 _cont(matrix.get_container())
816 template<
typename DT_,
typename IT_>
817 std::pair<IT_, IT_> gather_full(
818 DT_* data,
const IT_* ridx,
const IT_* cidx,
819 const IT_ m,
const IT_ n,
const IT_ stride,
820 const IT_ mo = IT_(0),
const IT_ no = IT_(0))
const
822 return _cont.gather_full(data, ridx, cidx, m, n, stride, mo, no);
825 template<
typename DT_,
typename IT_>
826 IT_ gather_diag(DT_* data,
const IT_* idx,
const IT_ m,
const IT_ mo = IT_(0))
const
828 return _cont.template gather_diag_pfm<0,0>(data, idx, m, mo);
831 template<
typename DT_,
typename IT_>
832 IT_ mult_cor(DT_* x,
const DT_ alpha,
const VectorTypeR& vec_cor,
const IT_* idx,
const IT_ m,
const IT_ off)
const
834 return _cont.mult_cor(x, alpha, vec_cor, idx, m, off);
838 template<
typename DT_,
typename IT_>
839 std::pair<const IT_*, const IT_*> vanka_graph(
const LAFEM::SparseMatrixCSR<DT_, IT_>& matrix)
841 return std::make_pair(matrix.row_ptr(), matrix.col_ind());
844 template<
typename DT_,
typename IT_,
int m_,
int n_>
845 std::pair<const IT_*, const IT_*> vanka_graph(
const LAFEM::SparseMatrixBCSR<DT_, IT_, m_, n_>& matrix)
847 return std::make_pair(matrix.row_ptr(), matrix.col_ind());
850 template<
typename DT_,
typename IT_,
int dim_>
851 std::pair<const IT_*, const IT_*> vanka_graph(
852 const LAFEM::PowerColMatrix<LAFEM::SparseMatrixCSR<DT_, IT_>, dim_>& matrix)
854 const auto& m = matrix.first();
855 return std::make_pair(m.row_ptr(), m.col_ind());
858 template<
typename DT_,
typename IT_,
int dim_>
859 std::pair<const IT_*, const IT_*> vanka_graph(
860 const LAFEM::PowerRowMatrix<LAFEM::SparseMatrixCSR<DT_, IT_>, dim_>& matrix)
862 const auto& m = matrix.first();
863 return std::make_pair(m.row_ptr(), m.col_ind());
866 template<
typename DT_,
typename IT_,
int dim_>
867 std::pair<const IT_*, const IT_*> vanka_graph(
868 const LAFEM::PowerDiagMatrix<LAFEM::SparseMatrixCSR<DT_, IT_>, dim_>& matrix)
870 const auto& m = matrix.first();
871 return std::make_pair(m.row_ptr(), m.col_ind());
874 template<
typename DT_,
typename IT_,
int row_dim_,
int col_dim_>
875 std::pair<const IT_*, const IT_*> vanka_graph(
876 const LAFEM::PowerFullMatrix<LAFEM::SparseMatrixCSR<DT_, IT_>, row_dim_, col_dim_>& matrix)
878 const auto& m = matrix.template at<0,0>();
879 return std::make_pair(m.row_ptr(), m.col_ind());
933 template<
typename Matrix_,
typename Filter_>
1008 template<
typename MatrixA_,
typename MatrixB_,
typename MatrixD_,
typename Filter_>
1009 class Vanka<LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>, Filter_> :
1010 public SolverBase<LAFEM::TupleVector<typename MatrixB_::VectorTypeL, typename MatrixD_::VectorTypeL>>
1032 typedef Intern::VankaMatrix<MatrixA_> VankaMatrixA;
1033 typedef Intern::VankaMatrix<MatrixB_> VankaMatrixB;
1034 typedef Intern::VankaMatrix<MatrixD_> VankaMatrixD;
1037 static_assert(VankaMatrixA::row_dim == VankaMatrixA::col_dim,
"Matrix A has invalid dimensions");
1038 static_assert(VankaMatrixA::row_dim == VankaMatrixB::row_dim,
"Matrices A and B have incompatible dimensions");
1039 static_assert(VankaMatrixA::col_dim == VankaMatrixD::col_dim,
"Matrices A and D have incompatible dimensions");
1040 static_assert(VankaMatrixB::col_dim == VankaMatrixD::row_dim,
"Matrices B and D have incompatible dimensions");
1043 static_assert(VankaMatrixB::col_dim == 1,
"Invalid pressure space dimension");
1115 watch_init_symbolic.
start();
1117 bool block = ((int(_type) & 0x010) != 0);
1118 bool multi = ((int(_type) & 0x100) == 0);
1123 this->_build_p_block();
1127 this->_build_p_nodal();
1131 this->_build_v_block();
1134 this->_alloc_data();
1144 watch_init_symbolic.
stop();
1156 _block_v_ptr.clear();
1157 _block_v_idx.clear();
1158 _block_p_ptr.clear();
1159 _block_p_idx.clear();
1165 watch_init_numeric.
start();
1167 bool full = ((int(_type) & 0x001) != 0);
1168 bool multi = ((int(_type) & 0x100) == 0);
1172 this->_factor_full();
1176 this->_factor_diag();
1181 this->_calc_scale();
1184 watch_init_numeric.
stop();
1187 virtual Status apply(VectorType& vec_cor,
const VectorType& vec_def)
override
1189 watch_apply.
start();
1191 bool full = ((int(_type) & 0x001) != 0);
1194 this->_apply_full(vec_cor, vec_def);
1198 this->_apply_diag(vec_cor, vec_def);
1206 std::size_t data_size()
const
1208 return _data.size();
1211 std::size_t bytes()
const
1213 return sizeof(IndexType) * (_block_v_ptr.size() + _block_v_idx.size() + _block_p_ptr.size() + _block_p_idx.size())
1214 +
sizeof(DataType) * (_data.size() + _vdef.size() + _vcor.size())
1223 watch_init_symbolic.
reset();
1224 watch_init_numeric.
reset();
1225 watch_apply.
reset();
1233 return watch_init_symbolic.
elapsed();
1241 return watch_init_numeric.
elapsed();
1265 auto graph_b = Intern::vanka_graph(_matrix.
block_b());
1266 const IndexType* row_ptr_b = graph_b.first;
1267 const IndexType* col_idx_b = graph_b.second;
1268 auto graph_d = Intern::vanka_graph(_matrix.
block_d());
1269 const IndexType* row_ptr_d = graph_d.first;
1270 const IndexType* col_idx_d = graph_d.second;
1273 _block_p_ptr.clear();
1274 _block_p_idx.clear();
1278 std::map<IndexType, int> map_s;
1281 std::vector<int> mask(std::size_t(m), 0);
1284 for(
Index i(0); i < m; ++i)
1294 for(
IndexType kd = row_ptr_d[i]; kd < row_ptr_d[i+1]; ++kd)
1300 for(
IndexType kb = row_ptr_b[col_d]; kb < row_ptr_b[col_d+1]; ++kb)
1306 auto ib = map_s.emplace(col_b, 1);
1310 ++(ib.first->second);
1317 for(
auto it = map_s.begin(); it != map_s.end(); ++it)
1321 for(
auto it = map_s.begin(); it != map_s.end(); ++it)
1323 if(ideg == it->second)
1326 _block_p_idx.push_back(it->first);
1327 mask[it->first] = 1;
1332 _block_p_ptr.push_back(
IndexType(_block_p_idx.size()));
1344 _block_p_ptr.clear();
1345 _block_p_idx.clear();
1346 _block_p_ptr.reserve(m+1);
1347 _block_p_idx.reserve(m);
1350 _block_p_ptr.push_back(i);
1351 _block_p_idx.push_back(i);
1353 _block_p_ptr.push_back(m);
1360 auto graph_d = Intern::vanka_graph(_matrix.
block_d());
1361 const IndexType* row_ptr_d = graph_d.first;
1362 const IndexType* col_idx_d = graph_d.second;
1368 _block_v_ptr.clear();
1369 _block_v_idx.clear();
1370 _block_v_ptr.reserve(m+1);
1373 std::set<IndexType> set_v;
1379 for(
IndexType j = _block_p_ptr[i]; j < _block_p_ptr[i+1]; ++j)
1385 for(
IndexType k = row_ptr_d[pix]; k < row_ptr_d[pix+1]; ++k)
1388 set_v.insert(col_idx_d[k]);
1393 for(
auto it = set_v.begin(); it != set_v.end(); ++it)
1395 _block_v_idx.push_back(*it);
1399 _block_v_ptr.push_back(
IndexType(_block_v_idx.size()));
1413 bool diag = ((int(_type) & 1) == 0);
1426 IndexType nv = _block_v_ptr[i+1] - _block_v_ptr[i];
1427 IndexType np = _block_p_ptr[i+1] - _block_p_ptr[i];
1452 _vdef.resize(dim*_degree_v + _degree_p);
1453 _vcor.resize(dim*_degree_v + _degree_p);
1460 this->_vec_scale.
format();
1461 Intern::VankaVector<VectorV> vanka_v(this->_vec_scale.template at<0>());
1462 Intern::VankaVector<VectorP> vanka_p(this->_vec_scale.template at<1>());
1465 const IndexType* vptr = _block_v_ptr.data();
1466 const IndexType* vidx = _block_v_idx.data();
1467 const IndexType* pptr = _block_p_ptr.data();
1468 const IndexType* pidx = _block_p_idx.data();
1471 std::vector<DataType> vec_one(vanka_v.dim*_degree_v + _degree_p,
DataType(1));
1472 const DataType* vone = vec_one.data();
1476 for(
IndexType iblock(0); iblock < nblocks; ++iblock)
1479 const IndexType nv = vptr[iblock+1] - vptr[iblock];
1480 const IndexType np = pptr[iblock+1] - pptr[iblock];
1488 this->_vec_scale.component_invert(this->_vec_scale);
1494 Intern::VankaMatrix<MatrixA_> vanka_a(_matrix.
block_a());
1495 Intern::VankaMatrix<MatrixB_> vanka_b(_matrix.
block_b());
1496 Intern::VankaMatrix<MatrixD_> vanka_d(_matrix.
block_d());
1503 const IndexType* vptr = _block_v_ptr.data();
1504 const IndexType* vidx = _block_v_idx.data();
1505 const IndexType* pptr = _block_p_ptr.data();
1506 const IndexType* pidx = _block_p_idx.data();
1509 ::memset(data, 0,
sizeof(
DataType) * _data.size());
1512 std::vector<IndexType> pivot(3*(dim*_degree_v + _degree_p));
1519 for(
IndexType iblock(0); iblock < nblocks; ++iblock)
1522 const IndexType nv = vptr[iblock+1] - vptr[iblock];
1523 const IndexType np = pptr[iblock+1] - pptr[iblock];
1526 const IndexType* loc_vidx = &vidx[vptr[iblock]];
1527 const IndexType* loc_pidx = &pidx[pptr[iblock]];
1534 DataType* block_data = &data[block_offset];
1537 std::pair<IndexType,IndexType> ao =
1538 vanka_a.gather_full(block_data, loc_vidx, loc_vidx, nv, nv, n);
1539 vanka_b.gather_full(block_data, loc_vidx, loc_pidx, nv, np, n,
IndexType(0), ao.second);
1540 vanka_d.gather_full(block_data, loc_pidx, loc_vidx, np, nv, n, ao.first,
IndexType(0));
1551 block_offset += block_size;
1562 const bool multi = ((int(_type) & 0x100) == 0);
1567 this->_vec_tmp1.
copy(vec_def);
1568 this->_vec_tmp2.
format();
1572 VectorV& vec_cv = (multi ? vec_cor.template at<0>() : this->_vec_tmp2.template at<0>());
1573 VectorP& vec_cp = (multi ? vec_cor.template at<1>() : this->_vec_tmp2.template at<1>());
1574 const VectorV& vec_dv = (multi ? vec_def.template at<0>() : this->_vec_tmp1.template at<0>());
1575 const VectorP& vec_dp = (multi ? vec_def.template at<1>() : this->_vec_tmp1.template at<1>());
1578 Intern::VankaMatrix<MatrixA_> vanka_a(_matrix.
block_a());
1579 Intern::VankaMatrix<MatrixB_> vanka_b(_matrix.
block_b());
1580 Intern::VankaMatrix<MatrixD_> vanka_d(_matrix.
block_d());
1581 Intern::VankaVector<VectorV> vanka_v(vec_cv);
1582 Intern::VankaVector<VectorP> vanka_p(vec_cp);
1591 const IndexType* vptr = _block_v_ptr.data();
1592 const IndexType* vidx = _block_v_idx.data();
1593 const IndexType* pptr = _block_p_ptr.data();
1594 const IndexType* pidx = _block_p_idx.data();
1597 const DataType* lmat_data = _data.data();
1610 this->_matrix.
apply(_vec_tmp1, vec_cor, vec_def, -
DataType(1));
1620 for(
IndexType iblock(0); iblock < num_blocks; ++iblock)
1623 const IndexType nv = vptr[iblock+1] - vptr[iblock];
1624 const IndexType np = pptr[iblock+1] - pptr[iblock];
1627 const IndexType* loc_vidx = &vidx[vptr[iblock]];
1628 const IndexType* loc_pidx = &pidx[pptr[iblock]];
1634 const DataType* lmat = &lmat_data[block_offset];
1638 DataType* lcor_p = &lcor[velo_dim * nv];
1640 DataType* ldef_p = &ldef[velo_dim * nv];
1643 vanka_v.gather_def(ldef_v, vec_dv, loc_vidx, nv,
IndexType(0));
1644 vanka_p.gather_def(ldef_p, vec_dp, loc_pidx, np,
IndexType(0));
1661 lcor[i] += lmat[i*n + j] * ldef[j];
1667 vanka_v.scatter_cor(_omega, lcor_v, loc_vidx, nv,
IndexType(0));
1668 vanka_p.scatter_cor(_omega, lcor_p, loc_pidx, np,
IndexType(0));
1671 block_offset += n*n;
1674 Statistics::add_time_precon(stamp_kernel.
elapsed_now());
1680 this->_vec_tmp2.component_product(this->_vec_tmp2, this->_vec_scale);
1683 vec_cor.axpy(this->_vec_tmp2);
1687 _filter.filter_cor(vec_cor);
1696 Intern::VankaMatrix<MatrixA_> vanka_a(_matrix.
block_a());
1697 Intern::VankaMatrix<MatrixB_> vanka_b(_matrix.
block_b());
1698 Intern::VankaMatrix<MatrixD_> vanka_d(_matrix.
block_d());
1705 const IndexType* vptr = _block_v_ptr.data();
1706 const IndexType* vidx = _block_v_idx.data();
1707 const IndexType* pptr = _block_p_ptr.data();
1708 const IndexType* pidx = _block_p_idx.data();
1711 ::memset(data, 0,
sizeof(
DataType) * _data.size());
1714 std::vector<IndexType> pivot(3*_degree_p);
1721 for(
IndexType iblock(0); iblock < nblocks; ++iblock)
1724 const IndexType nv = vptr[iblock+1] - vptr[iblock];
1725 const IndexType np = pptr[iblock+1] - pptr[iblock];
1729 const IndexType* loc_vidx = &vidx[vptr[iblock]];
1730 const IndexType* loc_pidx = &pidx[pptr[iblock]];
1736 DataType* block_data = &data[block_offset];
1740 DataType* loc_b = &block_data[dnv];
1741 DataType* loc_d = &block_data[dnv + dnv*np];
1745 vanka_a.gather_diag(loc_a, loc_vidx, nv);
1747 vanka_b.gather_full(loc_b, loc_vidx, loc_pidx, nv, np, np);
1748 vanka_d.gather_full(loc_d, loc_pidx, loc_vidx, np, nv, dnv);
1765 loc_d[j*dnv + i] *= loc_a[i];
1779 s += loc_d[i*dnv + k] * loc_b[k*np + j];
1781 loc_s[i*np + j] = -s;
1794 block_offset += block_size;
1805 const bool multi = ((int(_type) & 0x100) == 0);
1810 this->_vec_tmp1.
copy(vec_def);
1811 this->_vec_tmp2.
format();
1815 VectorV& vec_cv = (multi ? vec_cor.template at<0>() : this->_vec_tmp2.template at<0>());
1816 VectorP& vec_cp = (multi ? vec_cor.template at<1>() : this->_vec_tmp2.template at<1>());
1817 const VectorV& vec_dv = (multi ? vec_def.template at<0>() : this->_vec_tmp1.template at<0>());
1818 const VectorP& vec_dp = (multi ? vec_def.template at<1>() : this->_vec_tmp1.template at<1>());
1821 Intern::VankaMatrix<MatrixA_> vanka_a(_matrix.
block_a());
1822 Intern::VankaMatrix<MatrixB_> vanka_b(_matrix.
block_b());
1823 Intern::VankaMatrix<MatrixD_> vanka_d(_matrix.
block_d());
1824 Intern::VankaVector<VectorV> vanka_v(vec_cv);
1825 Intern::VankaVector<VectorP> vanka_p(vec_cp);
1834 const IndexType* vptr = _block_v_ptr.data();
1835 const IndexType* vidx = _block_v_idx.data();
1836 const IndexType* pptr = _block_p_ptr.data();
1837 const IndexType* pidx = _block_p_idx.data();
1840 const DataType* data = _data.data();
1853 this->_matrix.
apply(_vec_tmp1, vec_cor, vec_def, -
DataType(1));
1863 for(
IndexType iblock(0); iblock < num_blocks; ++iblock)
1866 const IndexType nv = vptr[iblock+1] - vptr[iblock];
1867 const IndexType np = pptr[iblock+1] - pptr[iblock];
1871 const IndexType* loc_vidx = &vidx[vptr[iblock]];
1872 const IndexType* loc_pidx = &pidx[pptr[iblock]];
1878 const DataType* block_data = &data[block_offset];
1881 const DataType* loc_a = block_data;
1882 const DataType* loc_b = &block_data[dnv];
1883 const DataType* loc_d = &block_data[dnv + dnv*np];
1893 vanka_v.gather_def(ldef_v, vec_dv, loc_vidx, nv,
IndexType(0));
1894 vanka_p.gather_def(ldef_p, vec_dp, loc_pidx, np,
IndexType(0));
1913 r += loc_d[i*dnv + j] * ldef_v[j];
1926 r += loc_s[i*np + j] * ldef_p[j];
1938 xb += loc_b[i*np + j] * lcor_p[j];
1941 lcor_v[i] = loc_a[i] * (ldef_v[i] - xb);
1943 flops += dnv * (2*np + 2);
1946 vanka_v.scatter_cor(_omega, lcor_v, loc_vidx, nv,
IndexType(0));
1947 vanka_p.scatter_cor(_omega, lcor_p, loc_pidx, np,
IndexType(0));
1950 block_offset += block_size;
1953 Statistics::add_time_precon(stamp_kernel.
elapsed_now());
1959 this->_vec_tmp2.component_product(this->_vec_tmp2, this->_vec_scale);
1962 vec_cor.axpy(this->_vec_tmp2);
1966 _filter.filter_cor(vec_cor);
1994 template<
typename MatrixA_,
typename MatrixB_,
typename MatrixD_,
typename Filter_>
1995 std::shared_ptr<Vanka<LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>, Filter_>>
new_vanka(
1997 const Filter_& filter,
1999 typename MatrixA_::DataType omega =
typename MatrixA_::DataType(1),
2002 return std::make_shared<Vanka<LAFEM::SaddlePointMatrix<MatrixA_, MatrixB_, MatrixD_>, Filter_>>
2003 (matrix, filter, type, omega, num_iter);
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Saddle-Point matrix meta class template.
MatrixTypeA::DataType DataType
data type
MatrixTypeA & block_a()
Returns the sub-matrix block A.
VectorTypeR create_vector_r() const
Returns a new compatible R-Vector.
void apply(VectorTypeL &r, const VectorTypeR &x) const
Applies this matrix onto a vector.
MatrixTypeA::IndexType IndexType
index type
MatrixTypeB & block_b()
Returns the sub-matrix block B.
MatrixTypeD & block_d()
Returns the sub-matrix block D.
Variadic TupleVector class template.
std::size_t bytes() const
Returns the total amount of bytes allocated.
void copy(const TupleVector &x, bool full=false)
Performs .
void format(DataType value=DataType(0))
Reset all elements of the container to a given value or zero if missing.
void clear()
Free all allocated arrays.
Polymorphic solver interface.
Base-class for solver generated exceptions.
MatrixType::DataType DataType
our data type
virtual void init_numeric() override
Performs numeric factorization.
void _calc_scale()
Calculate the scaling vector for additive Vanka.
double time_apply() const
Returns the total accumulated time for the solver application.
virtual void done_symbolic() override
Releases the symbolic factorization data.
DataType _omega
relaxation parameter
void _factor_full()
Performs the 'full' numerical factorization.
Index _num_iter
desired number of iterations
void _factor_diag()
Performs the 'diagonal' numerical factorization.
IndexType _degree_p
maximum pressure block degree
void _build_p_block()
Builds the 'blocked' pressure graph.
void _alloc_data()
Allocates the data arrays for numerical factorization.
virtual void init_symbolic() override
Performs symbolic factorization.
std::vector< IndexType > _block_v_ptr
velocity block structure
MatrixType::IndexType IndexType
our index type
std::vector< DataType > _data
factorization data
Filter_ FilterType
our filter type
void _apply_full(VectorType &vec_cor, const VectorType &vec_def)
Applies the 'full' Vanka iteration.
MatrixB_::VectorTypeR VectorP
pressure vector type
double time_init_numeric() const
Returns the total accumulated time for numeric initialization.
MatrixType::VectorTypeR VectorType
our vector type
virtual String name() const override
Returns the name of the solver.
void _build_v_block()
Builds the velocity graph.
std::vector< IndexType > _block_p_ptr
pressure block structure
const FilterType & _filter
the system filter
void reset_timings()
Resets the internal stop watches for time measurement.
VectorType _vec_scale
temporary vectors (additive types only)
VankaType _type
the Vanka type
IndexType _degree_v
maximum velocity block degree
Vanka(const MatrixType &matrix, const FilterType &filter, VankaType type, DataType omega=DataType(1), Index num_iter=Index(1))
Constructor.
void _apply_diag(VectorType &vec_cor, const VectorType &vec_def)
Applies the 'diagonal' Vanka iteration.
void _build_p_nodal()
Builds the 'nodal' pressure graph.
MatrixD_::VectorTypeR VectorV
velocity vector type
const MatrixType & _matrix
the system matrix
std::vector< DataType > _vdef
local defect/correction vectors
double time_init_symbolic() const
Returns the total accumulated time for symbolic initialization.
LAFEM::SaddlePointMatrix< MatrixA_, MatrixB_, MatrixD_ > MatrixType
our matrix type
Vanka Factorization Error.
Vanka preconditioner/smoother class template.
static void add_flops(Index flops)
Add an amount of flops to the global flop counter.
double elapsed() const
Returns the total elapsed time in seconds.
void start()
Starts the stop-watch.
void reset()
Resets the elapsed time.
void stop()
Stops the stop-watch and increments elapsed time.
String class implementation.
double elapsed_now() const
Calculates the time elapsed between the time stamp and now.
bool isnormal(T_ x)
Checks whether a value is normal.
T_ sqr(T_ x)
Returns the square of a value.
DT_ invert_matrix(const IT_ n, const IT_ stride, DT_ a[], IT_ p[])
Inverts a matrix and returns its determinant.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
VankaType
Vanka type enumeration.
@ nodal_full_mult
Nodal full Vanka type (multiplicative)
@ block_diag_add
Blocked diagonal Vanka type (additive)
@ nodal_full_add
Nodal full Vanka type (additive)
@ block_diag_mult
Blocked diagonal Vanka type (multiplicative)
@ nodal_diag_mult
Nodal diagonal Vanka type (multiplicative)
@ block_full_mult
Blocked full Vanka type (multiplicative)
@ nodal_diag_add
Nodal diagonal Vanka type (additive)
@ block_full_add
Blocked full Vanka type (additive)
Status
Solver status return codes enumeration.
@ success
solving successful (convergence criterion fulfilled)
@ iter
Plot every iteration (if applicable)
@ full
full Uzawa preconditioner
@ rest
restriction (multigrid)
std::shared_ptr< Vanka< LAFEM::SaddlePointMatrix< MatrixA_, MatrixB_, MatrixD_ >, Filter_ > > new_vanka(const LAFEM::SaddlePointMatrix< MatrixA_, MatrixB_, MatrixD_ > &matrix, const Filter_ &filter, VankaType type, typename MatrixA_::DataType omega=typename MatrixA_::DataType(1), Index num_iter=Index(1))
Creates a new Vanka solver object.
std::uint64_t Index
Index data type.