72 #ifndef GMM_PRECOND_ILU_H
73 #define GMM_PRECOND_ILU_H
85 template <
typename Matrix>
89 typedef typename linalg_traits<Matrix>::value_type value_type;
90 typedef csr_matrix_ref<value_type *, size_type *, size_type *, 0> tm_type;
95 std::vector<value_type> L_val, U_val;
96 std::vector<size_type> L_ind, U_ind, L_ptr, U_ptr;
98 template<
typename M>
void do_ilu(
const M& A, row_major);
99 void do_ilu(
const Matrix& A, col_major);
103 size_type nrows(
void)
const {
return mat_nrows(L); }
104 size_type ncols(
void)
const {
return mat_ncols(U); }
106 void build_with(
const Matrix& A) {
108 L_ptr.resize(mat_nrows(A)+1);
109 U_ptr.resize(mat_nrows(A)+1);
110 do_ilu(A,
typename principal_orientation_type<
typename
111 linalg_traits<Matrix>::sub_orientation>::potype());
115 size_type memsize()
const {
116 return sizeof(*this) +
117 (L_val.size()+U_val.size()) *
sizeof(value_type) +
118 (L_ind.size()+L_ptr.size()) *
sizeof(size_type) +
119 (U_ind.size()+U_ptr.size()) *
sizeof(size_type);
123 template <
typename Matrix>
template <
typename M>
125 typedef typename linalg_traits<Matrix>::storage_type store_type;
126 typedef value_type T;
127 typedef typename number_traits<T>::magnitude_type R;
129 size_type L_loc = 0, U_loc = 0, n = mat_nrows(A), i, j, k;
131 L_ptr[0] = 0; U_ptr[0] = 0;
132 R prec = default_tol(R());
133 R max_pivot = gmm::abs(A(0,0)) * prec;
136 for (
int count = 0; count < 2; ++count) {
138 L_val.resize(L_loc); L_ind.resize(L_loc);
139 U_val.resize(U_loc); U_ind.resize(U_loc);
142 for (i = 0; i < n; ++i) {
143 typedef typename linalg_traits<M>::const_sub_row_type row_type;
144 row_type row = mat_const_row(A, i);
145 typename linalg_traits<typename org_type<row_type>::t>::const_iterator
146 it = vect_const_begin(row), ite = vect_const_end(row);
148 if (count) { U_val[U_loc] = T(0); U_ind[U_loc] = i; }
151 for (k = 0; it != ite && k < 1000; ++it, ++k) {
154 j = index_of_it(it, k, store_type());
156 if (count) { L_val[L_loc] = *it; L_ind[L_loc] = j; }
160 if (count) U_val[U_loc-1] = *it;
163 if (count) { U_val[U_loc] = *it; U_ind[U_loc] = j; }
167 L_ptr[i+1] = L_loc; U_ptr[i+1] = U_loc;
171 if (A(0,0) == T(0)) {
172 U_val[U_ptr[0]] = T(1);
173 GMM_WARNING2(
"pivot 0 is too small");
177 for (i = 1; i < n; i++) {
180 if (gmm::abs(U_val[pn]) <= max_pivot) {
182 GMM_WARNING2(
"pivot " << i <<
" is too small");
184 max_pivot = std::max(max_pivot,
185 std::min(gmm::abs(U_val[pn]) * prec, R(1)));
187 for (j = L_ptr[i]; j < L_ptr[i+1]; j++) {
188 pn = U_ptr[L_ind[j]];
190 T multiplier = (L_val[j] /= U_val[pn]);
195 for (pn++; pn < U_ptr[L_ind[j]+1] && U_ind[pn] < i; pn++) {
196 while (qn < L_ptr[i+1] && L_ind[qn] < U_ind[pn])
198 if (qn < L_ptr[i+1] && U_ind[pn] == L_ind[qn])
199 L_val[qn] -= multiplier * U_val[pn];
201 for (; pn < U_ptr[L_ind[j]+1]; pn++) {
202 while (rn < U_ptr[i+1] && U_ind[rn] < U_ind[pn])
204 if (rn < U_ptr[i+1] && U_ind[pn] == U_ind[rn])
205 U_val[rn] -= multiplier * U_val[pn];
210 L = tm_type(&(L_val[0]), &(L_ind[0]), &(L_ptr[0]), n, mat_ncols(A));
211 U = tm_type(&(U_val[0]), &(U_ind[0]), &(U_ptr[0]), n, mat_ncols(A));
214 template <
typename Matrix>
215 void ilu_precond<Matrix>::do_ilu(
const Matrix& A, col_major) {
216 do_ilu(gmm::transposed(A), row_major());
220 template <
typename Matrix,
typename V1,
typename V2>
inline
221 void mult(
const ilu_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
224 gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
225 gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
228 gmm::lower_tri_solve(P.L, v2,
true);
229 gmm::upper_tri_solve(P.U, v2,
false);
233 template <
typename Matrix,
typename V1,
typename V2>
inline
234 void transposed_mult(
const ilu_precond<Matrix>& P,
const V1 &v1,V2 &v2) {
237 gmm::lower_tri_solve(P.L, v2,
true);
238 gmm::upper_tri_solve(P.U, v2,
false);
241 gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
242 gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
246 template <
typename Matrix,
typename V1,
typename V2>
inline
247 void left_mult(
const ilu_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
249 if (P.invert) gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
250 else gmm::lower_tri_solve(P.L, v2,
true);
253 template <
typename Matrix,
typename V1,
typename V2>
inline
254 void right_mult(
const ilu_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
256 if (P.invert) gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
257 else gmm::upper_tri_solve(P.U, v2,
false);
260 template <
typename Matrix,
typename V1,
typename V2>
inline
261 void transposed_left_mult(
const ilu_precond<Matrix>& P,
const V1 &v1,
264 if (P.invert) gmm::upper_tri_solve(P.U, v2,
false);
265 else gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
268 template <
typename Matrix,
typename V1,
typename V2>
inline
269 void transposed_right_mult(
const ilu_precond<Matrix>& P,
const V1 &v1,
272 if (P.invert) gmm::lower_tri_solve(P.L, v2,
true);
273 else gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);