FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
ilu_precond.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/solver/base.hpp>
10#include <kernel/lafem/sparse_matrix_csr.hpp>
11#include <kernel/lafem/sparse_matrix_bcsr.hpp>
12
13// includes, system
14#include <vector>
15
16namespace FEAT
17{
18 namespace Solver
19 {
21 namespace Intern
22 {
23 int cuda_ilu_apply(double * y, const double * x, double * csrVal, int * csrRowPtr, int * csrColInd, void * vinfo);
24 void * cuda_ilu_init_symbolic(int m, int nnz, double * csrVal, int * csrRowPtr, int * csrColInd);
25 void cuda_ilu_init_numeric(double * csrVal, int * csrRowPtr, int * csrColInd, void * vinfo);
26 void cuda_ilu_done_symbolic(void * vinfo);
27
28 int cuda_ilub_apply(double * y, const double * x, double * csrVal, int * csrRowPtr, int * csrColInd, void * vinfo);
29 void * cuda_ilub_init_symbolic(int m, int nnz, double * csrVal, int * csrRowPtr, int * csrColInd, const int blocksize);
30 void cuda_ilub_init_numeric(double * csrVal, int * csrRowPtr, int * csrColInd, void * vinfo);
31 void cuda_ilub_done_symbolic(void * vinfo);
32
44 template<typename IT_>
45 class ILUCoreSymbolic
46 {
47 protected:
49 IT_ _n;
51 std::vector<IT_> _row_ptr_l, _col_idx_l;
53 std::vector<IT_> _row_ptr_u, _col_idx_u;
54 //std::vector<IT_> _lvl_l, _lvl_u;
55
56 public:
58 void clear()
59 {
60 _n = IT_(0);
61 _row_ptr_l.clear();
62 _col_idx_l.clear();
63 _row_ptr_u.clear();
64 _col_idx_u.clear();
65 //_lvl_l.clear();
66 //_lvl_u.clear();
67 }
68
70 IT_ get_nnze_l() const
71 {
72 return _row_ptr_l.empty() ? IT_(0) : _row_ptr_l.back();
73 }
74
76 IT_ get_nnze_u() const
77 {
78 return _row_ptr_u.empty() ? IT_(0) : _row_ptr_u.back();
79 }
80
82 IT_ get_nnze() const
83 {
84 return _n + get_nnze_l() + get_nnze_u();
85 }
86
88 std::size_t bytes_symbolic() const
89 {
90 return sizeof(IT_) * (_row_ptr_l.size() + _row_ptr_u.size() + _col_idx_l.size() + _col_idx_u.size());
91 }
92
105 void set_struct_csr(const IT_ n, const IT_* row_ptr_a, const IT_* col_idx_a)
106 {
107 // First of all, let's guess the number of non-zeros for L and U:
108 // In most of our cases, the sparsity pattern of A is symmetric,
109 // so we have a guess of (nz(A)-n)/2 for both L and U:
110 const IT_ nzul = (Math::max(row_ptr_a[n], n) - n) / IT_(2);
111
112 // store size and clear containers
113 _n = n;
114 _row_ptr_l.clear();
115 _col_idx_l.clear();
116 _row_ptr_u.clear();
117 _col_idx_u.clear();
118
119 // reserve our non-zero guess
120 _row_ptr_l.reserve(n+1);
121 _row_ptr_u.reserve(n+1);
122 _col_idx_l.reserve(nzul);
123 _col_idx_u.reserve(nzul);
124
125 // initialize row-pointers
126 _row_ptr_l.push_back(0);
127 _row_ptr_u.push_back(0);
128
129 // loop over all matrix rows
130 for(IT_ i(0); i < n; ++i)
131 {
132 IT_ j = row_ptr_a[i];
133 const IT_ jend = row_ptr_a[i+1];
134 for(; (j < jend) && (col_idx_a[j] < i); ++j)
135 {
136 _col_idx_l.push_back(col_idx_a[j]);
137 }
138 if(col_idx_a[j] != i)
139 throw InvalidMatrixStructureException();
140 for(++j; j < jend; ++j)
141 {
142 _col_idx_u.push_back(col_idx_a[j]);
143 }
144 _row_ptr_l.push_back(IT_(_col_idx_l.size()));
145 _row_ptr_u.push_back(IT_(_col_idx_u.size()));
146 }
147
148 //_lvl_l.resize(_col_idx_l.size(), IT_(0));
149 //_lvl_u.resize(_col_idx_u.size(), IT_(0));
150 }
151
158 template<typename DT_>
159 void set_struct(const LAFEM::SparseMatrixCSR<DT_, IT_>& matrix)
160 {
161 this->set_struct_csr(IT_(matrix.rows()), matrix.row_ptr(), matrix.col_ind());
162 }
163
170 template<typename DT_, int m_, int n_>
171 void set_struct(const LAFEM::SparseMatrixBCSR<DT_, IT_, m_, n_>& matrix)
172 {
173 this->set_struct_csr(IT_(matrix.rows()), matrix.row_ptr(), matrix.col_ind());
174 }
175
190 void factorize_symbolic(const int p)
191 {
192 if(p < 1)
193 return;
194
195 // our new level-p structures for L and U
196 std::vector<IT_> new_ptr_l, new_idx_l, new_ptr_u, new_idx_u;
197
198 // our temporary level arrays
199 std::vector<int> new_lvl_l, new_lvl_u;
200
201 // initialize new row pointers
202 new_ptr_l.push_back(IT_(0));
203 new_ptr_u.push_back(IT_(0));
204
205 // loop over all rows
206 for(IT_ i(0); i < _n; ++i)
207 {
208 // first off, add all level 0 entries to L and U
209 for(IT_ j(_row_ptr_l[i]); j < _row_ptr_l[i+1]; ++j)
210 {
211 new_idx_l.push_back(_col_idx_l[j]);
212 new_lvl_l.push_back(0);
213 }
214 for(IT_ j(_row_ptr_u[i]); j < _row_ptr_u[i+1]; ++j)
215 {
216 new_idx_u.push_back(_col_idx_u[j]);
217 new_lvl_u.push_back(0);
218 }
219
220 // loop over row L_i
221 for(IT_ j(new_ptr_l[i]); j < IT_(new_idx_l.size()); ++j)
222 {
223 // get column index and level of L_ij
224 const IT_ cj = new_idx_l[j];
225 const int lj = new_lvl_l[j];
226 IT_ olj = j;
227 IT_ ouj = new_ptr_u[i];
228
229 // loop over row U_j
230 for(IT_ k(new_ptr_u[cj]); k < new_ptr_u[cj+1]; ++k)
231 {
232 // get column index and level of U_jk
233 const IT_ ck = new_idx_u[k];
234 const int lk = new_lvl_u[k];
235
236 // compute level of entry L/U_ik
237 const int ll = lj + lk + 1;
238 if(ll > p)
239 continue;
240
241 // insert into L or U
242 if(ck < i)
243 olj = _insert(new_idx_l, new_lvl_l, olj, ck, ll);
244 else if(ck > i)
245 ouj = _insert(new_idx_u, new_lvl_u, ouj, ck, ll);
246 }
247 }
248
249 // update row-pointers
250 new_ptr_l.push_back(IT_(new_idx_l.size()));
251 new_ptr_u.push_back(IT_(new_idx_u.size()));
252 }
253
254 // replace old arrays
255 _row_ptr_l = std::move(new_ptr_l);
256 _col_idx_l = std::move(new_idx_l);
257 _row_ptr_u = std::move(new_ptr_u);
258 _col_idx_u = std::move(new_idx_u);
259
260 //_lvl_l = new_lvl_l;
261 //_lvl_u = new_lvl_u;
262 }
263
264 protected:
289 static IT_ _insert(std::vector<IT_>& idx, std::vector<int>& lvl, IT_ i, const IT_ j, const int l)
290 {
291 // get the current length of the column-index vector
292 IT_ n = IT_(idx.size());
293
294 // loop over the row and try to find our entry
295 for(; i < n; ++i)
296 {
297 if(idx[i] == j)
298 {
299 // the entry that we want to add already exists in the sparsity pattern,
300 // so check whether we need to adapt its level
301 if(l < lvl[i])
302 lvl[i] = l;
303
304 // return next entry starting position
305 return ++i;
306 }
307 else if(j < idx[i])
308 {
309 // we have reached a column index beyond the entry we want to add,
310 // so stop searching
311 break;
312 }
313 }
314
315 // the entry we want to add does not yet exist in the sparsity pattern,
316 // so we add it at position i by linear insertion:
317 idx.push_back(IT_(0));
318 lvl.push_back(0);
319
320 // shift all entries backward by one position
321 for(IT_ k(n); k > i; --k)
322 {
323 idx[k] = idx[k-1];
324 lvl[k] = lvl[k-1];
325 }
326
327 // insert at desired position
328 idx[i] = j;
329 lvl[i] = l;
330
331 // return next entry starting position
332 return ++i;
333 }
334 }; // class ILUCoreSymbolic
335
349 template<typename DT_, typename IT_>
350 class ILUCoreScalar :
351 public ILUCoreSymbolic<IT_>
352 {
353 protected:
354 typedef ILUCoreSymbolic<IT_> BaseClass;
355
357 std::vector<DT_> _data_l, _data_u, _data_d;
358
359 public:
361 void clear()
362 {
363 BaseClass::clear();
364 _data_l.clear();
365 _data_u.clear();
366 _data_d.clear();
367 }
368
370 void alloc_data()
371 {
372 // resize data arrays
373 _data_d.resize(this->_n);
374 _data_l.resize(this->_col_idx_l.size());
375 _data_u.resize(this->_col_idx_u.size());
376 }
377
379 std::size_t bytes_numeric() const
380 {
381 return sizeof(DT_) * (_data_l.size() + _data_u.size() + _data_d.size());
382 }
383
385 std::size_t bytes() const
386 {
387 return this->bytes_numeric() + this->bytes_symbolic();
388 }
389
402 void copy_data_csr(const IT_* row_ptr_a, const IT_* col_idx_a, const DT_* data_a)
403 {
404 // loop over all rows
405 for(IT_ i(0); i < this->_n; ++i)
406 {
407 // get row pointer of a
408 IT_ ra = row_ptr_a[i];
409 IT_ xa = row_ptr_a[i+1];
410
411 // fetch row i of L
412 for(IT_ j(this->_row_ptr_l[i]); j < this->_row_ptr_l[i+1]; ++j)
413 {
414 if(this->_col_idx_l[j] == col_idx_a[ra])
415 _data_l[j] = data_a[ra++];
416 else //if(this->_col_idx_l[j] < col_idx_a[ra])
417 _data_l[j] = DT_(0);
418 }
419
420 // fetch diagonal of a
421 _data_d[i] = data_a[ra++];
422
423 // fetch row i of U
424 for(IT_ j(this->_row_ptr_u[i]); j < this->_row_ptr_u[i+1]; ++j)
425 {
426 if((ra < xa) && (this->_col_idx_u[j] == col_idx_a[ra]))
427 _data_u[j] = data_a[ra++];
428 else// if(this->_col_idx_u[j] < col_idx_a[ra])
429 _data_u[j] = DT_(0);
430 }
431 }
432 }
433
440 void copy_data(const LAFEM::SparseMatrixCSR<DT_, IT_>& matrix)
441 {
442 this->copy_data_csr(matrix.row_ptr(), matrix.col_ind(), matrix.val());
443 }
444
451 void factorize_numeric_il_du()
452 {
453 // get data arrays
454 const IT_* rptr_l = this->_row_ptr_l.data();
455 const IT_* rptr_u = this->_row_ptr_u.data();
456 const IT_* cidx_l = (this->_col_idx_l.empty() ? nullptr : this->_col_idx_l.data());
457 const IT_* cidx_u = (this->_col_idx_u.empty() ? nullptr : this->_col_idx_u.data());
458 DT_* data_l = (this->_data_l.empty() ? nullptr : this->_data_l.data());
459 DT_* data_u = (this->_data_u.empty() ? nullptr : this->_data_u.data());
460 DT_* data_d = this->_data_d.data();
461
462 // loop over all rows
463 for(IT_ i(0); i < this->_n; ++i)
464 {
465 // get row-end pointers of L and U
466 const IT_ ql = rptr_l[i+1];
467 const IT_ qu = rptr_u[i+1];
468
469 // loop over row i of L
470 for(IT_ j(rptr_l[i]); j < rptr_l[i+1]; ++j)
471 {
472 // get column index of L_ij
473 const IT_ cj = cidx_l[j];
474
475 // get L/U pointers
476 IT_ pl = j;
477 IT_ pu = rptr_u[i];
478
479 // update L_ij <- L_ij / D_jj
480 data_l[j] *= data_d[cj];
481
482 // loop over row j of U and process row i of L
483 IT_ k(rptr_u[cj]);
484 for(; k < rptr_u[cj+1]; ++k)
485 {
486 const IT_ ck = cidx_u[k];
487 if(ck >= i)
488 break;
489 for(; (pl < ql) && (cidx_l[pl] <= ck); ++pl)
490 {
491 if(cidx_l[pl] == ck)
492 data_l[pl] -= data_l[j] * data_u[k];
493 }
494 }
495
496 // process main diagonal entry
497 if((k < rptr_u[cj+1]) && (cidx_u[k] == i))
498 {
499 data_d[i] -= data_l[j] * data_u[k];
500 ++k;
501 }
502 // loop over row j of U and process row i of U
503 for(; k < rptr_u[cj+1]; ++k)
504 {
505 const IT_ ck = cidx_u[k];
506 for(; (pu < qu) && (cidx_u[pu] <= ck); ++pu)
507 {
508 if(cidx_u[pu] == ck)
509 data_u[pu] -= data_l[j] * data_u[k];
510 }
511 }
512 }
513
514 // invert main diagonal entry
515 data_d[i] = DT_(1) / data_d[i];
516 }
517 }
518
531 void solve_il(DT_* x, const DT_* b) const
532 {
533
534 const IT_* rptr = this->_row_ptr_l.data();
535 const IT_* cidx = (this->_col_idx_l.empty() ? nullptr : this->_col_idx_l.data());
536 const DT_* data_l = (this->_data_l.empty() ? nullptr : this->_data_l.data());
537
538 for(IT_ i(0); i < this->_n; ++i)
539 {
540 DT_ r(b[i]);
541 for(IT_ j(rptr[i]); j < rptr[i+1]; ++j)
542 {
543 r -= data_l[j] * x[cidx[j]];
544 }
545 x[i] = r;
546 }
547 }
548
561 void solve_du(DT_* x, const DT_* b) const
562 {
563 const IT_* rptr = this->_row_ptr_u.data();
564 const IT_* cidx = (this->_col_idx_u.empty() ? nullptr : this->_col_idx_u.data());
565 const DT_* data_u = (this->_data_u.empty() ? nullptr : this->_data_u.data());
566 const DT_* data_d = this->_data_d.data();
567
568 for(IT_ i(this->_n); i > IT_(0); )
569 {
570 --i;
571 DT_ r(b[i]);
572 for(IT_ j(rptr[i]); j < rptr[i+1]; ++j)
573 {
574 r -= data_u[j] * x[cidx[j]];
575 }
576 x[i] = data_d[i] * r;
577 }
578 }
579
592 void solve_ilt(DT_* x, const DT_* b) const
593 {
594 const IT_* rptr = this->_row_ptr_l.data();
595 const IT_* cidx = (this->_col_idx_l.empty() ? nullptr : this->_col_idx_l.data());
596 const DT_* data_l = (this->_data_l.empty() ? nullptr : this->_data_l.data());
597
598 if(x != b)
599 {
600 for(IT_ i(0); i < this->_n; ++i)
601 x[i] = b[i];
602 }
603
604 for(IT_ i(this->_n); i > IT_(0); )
605 {
606 --i;
607 for(IT_ j(rptr[i]); j < rptr[i+1]; ++j)
608 {
609 // x_j -= L_ij * x[i]
610 x[cidx[j]] -= data_l[j] * x[i];
611 }
612 }
613 }
614
627 void solve_dut(DT_* x, const DT_* b) const
628 {
629 const IT_* rptr = this->_row_ptr_u.data();
630 const IT_* cidx = (this->_col_idx_u.empty() ? nullptr : this->_col_idx_u.data());
631 const DT_* data_u = (this->_data_u.empty() ? nullptr : this->_data_u.data());
632 const DT_* data_d = this->_data_d.data();
633
634 if(x != b)
635 {
636 for(IT_ i(0); i < this->_n; ++i)
637 x[i] = b[i];
638 }
639
640 for(IT_ i(0); i < this->_n; ++i)
641 {
642 x[i] *= data_d[i];
643 for(IT_ j(rptr[i]); j < rptr[i+1]; ++j)
644 {
645 // x_j -= U_ij * x_i
646 x[cidx[j]] -= data_u[j] * x[i];
647 }
648 }
649 }
650 }; // class ILUCoreScalar
651
668 template<typename DT_, typename IT_, int dim_>
669 class ILUCoreBlocked :
670 public ILUCoreSymbolic<IT_>
671 {
672 protected:
673 typedef ILUCoreSymbolic<IT_> BaseClass;
674
675 static_assert(dim_ > 0, "invalid block dimension");
676
677 typedef Tiny::Matrix<DT_, dim_, dim_> MatBlock;
678 typedef Tiny::Vector<DT_, dim_> VecBlock;
679
681 std::vector<MatBlock> _data_l, _data_u, _data_d;
682
683 public:
685 void clear()
686 {
687 BaseClass::clear();
688 _data_l.clear();
689 _data_u.clear();
690 _data_d.clear();
691 }
692
694 void alloc_data()
695 {
696 // resize data arrays
697 _data_d.resize(this->_n);
698 _data_l.resize(this->_col_idx_l.size());
699 _data_u.resize(this->_col_idx_u.size());
700 }
701
703 std::size_t bytes_numeric() const
704 {
705 return sizeof(DT_) * std::size_t(Math::sqr(dim_)) * (_data_l.size() + _data_u.size() + _data_d.size());
706 }
707
709 std::size_t bytes() const
710 {
711 return this->bytes_numeric() + this->bytes_symbolic();
712 }
713
726 void copy_data_bcsr(const IT_* row_ptr_a, const IT_* col_idx_a, const MatBlock* data_a)
727 {
728 // loop over all rows
729 for(IT_ i(0); i < this->_n; ++i)
730 {
731 // get row pointer of a
732 IT_ ra = row_ptr_a[i];
733 IT_ xa = row_ptr_a[i+1];
734
735 // fetch row i of L
736 for(IT_ j(this->_row_ptr_l[i]); j < this->_row_ptr_l[i+1]; ++j)
737 {
738 if(this->_col_idx_l[j] == col_idx_a[ra])
739 _data_l[j] = data_a[ra++];
740 else //if(this->_col_idx_l[j] < col_idx_a[ra])
741 _data_l[j] = DT_(0);
742 }
743
744 // fetch diagonal of a
745 _data_d[i] = data_a[ra++];
746
747 // fetch row i of U
748 for(IT_ j(this->_row_ptr_u[i]); j < this->_row_ptr_u[i+1]; ++j)
749 {
750 if((ra < xa) && (this->_col_idx_u[j] == col_idx_a[ra]))
751 _data_u[j] = data_a[ra++];
752 else// if(this->_col_idx_u[j] < col_idx_a[ra])
753 _data_u[j] = DT_(0);
754 }
755 }
756 }
757
764 void copy_data(const LAFEM::SparseMatrixBCSR<DT_, IT_, dim_, dim_>& matrix)
765 {
766 this->copy_data_bcsr(matrix.row_ptr(), matrix.col_ind(), matrix.val());
767 }
768
775 void factorize_numeric_il_du()
776 {
777 // get data arrays
778 const IT_* rptr_l = this->_row_ptr_l.data();
779 const IT_* rptr_u = this->_row_ptr_u.data();
780 const IT_* cidx_l = (this->_col_idx_l.empty() ? nullptr : this->_col_idx_l.data());
781 const IT_* cidx_u = (this->_col_idx_u.empty() ? nullptr : this->_col_idx_u.data());
782 MatBlock* data_l = (this->_data_l.empty() ? nullptr : this->_data_l.data());
783 MatBlock* data_u = (this->_data_u.empty() ? nullptr : this->_data_u.data());
784 MatBlock* data_d = this->_data_d.data();
785
786 // loop over all rows
787 for(IT_ i(0); i < this->_n; ++i)
788 {
789 // get row-end pointers of L and U
790 const IT_ ql = rptr_l[i+1];
791 const IT_ qu = rptr_u[i+1];
792
793 // loop over row i of L
794 for(IT_ j(rptr_l[i]); j < rptr_l[i+1]; ++j)
795 {
796 // get column index of L_ij
797 const IT_ cj = cidx_l[j];
798
799 // get L/U pointers
800 IT_ pl = j;
801 IT_ pu = rptr_u[i];
802
803 // update L_ij <- D_jj^{-1} * L_ij
804 {
805 //data_l[j] *= data_d[cj];
806 const MatBlock l_ij(data_l[j]);
807 data_l[j].set_mat_mat_mult(data_d[cj], l_ij);
808 }
809
810 // loop over row j of U and process row i of L
811 IT_ k(rptr_u[cj]);
812 for(; k < rptr_u[cj+1]; ++k)
813 {
814 const IT_ ck = cidx_u[k];
815 if(ck >= i)
816 break;
817 for(; (pl < ql) && (cidx_l[pl] <= ck); ++pl)
818 {
819 if(cidx_l[pl] == ck)
820 //data_l[pl] -= data_l[j] * data_u[k];
821 data_l[pl].add_mat_mat_mult(data_l[j], data_u[k], -DT_(1));
822 }
823 }
824
825 // process main diagonal entry
826 if((k < rptr_u[cj+1]) && (cidx_u[k] == i))
827 {
828 //data_d[i] -= data_l[j] * data_u[k];
829 data_d[i].add_mat_mat_mult(data_l[j], data_u[k], -DT_(1));
830 ++k;
831 }
832
833 // loop over row j of U and process row i of U
834 for(; k < rptr_u[cj+1]; ++k)
835 {
836 const IT_ ck = cidx_u[k];
837 for(; (pu < qu) && (cidx_u[pu] <= ck); ++pu)
838 {
839 if(cidx_u[pu] == ck)
840 //data_u[pu] -= data_l[j] * data_u[k];
841 data_u[pu].add_mat_mat_mult(data_l[j], data_u[k], -DT_(1));
842 }
843 }
844 }
845
846 // invert main diagonal entry
847 {
848 //data_d[i] = DT_(1) / data_d[i];
849 const MatBlock d_ii(data_d[i]);
850 data_d[i].set_inverse(d_ii);
851 }
852 }
853 }
854
867 void solve_il(VecBlock* x, const VecBlock* b) const
868 {
869 const IT_* rptr = this->_row_ptr_l.data();
870 const IT_* cidx = (this->_col_idx_l.empty() ? nullptr : this->_col_idx_l.data());
871 const MatBlock* data_l = (this->_data_l.empty() ? nullptr : this->_data_l.data());
872
873 for(IT_ i(0); i < this->_n; ++i)
874 {
875 VecBlock r(b[i]);
876 for(IT_ j(rptr[i]); j < rptr[i+1]; ++j)
877 {
878 //r -= data_l[j] * x[cidx[j]];
879 r.add_mat_vec_mult(data_l[j], x[cidx[j]], -DT_(1));
880 }
881 x[i] = r;
882 }
883 }
884
897 void solve_du(VecBlock* x, const VecBlock* b) const
898 {
899 const IT_* rptr = this->_row_ptr_u.data();
900 const IT_* cidx = (this->_col_idx_u.empty() ? nullptr : this->_col_idx_u.data());
901 const MatBlock* data_u = (this->_data_u.empty() ? nullptr : this->_data_u.data());
902 const MatBlock* data_d = this->_data_d.data();
903
904 for(IT_ i(this->_n); i > IT_(0); )
905 {
906 --i;
907 VecBlock r(b[i]);
908 for(IT_ j(rptr[i]); j < rptr[i+1]; ++j)
909 {
910 //r -= data_u[j] * x[cidx[j]];
911 r.add_mat_vec_mult(data_u[j], x[cidx[j]], -DT_(1));
912 }
913 //x[i] = data_d[i] * r;
914 x[i].set_mat_vec_mult(data_d[i], r);
915 }
916 }
917 }; // class ILUCoreBlocked
918 } // namespace Intern
920
935 template<typename Matrix_>
937 {
938 public:
939 typedef typename Matrix_::DataType DataType;
940 typedef typename Matrix_::VectorTypeL VectorType;
941
942 virtual void set_fill_in_param(int p) = 0;
943
944 virtual void init_symbolic() = 0;
945
946 virtual void done_symbolic() = 0;
947
948 virtual void init_numeric() = 0;
949
950 virtual String name() const = 0;
951
952 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) = 0;
953
954 virtual ~ILUPrecondBase() {}
955 }; // ILUPrecondBase class
956
965 template<PreferredBackend backend_, typename Matrix_, typename Filter_>
967
975 template<typename DT_, typename IT_, typename Filter_>
977 public ILUPrecondBase<typename LAFEM::SparseMatrixCSR<DT_, IT_>>
978 {
979 public:
981 typedef DT_ DataType;
982 typedef IT_ IndexType;
983 typedef Filter_ FilterType;
984 typedef typename MatrixType::VectorTypeL VectorType;
985
986 protected:
987 const MatrixType& _matrix;
988 const FilterType& _filter;
989 Intern::ILUCoreScalar<DataType, IndexType> _ilu;
990 int _p;
991
992 public:
1002 explicit ILUPrecondWithBackend(const MatrixType& matrix, const FilterType& filter, const int p = 0) :
1003 _matrix(matrix),
1004 _filter(filter),
1005 _p(p)
1006 {
1007 }
1008
1009 explicit ILUPrecondWithBackend(const String& section_name, const PropertyMap* section,
1010 const MatrixType& matrix, const FilterType& filter) :
1011 _matrix(matrix),
1012 _filter(filter),
1013 _p(-1)
1014 {
1015 auto fill_in_param_p = section->query("fill_in_param");
1016 if(fill_in_param_p.second && !fill_in_param_p.first.parse(_p))
1017 throw ParseError(section_name + ".fill_in_param", fill_in_param_p.first, "a non-negative integer");
1018 }
1019
1024 {
1025 }
1026
1033 virtual void set_fill_in_param(int p) override
1034 {
1035 XASSERT(p > 0);
1036 _p = p;
1037 }
1038
1040 virtual String name() const override
1041 {
1042 return "ILU";
1043 }
1044
1045 virtual void init_symbolic() override
1046 {
1047 if (_matrix.columns() != _matrix.rows())
1048 {
1049 XABORTM("Matrix is not square!");
1050 }
1051
1052 // set matrix structure
1053 _ilu.set_struct(_matrix);
1054
1055 // perform symbolic factorization
1056 _ilu.factorize_symbolic(_p);
1057
1058 // allocate data arrays
1059 _ilu.alloc_data();
1060 }
1061
1062 virtual void done_symbolic() override
1063 {
1064 _ilu.clear();
1065 }
1066
1067 virtual void init_numeric() override
1068 {
1069 _ilu.copy_data(_matrix);
1070 _ilu.factorize_numeric_il_du();
1071 }
1072
1079 virtual Status apply(VectorType& out, const VectorType& in) override
1080 {
1081 TimeStamp ts_start;
1082
1083 // get vector data arrays
1084 DataType* x = out.elements();
1085 const DataType* b = in.elements();
1086
1087 // solve: (I+L)*y = b
1088 _ilu.solve_il(x, b);
1089
1090 // solve: (D+U)*x = y
1091 _ilu.solve_du(x, x);
1092
1093 // apply filter
1094 this->_filter.filter_cor(out);
1095
1096 TimeStamp ts_stop;
1097 Statistics::add_time_precon(ts_stop.elapsed(ts_start));
1098 Statistics::add_flops(_ilu.get_nnze() * 2 + out.size());
1099
1100 return Status::success;
1101 }
1102 }; // class ILUPrecondWithBackend<generic, SparseMatrixCSR,...>
1103
1109 template<typename DT_, typename IT_, int dim_, typename Filter_>
1111 public ILUPrecondBase<typename LAFEM::SparseMatrixBCSR<DT_, IT_, dim_, dim_>>
1112 {
1113 public:
1115 typedef DT_ DataType;
1116 typedef IT_ IndexType;
1117 typedef Filter_ FilterType;
1118 typedef typename MatrixType::VectorTypeL VectorType;
1119
1120 protected:
1121 const MatrixType& _matrix;
1122 const FilterType& _filter;
1123 Intern::ILUCoreBlocked<DataType, IndexType, dim_> _ilu;
1124 int _p;
1125
1126 public:
1136 explicit ILUPrecondWithBackend(const MatrixType& matrix, const FilterType& filter, const int p = 0) :
1137 _matrix(matrix),
1138 _filter(filter),
1139 _p(p)
1140 {
1141 }
1142
1143 explicit ILUPrecondWithBackend(const String& section_name, const PropertyMap* section,
1144 const MatrixType& matrix, const FilterType& filter) :
1145 _matrix(matrix),
1146 _filter(filter),
1147 _p(-1)
1148 {
1149 auto fill_in_param_p = section->query("fill_in_param");
1150 if(fill_in_param_p.second && !fill_in_param_p.first.parse(_p))
1151 throw ParseError(section_name + ".fill_in_param", fill_in_param_p.first, "a non-negative integer");
1152 }
1153
1158 {
1159 }
1160
1167 virtual void set_fill_in_param(int p) override
1168 {
1169 XASSERT(p > 0);
1170 _p = p;
1171 }
1172
1174 virtual String name() const override
1175 {
1176 return "ILU";
1177 }
1178
1179 virtual void init_symbolic() override
1180 {
1181 if (_matrix.columns() != _matrix.rows())
1182 {
1183 XABORTM("Matrix is not square!");
1184 }
1185
1186 // set matrix structure
1187 _ilu.set_struct(_matrix);
1188
1189 // perform symbolic factorization
1190 _ilu.factorize_symbolic(_p);
1191
1192 // allocate data arrays
1193 _ilu.alloc_data();
1194 }
1195
1196 virtual void done_symbolic() override
1197 {
1198 _ilu.clear();
1199 }
1200
1201 virtual void init_numeric() override
1202 {
1203 _ilu.copy_data(_matrix);
1204 _ilu.factorize_numeric_il_du();
1205 }
1206
1213 virtual Status apply(VectorType& out, const VectorType& in) override
1214 {
1215 TimeStamp ts_start;
1216
1217 // get vector data arrays
1218 auto* x = out.elements();
1219 const auto* b = in.elements();
1220
1221 // solve: (I+L)*y = b
1222 _ilu.solve_il(x, b);
1223
1224 // solve: (D+U)*x = y
1225 _ilu.solve_du(x, x);
1226
1227 // apply filter
1228 this->_filter.filter_cor(out);
1229
1230 TimeStamp ts_stop;
1231 Statistics::add_time_precon(ts_stop.elapsed(ts_start));
1232 Statistics::add_flops(_ilu.get_nnze() * 2 + out.size());
1233
1234 return Status::success;
1235 }
1236 }; // class ILUPrecondWithBackend<generic, SparseMatrixBCSR<...>,...>
1237
1238#ifdef FEAT_HAVE_CUDA
1252 template<typename Filter_>
1253 class ILUPrecondWithBackend<PreferredBackend::cuda, LAFEM::SparseMatrixCSR<double, unsigned int>, Filter_> :
1254 public ILUPrecondBase<LAFEM::SparseMatrixCSR<double, unsigned int>>
1255 {
1256 public:
1258 typedef Filter_ FilterType;
1259 typedef typename MatrixType::VectorTypeL VectorType;
1260 typedef typename MatrixType::DataType DataType;
1261
1262 protected:
1263 const MatrixType& _matrix;
1264 MatrixType _lu_matrix;
1265 const FilterType& _filter;
1266 void * cuda_info;
1267
1268 public:
1280 explicit ILUPrecondWithBackend(const MatrixType& matrix, const FilterType& filter, const int = 0) :
1281 _matrix(matrix),
1282 _filter(filter)
1283 {
1284 }
1285
1286 explicit ILUPrecondWithBackend(const String& section_name, const PropertyMap* section,
1287 const MatrixType& matrix, const FilterType& filter) :
1288 _matrix(matrix),
1289 _filter(filter)
1290 {
1291 // Check for _p
1292 auto fill_in_param_p = section->query("fill_in_param");
1293 if(fill_in_param_p.second)
1294 {
1295 XASSERTM(std::stoi(fill_in_param_p.first) == 0, "For PreferredBackend::cuda, the fill in parameter has to be == 0!");
1296 }
1297 }
1298
1302 virtual ~ILUPrecondWithBackend()
1303 {
1304 }
1305
1312 virtual void set_fill_in_param(int p) override
1313 {
1314 XASSERTM(p == 0, "For PreferredBackend::cuda, the fill in parameter has to be == 0!");
1315 }
1316
1318 virtual String name() const override
1319 {
1320 return "ILU";
1321 }
1322
1323 virtual void init_symbolic() override
1324 {
1325 if (_matrix.columns() != _matrix.rows())
1326 {
1327 XABORTM("Matrix is not square!");
1328 }
1329
1330 _lu_matrix.clone(_matrix, LAFEM::CloneMode::Layout);
1331
1332 cuda_info = Intern::cuda_ilu_init_symbolic(
1333 (int)_lu_matrix.rows(),
1334 (int)_lu_matrix.used_elements(),
1335 _lu_matrix.val(),
1336 (int*)_lu_matrix.row_ptr(),
1337 (int*)_lu_matrix.col_ind());
1338 }
1339
1340 virtual void done_symbolic() override
1341 {
1342 Intern::cuda_ilu_done_symbolic(cuda_info);
1343 }
1344
1345 virtual void init_numeric() override
1346 {
1347 _lu_matrix.copy(_matrix);
1348
1349 Intern::cuda_ilu_init_numeric(
1350 _lu_matrix.val(),
1351 (int*)_lu_matrix.row_ptr(),
1352 (int*)_lu_matrix.col_ind(),
1353 cuda_info);
1354 }
1355
1356 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) override
1357 {
1358 XASSERTM(_matrix.rows() == vec_cor.size(), "matrix / vector size mismatch!");
1359 XASSERTM(_matrix.rows() == vec_def.size(), "matrix / vector size mismatch!");
1360
1361 TimeStamp ts_start;
1362
1363 int status = Intern::cuda_ilu_apply(
1364 vec_cor.elements(),
1365 vec_def.elements(),
1366 _lu_matrix.val(),
1367 (int*)_lu_matrix.row_ptr(),
1368 (int*)_lu_matrix.col_ind(),
1369 cuda_info);
1370
1371 this->_filter.filter_cor(vec_cor);
1372
1373 TimeStamp ts_stop;
1374 Statistics::add_time_precon(ts_stop.elapsed(ts_start));
1375 Statistics::add_flops(_matrix.used_elements() * 2 + vec_cor.size());
1376
1377 return (status == 0) ? Status::success : Status::aborted;
1378 }
1379 }; // class ILUPrecondWithBackend<cuda, SparseMatrixCSR<...>,...>
1380
1381 /*
1382 template<typename Filter_>
1383 class ILUPrecond<LAFEM::SparseMatrixCSR<Mem::CUDA, float, unsigned int>, Filter_> :
1384 public SolverBase<LAFEM::SparseMatrixCSR<Mem::CUDA, float, unsigned int>::VectorTypeL>
1385 {
1386 public:
1387 typedef LAFEM::SparseMatrixCSR<Mem::CUDA, float, unsigned int> MatrixType;
1388 typedef typename MatrixType::VectorTypeL VectorType;
1389 typedef Filter_ FilterType;
1390
1391 explicit ILUPrecond(const MatrixType&, const FilterType&, const int = 0)
1392 {
1393 }
1394
1395 Status apply(VectorType &, const VectorType &) override
1396 {
1397 XABORTM("not implemented yet!");
1398 }
1399
1400 String name() const override
1401 {
1402 XABORTM("not implemented yet!");
1403 }
1404 };
1405
1406 template<typename Filter_>
1407 class ILUPrecond<LAFEM::SparseMatrixCSR<Mem::CUDA, float, unsigned long>, Filter_> :
1408 public SolverBase<LAFEM::SparseMatrixCSR<Mem::CUDA, float, unsigned long>::VectorTypeL>
1409 {
1410 public:
1411 typedef LAFEM::SparseMatrixCSR<Mem::CUDA, float, unsigned long> MatrixType;
1412 typedef typename MatrixType::VectorTypeL VectorType;
1413 typedef Filter_ FilterType;
1414
1415 explicit ILUPrecond(const MatrixType&, const FilterType&, const int = 0)
1416 {
1417 }
1418
1419 Status apply(VectorType &, const VectorType &) override
1420 {
1421 XABORTM("not implemented yet!");
1422 }
1423
1424 String name() const override
1425 {
1426 XABORTM("not implemented yet!");
1427 }
1428 };
1429
1430 template<typename Filter_>
1431 class ILUPrecond<LAFEM::SparseMatrixCSR<Mem::CUDA, double, unsigned long>, Filter_> :
1432 public SolverBase<LAFEM::SparseMatrixCSR<Mem::CUDA, double, unsigned long>::VectorTypeL>
1433 {
1434 public:
1435 typedef LAFEM::SparseMatrixCSR<Mem::CUDA, double, unsigned long> MatrixType;
1436 typedef typename MatrixType::VectorTypeL VectorType;
1437 typedef Filter_ FilterType;
1438
1439 explicit ILUPrecond(const MatrixType&, const FilterType&, const int = 0)
1440 {
1441 }
1442
1443 Status apply(VectorType &, const VectorType &) override
1444 {
1445 XABORTM("not implemented yet!");
1446 }
1447
1448 String name() const override
1449 {
1450 XABORTM("not implemented yet!");
1451 }
1452 };*/
1453
1467 template<typename Filter_, int blocksize_>
1468 class ILUPrecondWithBackend<PreferredBackend::cuda, LAFEM::SparseMatrixBCSR<double, unsigned int, blocksize_, blocksize_>, Filter_> :
1469 public ILUPrecondBase<typename LAFEM::SparseMatrixBCSR<double, unsigned int, blocksize_, blocksize_>>
1470 {
1471 public:
1472 typedef LAFEM::SparseMatrixBCSR<double, unsigned int, blocksize_, blocksize_> MatrixType;
1473 typedef Filter_ FilterType;
1474 typedef typename MatrixType::VectorTypeL VectorType;
1475 typedef typename MatrixType::DataType DataType;
1476
1477 protected:
1478 const MatrixType& _matrix;
1479 MatrixType _lu_matrix;
1480 const FilterType& _filter;
1481 void * cuda_info;
1482
1483 public:
1495 explicit ILUPrecondWithBackend(const MatrixType& matrix, const FilterType& filter, const int = 0) :
1496 _matrix(matrix),
1497 _filter(filter)
1498 {
1499 }
1500
1517 explicit ILUPrecondWithBackend(const String& section_name, const PropertyMap* section,
1518 const MatrixType& matrix, const FilterType& filter) :
1519 _matrix(matrix),
1520 _filter(filter)
1521 {
1522 // Check for _p
1523 auto fill_in_param_p = section->query("fill_in_param");
1524 if(fill_in_param_p.second)
1525 {
1526 XASSERTM(std::stoi(fill_in_param_p.first) == 0, "For PreferredBackend::cuda, the fill in parameter has to be == 0!");
1527 }
1528 }
1529
1533 virtual ~ILUPrecondWithBackend()
1534 {
1535 }
1536
1543 virtual void set_fill_in_param(int p) override
1544 {
1545 XASSERTM(p == 0, "For PreferredBackend::cuda, the fill in parameter has to be == 0!");
1546 }
1547
1549 virtual String name() const override
1550 {
1551 return "ILU";
1552 }
1553
1554 virtual void init_symbolic() override
1555 {
1556 if (_matrix.columns() != _matrix.rows())
1557 {
1558 XABORTM("Matrix is not square!");
1559 }
1560
1561 _lu_matrix.clone(_matrix, LAFEM::CloneMode::Layout);
1562
1563 cuda_info = Intern::cuda_ilub_init_symbolic(
1564 (int)_lu_matrix.rows(),
1565 (int)_lu_matrix.used_elements(),
1566 _lu_matrix.template val<LAFEM::Perspective::pod>(),
1567 (int*)_lu_matrix.row_ptr(),
1568 (int*)_lu_matrix.col_ind(),
1569 blocksize_);
1570 }
1571
1572 virtual void done_symbolic() override
1573 {
1574 Intern::cuda_ilub_done_symbolic(cuda_info);
1575 }
1576
1577 virtual void init_numeric() override
1578 {
1579 _lu_matrix.copy(_matrix);
1580
1581 Intern::cuda_ilub_init_numeric(_lu_matrix.template val<LAFEM::Perspective::pod>(), (int*)_lu_matrix.row_ptr(), (int*)_lu_matrix.col_ind(), cuda_info);
1582 }
1583
1584 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) override
1585 {
1586 XASSERTM(_matrix.rows() == vec_cor.size(), "matrix / vector size mismatch!");
1587 XASSERTM(_matrix.rows() == vec_def.size(), "matrix / vector size mismatch!");
1588
1589 TimeStamp ts_start;
1590
1591 int status = Intern::cuda_ilub_apply(
1592 vec_cor.template elements<LAFEM::Perspective::pod>(),
1593 vec_def.template elements<LAFEM::Perspective::pod>(),
1594 _lu_matrix.template val<LAFEM::Perspective::pod>(),
1595 (int*)_lu_matrix.row_ptr(),
1596 (int*)_lu_matrix.col_ind(),
1597 cuda_info);
1598
1599 this->_filter.filter_cor(vec_cor);
1600
1601 TimeStamp ts_stop;
1602 Statistics::add_time_precon(ts_stop.elapsed(ts_start));
1603 Statistics::add_flops(_matrix.used_elements() * 2 + vec_cor.size());
1604
1605 return (status == 0) ? Status::success : Status::aborted;
1606 }
1607 }; // class ILUPrecondWithBackend<cuda, SparseMatrixBCSR<...>,...>
1608#endif //FEAT_HAVE_CUDA
1609
1611 template<PreferredBackend backend_, typename Matrix_, typename Filter_>
1613 public ILUPrecondBase<Matrix_>
1614 {
1615 public:
1616
1617 explicit ILUPrecondWithBackend(const Matrix_&, const Filter_&, const int = 0)
1618 {
1619 }
1620
1621 explicit ILUPrecondWithBackend(const String& , const PropertyMap*, const Matrix_& , const Filter_& )
1622 {
1623 }
1624
1625 virtual Status apply(typename Matrix_::VectorTypeL &, const typename Matrix_::VectorTypeL &) override
1626 {
1627 XABORTM("not implemented yet!");
1628 }
1629
1630 virtual String name() const override
1631 {
1632 XABORTM("not implemented yet!");
1633 }
1634
1635 virtual void init_symbolic() override
1636 {
1637 XABORTM("not implemented yet!");
1638 }
1639
1640 virtual void done_symbolic() override
1641 {
1642 XABORTM("not implemented yet!");
1643 }
1644
1645 virtual void set_fill_in_param(int /*p*/) override
1646 {
1647 XABORTM("not implemented yet!");
1648 }
1649
1650 virtual void init_numeric() override
1651 {
1652 XABORTM("not implemented yet!");
1653 }
1654 };
1655
1667 template<typename Matrix_, typename Filter_>
1668 class ILUPrecond : public SolverBase<typename Matrix_::VectorTypeL>
1669 {
1670 private:
1671 std::shared_ptr<ILUPrecondBase<Matrix_>> _impl;
1672
1673 public:
1674 typedef Matrix_ MatrixType;
1675 typedef Filter_ FilterType;
1676 typedef typename MatrixType::VectorTypeL VectorType;
1677 typedef typename MatrixType::DataType DataType;
1678
1681
1682 public:
1699 ILUPrecond(PreferredBackend backend, const MatrixType& matrix, const FilterType& filter, const int p = 0)
1700 {
1701 switch (backend)
1702 {
1704 _impl = std::make_shared<ILUPrecondWithBackend<PreferredBackend::cuda, Matrix_, Filter_>>(matrix, filter);
1705 break;
1708 default:
1709 _impl = std::make_shared<ILUPrecondWithBackend<PreferredBackend::generic, Matrix_, Filter_>>(matrix, filter, p);
1710 }
1711 }
1712
1732 ILUPrecond(const String& section_name, const PropertyMap* section, PreferredBackend backend, const MatrixType& matrix, const FilterType& filter) :
1733 BaseClass(section_name, section)
1734 {
1735 switch (backend)
1736 {
1738 _impl = std::make_shared<ILUPrecondWithBackend<PreferredBackend::cuda, Matrix_, Filter_>>(section_name, section, matrix, filter);
1739 break;
1742 default:
1743 _impl = std::make_shared<ILUPrecondWithBackend<PreferredBackend::generic, Matrix_, Filter_>>(section_name, section, matrix, filter);
1744 }
1745 }
1746
1750 virtual ~ILUPrecond()
1751 {
1752 }
1753
1755 virtual String name() const override
1756 {
1757 return _impl->name();
1758 }
1759
1766 virtual void set_fill_in_param(int p)
1767 {
1768 _impl->set_fill_in_param(p);
1769 }
1770
1777 virtual Status apply(VectorType& vec_cor, const VectorType& vec_def) override
1778 {
1779 return _impl->apply(vec_cor, vec_def);
1780 }
1781
1782 virtual void init_symbolic() override
1783 {
1784 _impl->init_symbolic();
1785 }
1786
1787 virtual void done_symbolic() override
1788 {
1789 _impl->done_symbolic();
1790 }
1791
1792 virtual void init_numeric() override
1793 {
1794 _impl->init_numeric();
1795 }
1796 }; // class ILUPrecond
1797
1816 template<typename Matrix_, typename Filter_>
1817 inline std::shared_ptr<ILUPrecond<Matrix_, Filter_>> new_ilu_precond(PreferredBackend backend,
1818 const Matrix_& matrix, const Filter_& filter, const int p = 0)
1819 {
1820 return std::make_shared<ILUPrecond<Matrix_, Filter_>>(backend, matrix, filter, p);
1821 }
1822
1844 template<typename Matrix_, typename Filter_>
1845 inline std::shared_ptr<ILUPrecond<Matrix_, Filter_>> new_ilu_precond(
1846 const String& section_name, const PropertyMap* section, PreferredBackend backend,
1847 const Matrix_& matrix, const Filter_& filter)
1848 {
1849 return std::make_shared<ILUPrecond<Matrix_, Filter_>>(section_name, section, backend, matrix, filter);
1850 }
1851 } // namespace Solver
1852} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Index size() const
Returns the containers size.
Definition: container.hpp:1136
DT_ * elements()
Get a pointer to the data array.
CSR based blocked sparse matrix.
Intern::BCSRVectorHelper< DT_, IT_, BlockHeight_ >::VectorType VectorTypeL
Compatible L-vector type.
Index rows() const
Retrieve matrix row count.
Index columns() const
Retrieve matrix column count.
CSR based sparse matrix.
Index rows() const
Retrieve matrix row count.
Index columns() const
Retrieve matrix column count.
Class for parser related errors.
Definition: exception.hpp:132
A class organizing a tree of key-value pairs.
std::pair< String, bool > query(String key_path) const
Queries a value by its key path.
Inheritances inside ilu_precond.hpp.
ILU(0) and ILU(p) preconditioner implementation.
ILUPrecond(const String &section_name, const PropertyMap *section, PreferredBackend backend, const MatrixType &matrix, const FilterType &filter)
Constructor using a PropertyMap.
virtual ~ILUPrecond()
Empty virtual destructor.
ILUPrecond(PreferredBackend backend, const MatrixType &matrix, const FilterType &filter, const int p=0)
Constructor.
SolverBase< VectorType > BaseClass
Our base class.
virtual void init_numeric() override
Numeric initialization method.
virtual Status apply(VectorType &vec_cor, const VectorType &vec_def) override
apply the preconditioner
virtual void set_fill_in_param(int p)
Sets the fill-in parameter.
virtual void done_symbolic() override
Symbolic finalization method.
virtual void init_symbolic() override
Symbolic initialization method.
virtual String name() const override
Returns the name of the solver.
ILUPrecondWithBackend(const MatrixType &matrix, const FilterType &filter, const int p=0)
Constructor.
virtual Status apply(VectorType &out, const VectorType &in) override
apply the preconditioner
virtual Status apply(VectorType &out, const VectorType &in) override
apply the preconditioner
ILUPrecondWithBackend(const MatrixType &matrix, const FilterType &filter, const int p=0)
Constructor.
ILU(0) and ILU(p) preconditioner internal implementation.
Polymorphic solver interface.
Definition: base.hpp:183
static void add_flops(Index flops)
Add an amount of flops to the global flop counter.
Definition: statistics.hpp:206
String class implementation.
Definition: string.hpp:46
Time stamp class.
Definition: time_stamp.hpp:54
double elapsed(const TimeStamp &before) const
Calculates the time elapsed between two time stamps.
Definition: time_stamp.hpp:100
Status
Solver status return codes enumeration.
Definition: base.hpp:47
@ success
solving successful (convergence criterion fulfilled)
@ aborted
premature abort (solver aborted due to internal errors or preconditioner failure)
std::shared_ptr< ILUPrecond< Matrix_, Filter_ > > new_ilu_precond(PreferredBackend backend, const Matrix_ &matrix, const Filter_ &filter, const int p=0)
Creates a new ILUPrecond solver object.
FEAT namespace.
Definition: adjactor.hpp:12
PreferredBackend
The backend that shall be used in all compute heavy calculations.
Definition: backend.hpp:124