71 #ifndef GMM_PRECOND_ILU_H
72 #define GMM_PRECOND_ILU_H
84 template <
typename Matrix>
88 typedef typename linalg_traits<Matrix>::value_type value_type;
89 typedef csr_matrix_ref<value_type *, size_type *, size_type *, 0> tm_type;
94 std::vector<value_type> L_val, U_val;
95 std::vector<size_type> L_ind, U_ind, L_ptr, U_ptr;
97 template<
typename M>
void do_ilu(
const M& A, row_major);
98 void do_ilu(
const Matrix& A, col_major);
102 size_type nrows()
const {
return mat_nrows(L); }
103 size_type ncols()
const {
return mat_ncols(U); }
105 void build_with(
const Matrix& A) {
107 L_ptr.resize(mat_nrows(A)+1);
108 U_ptr.resize(mat_nrows(A)+1);
109 do_ilu(A,
typename principal_orientation_type<
typename
110 linalg_traits<Matrix>::sub_orientation>::potype());
114 size_type memsize()
const {
115 return sizeof(*this) +
116 (L_val.size()+U_val.size()) *
sizeof(value_type) +
117 (L_ind.size()+L_ptr.size()) *
sizeof(size_type) +
118 (U_ind.size()+U_ptr.size()) *
sizeof(size_type);
122 template <
typename Matrix>
template <
typename M>
124 typedef typename linalg_traits<Matrix>::storage_type store_type;
125 typedef value_type T;
126 typedef typename number_traits<T>::magnitude_type R;
128 size_type L_loc = 0, U_loc = 0, n = mat_nrows(A), i, j, k;
130 L_ptr[0] = 0; U_ptr[0] = 0;
131 R prec = default_tol(R());
132 R max_pivot = gmm::abs(A(0,0)) * prec;
134 for (
int count = 0; count < 2; ++count) {
136 L_val.resize(L_loc); L_ind.resize(L_loc);
137 U_val.resize(U_loc); U_ind.resize(U_loc);
140 for (i = 0; i < n; ++i) {
141 typedef typename linalg_traits<M>::const_sub_row_type row_type;
142 row_type row = mat_const_row(A, i);
143 typename linalg_traits<typename org_type<row_type>::t>::const_iterator
144 it = vect_const_begin(row), ite = vect_const_end(row);
152 for (k = 0; it != ite && k < 1000; ++it, ++k) {
155 j = index_of_it(it, k, store_type());
163 if (count) U_val[U_loc-1] = *it;
177 if (A(0,0) == T(0)) {
178 U_val[U_ptr[0]] = T(1);
179 GMM_WARNING2(
"pivot 0 is too small");
183 for (i = 1; i < n; i++) {
186 if (gmm::abs(U_val[pn]) <= max_pivot) {
188 GMM_WARNING2(
"pivot " << i <<
" is too small");
190 max_pivot = std::max(max_pivot,
191 std::min(gmm::abs(U_val[pn]) * prec, R(1)));
193 for (j = L_ptr[i]; j < L_ptr[i+1]; j++) {
194 pn = U_ptr[L_ind[j]];
196 T multiplier = (L_val[j] /= U_val[pn]);
201 for (pn++; pn < U_ptr[L_ind[j]+1] && U_ind[pn] < i; pn++) {
202 while (qn < L_ptr[i+1] && L_ind[qn] < U_ind[pn])
204 if (qn < L_ptr[i+1] && U_ind[pn] == L_ind[qn])
205 L_val[qn] -= multiplier * U_val[pn];
207 for (; pn < U_ptr[L_ind[j]+1]; pn++) {
208 while (rn < U_ptr[i+1] && U_ind[rn] < U_ind[pn])
210 if (rn < U_ptr[i+1] && U_ind[pn] == U_ind[rn])
211 U_val[rn] -= multiplier * U_val[pn];
216 L = tm_type(&(L_val[0]), &(L_ind[0]), &(L_ptr[0]), n, mat_ncols(A));
217 U = tm_type(&(U_val[0]), &(U_ind[0]), &(U_ptr[0]), n, mat_ncols(A));
220 template <
typename Matrix>
221 void ilu_precond<Matrix>::do_ilu(
const Matrix& A, col_major) {
222 do_ilu(gmm::transposed(A), row_major());
226 template <
typename Matrix,
typename V1,
typename V2>
inline
227 void mult(
const ilu_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
230 gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
231 gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
234 gmm::lower_tri_solve(P.L, v2,
true);
235 gmm::upper_tri_solve(P.U, v2,
false);
239 template <
typename Matrix,
typename V1,
typename V2>
inline
240 void transposed_mult(
const ilu_precond<Matrix>& P,
const V1 &v1,V2 &v2) {
243 gmm::lower_tri_solve(P.L, v2,
true);
244 gmm::upper_tri_solve(P.U, v2,
false);
247 gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
248 gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
252 template <
typename Matrix,
typename V1,
typename V2>
inline
253 void left_mult(
const ilu_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
255 if (P.invert) gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
256 else gmm::lower_tri_solve(P.L, v2,
true);
259 template <
typename Matrix,
typename V1,
typename V2>
inline
260 void right_mult(
const ilu_precond<Matrix>& P,
const V1 &v1, V2 &v2) {
262 if (P.invert) gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
263 else gmm::upper_tri_solve(P.U, v2,
false);
266 template <
typename Matrix,
typename V1,
typename V2>
inline
267 void transposed_left_mult(
const ilu_precond<Matrix>& P,
const V1 &v1,
270 if (P.invert) gmm::upper_tri_solve(P.U, v2,
false);
271 else gmm::upper_tri_solve(gmm::transposed(P.L), v2,
true);
274 template <
typename Matrix,
typename V1,
typename V2>
inline
275 void transposed_right_mult(
const ilu_precond<Matrix>& P,
const V1 &v1,
278 if (P.invert) gmm::lower_tri_solve(P.L, v2,
true);
279 else gmm::lower_tri_solve(gmm::transposed(P.U), v2,
false);
Incomplete LU without fill-in Preconditioner.
void copy(const L1 &l1, L2 &l2)
*/
void mult(const L1 &l1, const L2 &l2, L3 &l3)
*/
size_t size_type
used as the common size type in the library