64 #ifndef GMM_PRECOND_ILUT_H
65 #define GMM_PRECOND_ILUT_H
87 template<
typename T>
struct elt_rsvector_value_less_ {
88 inline bool operator()(
const elt_rsvector_<T>& a,
89 const elt_rsvector_<T>& b)
const
90 {
return (gmm::abs(a.e) > gmm::abs(b.e)); }
101 template <
typename Matrix>
104 typedef typename linalg_traits<Matrix>::value_type value_type;
107 typedef row_matrix<_rsvector> LU_Matrix;
116 template<
typename M>
void do_ilut(
const M&, row_major);
117 void do_ilut(
const Matrix&, col_major);
120 void build_with(
const Matrix& A,
int k_ = -1,
double eps_ =
double(-1)) {
122 if (eps_ >=
double(0)) eps = eps_;
126 do_ilut(A,
typename principal_orientation_type<
typename
127 linalg_traits<Matrix>::sub_orientation>::potype());
130 : L(mat_nrows(A), mat_ncols(A)), U(mat_nrows(A), mat_ncols(A)),
131 K(k_), eps(eps_) { build_with(A); }
132 ilut_precond(size_type k_,
double eps_) : K(k_), eps(eps_) {}
134 size_type memsize()
const {
135 return sizeof(*this) + (
nnz(U)+
nnz(L))*
sizeof(value_type);
139 template<
typename Matrix>
template<
typename M>
141 typedef value_type T;
142 typedef typename number_traits<T>::magnitude_type R;
144 size_type n = mat_nrows(A);
146 std::vector<T> indiag(n);
147 _wsvector w(mat_ncols(A));
148 _rsvector ww(mat_ncols(A)), wL(mat_ncols(A)), wU(mat_ncols(A));
151 R prec = default_tol(R());
152 R max_pivot = gmm::abs(A(0,0)) * prec;
154 for (size_type i = 0; i < n; ++i) {
155 gmm::copy(mat_const_row(A, i), w);
158 typename _wsvector::iterator wkold = w.end();
159 for (
typename _wsvector::iterator wk = w.begin();
160 wk != w.end() && wk->first < i; ) {
161 size_type k = wk->first;
162 tmp = (wk->second) * indiag[k];
163 if (gmm::abs(tmp) < eps * norm_row) w.erase(k);
164 else { wk->second += tmp; gmm::add(scaled(mat_row(U, k), -tmp), w); }
165 if (wkold == w.end()) wk = w.begin();
else { wk = wkold; ++wk; }
166 if (wk != w.end() && wk->first == k)
167 {
if (wkold == w.end()) wkold = w.begin();
else ++wkold; ++wk; }
171 if (gmm::abs(tmp) <= max_pivot) {
172 GMM_WARNING2(
"pivot " << i <<
" too small. try with ilutp ?");
176 max_pivot = std::max(max_pivot, std::min(gmm::abs(tmp) * prec, R(1)));
177 indiag[i] = T(1) / tmp;
178 gmm::clean(w, eps * norm_row);
180 std::sort(ww.begin(), ww.end(), elt_rsvector_value_less_<T>());
181 typename _rsvector::const_iterator wit = ww.begin(), wite = ww.end();
184 wL.base_resize(K); wU.base_resize(K+1);
185 typename _rsvector::iterator witL = wL.begin(), witU = wU.begin();
186 for (; wit != wite; ++wit)
187 if (wit->c < i) {
if (nnl < K) { *witL++ = *wit; ++nnl; } }
188 else {
if (nnu < K || wit->c == i) { *witU++ = *wit; ++nnu; } }
189 wL.base_resize(nnl); wU.base_resize(nnu);
190 std::sort(wL.begin(), wL.end());
191 std::sort(wU.begin(), wU.end());
192 gmm::copy(wL, L.row(i));
193 gmm::copy(wU, U.row(i));
198 template<
typename Matrix>
199 void ilut_precond<Matrix>::do_ilut(
const Matrix& A, col_major) {
200 do_ilut(gmm::transposed(A), row_major());
204 template <
typename Matrix,
typename V1,
typename V2>
inline
205 void mult(
const ilut_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
208 gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
209 gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
212 gmm::lower_tri_solve(P.L, v2,
true);
213 gmm::upper_tri_solve(P.U, v2,
false);
217 template <
typename Matrix,
typename V1,
typename V2>
inline
218 void transposed_mult(
const ilut_precond<Matrix>& P,
const V1 &v1,V2 &v2) {
221 gmm::lower_tri_solve(P.L, v2,
true);
222 gmm::upper_tri_solve(P.U, v2,
false);
225 gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
226 gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
230 template <
typename Matrix,
typename V1,
typename V2>
inline
231 void left_mult(
const ilut_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
233 if (P.invert) gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
234 else gmm::lower_tri_solve(P.L, v2,
true);
237 template <
typename Matrix,
typename V1,
typename V2>
inline
238 void right_mult(
const ilut_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
240 if (P.invert) gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
241 else gmm::upper_tri_solve(P.U, v2,
false);
244 template <
typename Matrix,
typename V1,
typename V2>
inline
245 void transposed_left_mult(
const ilut_precond<Matrix>& P,
const V1 &v1,
248 if (P.invert) gmm::upper_tri_solve(P.U, v2,
false);
249 else gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
252 template <
typename Matrix,
typename V1,
typename V2>
inline
253 void transposed_right_mult(
const ilut_precond<Matrix>& P,
const V1 &v1,
256 if (P.invert) gmm::lower_tri_solve(P.L, v2,
true);
257 else gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);