26 #if defined (HAVE_CONFIG_H)
46 template <
typename octave_matrix_t,
typename T>
47 void ilu_0 (octave_matrix_t& sm,
const std::string milu =
"off")
61 else if (milu ==
"col")
76 for (i = 0; i <
n; i++)
80 for (k = 0; k <
n; k++)
86 error (
"ilu: A has a zero on the diagonal");
88 for (j = j1; j < j2; j++)
94 while ((jrow < k) && (j < j2))
98 tl = data[j] / data[uptr[jrow]];
101 for (jj = uptr[jrow] + 1; jj < cidx[jrow+1]; jj++)
106 data[jw] -= tl * data[jj];
108 data[jw] -= data[j] * data[jj];
115 r += data[j] * data[jj];
125 for (jj = uptr[k] + 1; jj < cidx[k+1]; jj++)
126 data[jj] /= data[uptr[k]];
129 error (
"ilu: A has a zero on the diagonal");
132 error (
"ilu: encountered a pivot equal to 0");
134 for (i = j1; i < j2; i++)
139 sm = sm.transpose ();
142 DEFUN (__ilu0__, args, ,
149 if (args.length () != 2)
154 std::string milu = args(1).string_value ();
160 if (! args(0).iscomplex ())
165 ilu_0 <SparseMatrix, double> (sm, milu);
167 retval(0) = speye +
Ftril (
ovl (sm, -1))(0).sparse_matrix_value ();
168 retval(1) =
Ftriu (
ovl (sm))(0).sparse_matrix_value ();
175 ilu_0 <SparseComplexMatrix, Complex> (sm, milu);
178 Ftril (
ovl (sm, -1))(0).sparse_complex_matrix_value ();
179 retval(1) =
Ftriu (
ovl (sm))(0).sparse_complex_matrix_value ();
185 template <
typename octave_matrix_t,
typename T>
187 ilu_crout (octave_matrix_t& sm_l, octave_matrix_t& sm_u,
188 octave_matrix_t& L, octave_matrix_t& U, T *cols_norm,
189 T *rows_norm,
const T droptol = 0,
190 const std::string milu =
"off")
194 enum {OFF, ROW, COL};
197 else if (milu ==
"col")
202 octave_idx_type jrow, i, j, k, jj, total_len_l, total_len_u, max_len_u,
203 max_len_l, w_len_u, w_len_l, cols_list_len, rows_list_len;
206 sm_u = sm_u.transpose ();
208 max_len_u = sm_u.nnz ();
209 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
210 max_len_l = sm_l.nnz ();
211 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
216 T *data_in_u = sm_u.data ();
219 T *data_in_l = sm_l.data ();
247 cidx_u[0] = cidx_in_u[0];
248 cidx_l[0] = cidx_in_l[0];
249 for (i = 0; i <
n; i++)
262 for (k = 0; k <
n; k++)
265 for (i = cidx_in_l[k]; i < cidx_in_l[k+1]; i++)
266 w_data_l[ridx_in_l[i]] = data_in_l[i];
268 for (i = cidx_in_u[k]; i < cidx_in_u[k+1]; i++)
269 w_data_u[ridx_in_u[i]] = data_in_u[i];
272 for (j = 0; j < rows_list_len; j++)
274 if ((Ufirst[rows_list[j]] != -1))
275 for (jj = Ufirst[rows_list[j]]; jj < cidx_u[rows_list[j]+1]; jj++)
278 w_data_u[jrow] -= data_u[jj] * data_l[Lfirst[rows_list[j]]];
282 for (j = 0; j < cols_list_len; j++)
284 if (Lfirst[cols_list[j]] != -1)
285 for (jj = Lfirst[cols_list[j]]; jj < cidx_l[cols_list[j]+1]; jj++)
288 w_data_l[jrow] -= data_l[jj] * data_u[Ufirst[cols_list[j]]];
292 if ((max_len_u - total_len_u) <
n)
294 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
301 if ((max_len_l - total_len_l) <
n)
303 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
312 data_u[total_len_u] = w_data_u[k];
313 ridx_u[total_len_u] = k;
315 for (i = k + 1; i <
n; i++)
317 if (w_data_u[i] != zero)
319 if (std::abs (w_data_u[i]) < (droptol * rows_norm[k]))
322 cr_sum[k] += w_data_u[i];
324 cr_sum[i] += w_data_u[i];
328 data_u[total_len_u + w_len_u] = w_data_u[i];
329 ridx_u[total_len_u + w_len_u] = i;
335 if (w_data_l[i] != zero)
337 if (std::abs (w_data_l[i]) < (droptol * cols_norm[k]))
340 cr_sum[k] += w_data_l[i];
342 cr_sum[i] += w_data_l[i];
346 data_l[total_len_l + w_len_l] = w_data_l[i];
347 ridx_l[total_len_l + w_len_l] = i;
356 if (opt == COL || opt == ROW)
357 data_u[total_len_u] += cr_sum[k];
360 if (data_u[total_len_u] == zero)
361 error (
"ilu: encountered a pivot equal to 0");
364 for (i = total_len_l ; i < (total_len_l + w_len_l); i++)
365 data_l[i] /= data_u[total_len_u];
367 total_len_u += w_len_u;
368 total_len_l += w_len_l;
371 if (total_len_l < 0 || total_len_u < 0)
372 error (
"ilu: integer overflow. Too many fill-in elements in L or U");
374 cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
375 cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
388 Ufirst[k] = cidx_u[k];
392 Lfirst[k] = cidx_l[k];
397 for (i = 0; i <= k; i++)
401 jj = ridx_u[Ufirst[i]];
404 if (Ufirst[i] < (cidx_u[i+1]))
407 if (Ufirst[i] == cidx_u[i+1])
410 jj = ridx_u[Ufirst[i]];
415 cols_list[cols_list_len] = i;
422 jj = ridx_l[Lfirst[i]];
424 if (Lfirst[i] < (cidx_l[i+1]))
427 if (Lfirst[i] == cidx_l[i+1])
430 jj = ridx_l[Lfirst[i]];
434 rows_list[rows_list_len] = i;
443 L = octave_matrix_t (
n,
n, total_len_l);
444 U = octave_matrix_t (
n,
n, total_len_u);
447 for (i = 0; i <=
n; i++)
448 L.cidx (i) = cidx_l[i];
450 for (i = 0; i < total_len_l; i++)
452 L.ridx (i) = ridx_l[i];
453 L.data (i) = data_l[i];
456 for (i = 0; i <=
n; i++)
457 U.cidx (i) = cidx_u[i];
459 for (i = 0; i < total_len_u; i++)
461 U.ridx (i) = ridx_u[i];
462 U.data (i) = data_u[i];
468 DEFUN (__iluc__, args, ,
474 if (args.length () != 3)
477 double droptol = args(1).double_value ();
478 std::string milu = args(2).string_value ();
480 if (! args(0).iscomplex ())
489 ilu_crout <SparseMatrix, double> (sm_l, sm_u, L, U,
496 return ovl (L + speye, U);
507 ilu_crout <SparseComplexMatrix, Complex> (sm_l, sm_u, L, U,
514 return ovl (L + speye, U);
526 template <
typename octave_matrix_t,
typename T>
528 ilu_tp (octave_matrix_t& sm, octave_matrix_t& L, octave_matrix_t& U,
531 const T thresh = T(0),
const std::string milu =
"off",
532 const double udiag = 0)
535 enum {OFF, ROW, COL};
538 else if (milu ==
"col")
547 sm = sm.transpose ();
552 T *data_in = sm.data ();
553 octave_idx_type jrow, i, j, k, jj, c, total_len_l, total_len_u, p_perm,
554 max_ind, max_len_l, max_len_u;
557 T tl = zero, aux, maximum;
560 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
562 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
582 T total_sum, partial_col_sum = zero, partial_row_sum = zero;
583 std::set <octave_idx_type> iw_l;
584 std::set <octave_idx_type> iw_u;
585 std::set <octave_idx_type>::iterator it, it2;
592 cidx_l[0] = cidx_in[0];
593 cidx_u[0] = cidx_in[0];
594 for (i = 0; i <
n; i++)
604 for (k = 0; k <
n; k++)
606 for (j = cidx_in[k]; j < cidx_in[k+1]; j++)
608 p_perm = iperm[ridx_in[j]];
609 w_data[iperm[ridx_in[j]]] = data_in[j];
611 iw_l.insert (ridx_in[j]);
613 iw_u.insert (p_perm);
619 while ((jrow < k) && (it != iw_u.end ()))
622 partial_col_sum = w_data[jrow];
623 if (w_data[jrow] != zero)
627 partial_row_sum = w_data[jrow];
628 tl = w_data[jrow] / data_u[uptr[jrow]];
630 for (jj = cidx_l[jrow]; jj < cidx_l[jrow+1]; jj++)
632 p_perm = iperm[ridx_l[jj]];
633 aux = w_data[p_perm];
636 w_data[p_perm] -= tl * data_l[jj];
637 partial_row_sum += tl * data_l[jj];
641 tl = data_l[jj] * w_data[jrow];
642 w_data[p_perm] -= tl;
644 partial_col_sum += tl;
647 if ((aux == zero) && (w_data[p_perm] != zero))
650 iw_l.insert (ridx_l[jj]);
652 iw_u.insert (p_perm);
658 if ((std::abs (w_data[jrow]) < (droptol * cols_norm[k]))
659 && (w_data[jrow] != zero))
662 total_sum += partial_col_sum;
664 total_sum += partial_row_sum;
683 if ((thresh > zero) && (k < (
n - 1)))
685 maximum = std::abs (w_data[k]) / thresh;
687 for (it = iw_l.begin (); it != iw_l.end (); ++it)
690 if (std::abs (w_data[p_perm]) > maximum)
692 maximum = std::abs (w_data[p_perm]);
698 p_perm = iperm[max_ind];
699 if (max_ind != perm[k])
702 if (w_data[k] != zero)
703 iw_l.insert (perm[k]);
708 iperm[perm[p_perm]] = k;
709 iperm[perm[k]] = p_perm;
711 perm[k] = perm[p_perm];
713 w_data[k] = w_data[p_perm];
714 w_data[p_perm] = aux;
722 while (it != iw_l.end ())
726 if (std::abs (w_data[p_perm]) < (droptol * cols_norm[k]))
729 total_sum += w_data[p_perm];
730 w_data[p_perm] = zero;
744 if ((total_sum > zero) && (w_data[k] == zero))
746 w_data[k] += total_sum;
752 if (w_data[k] == zero)
755 error (
"ilu: encountered a pivot equal to 0");
763 for (it = iw_l.begin (); it != iw_l.end (); ++it)
766 w_data[p_perm] = w_data[p_perm] / w_data[k];
769 if ((max_len_u - total_len_u) <
n)
771 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
778 if ((max_len_l - total_len_l) <
n)
780 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
789 for (it = iw_u.begin (); it != iw_u.end (); ++it)
791 if (w_data[*it] != zero)
793 data_u[total_len_u + w_len_u] = w_data[*it];
794 ridx_u[total_len_u + w_len_u] = *it;
802 for (it = iw_l.begin (); it != iw_l.end (); ++it)
805 if (w_data[p_perm] != zero)
807 data_l[total_len_l + w_len_l] = w_data[p_perm];
808 ridx_l[total_len_l + w_len_l] = *it;
813 total_len_u += w_len_u;
814 total_len_l += w_len_l;
818 if (total_len_l < 0 || total_len_u < 0)
819 error (
"ilu: Integer overflow. Too many fill-in elements in L or U");
822 uptr[k] = total_len_u - 1;
824 cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
825 cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
831 octave_matrix_t *L_ptr;
832 octave_matrix_t *U_ptr;
833 octave_matrix_t diag (
n,
n,
n);
842 L = octave_matrix_t (
n,
n, total_len_u -
n);
843 U = octave_matrix_t (
n,
n, total_len_l);
849 L = octave_matrix_t (
n,
n, total_len_l);
850 U = octave_matrix_t (
n,
n, total_len_u);
853 for (i = 0; i <=
n; i++)
855 L_ptr->cidx (i) = cidx_l[i];
856 U_ptr->cidx (i) = cidx_u[i];
858 U_ptr->cidx (i) -= i;
861 for (i = 0; i <
n; i++)
864 diag.elem (i, i) = data_u[uptr[i]];
867 while (j < cidx_l[i+1])
869 L_ptr->ridx (j) = ridx_l[j];
870 L_ptr->data (j) = data_l[j];
875 while (j < cidx_u[i+1])
891 U_ptr->data (c) = data_u[j];
892 U_ptr->ridx (c) = ridx_u[j];
906 DEFUN (__ilutp__, args, nargout,
913 if (args.length () != 5)
917 double droptol = args(1).double_value ();
918 double thresh = args(2).double_value ();
919 std::string milu = args(3).string_value ();
920 double udiag = args(4).double_value ();
924 if (! args(0).iscomplex ())
928 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_matrix_value ()).nnz ();
929 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_matrix_value ()).nnz ();
937 ilu_tp <SparseMatrix, double> (sm, L, U, nnz_u, nnz_l,
939 perm, droptol, thresh, milu, udiag);
944 retval(0) = L + speye;
969 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_complex_matrix_value ()).nnz ();
970 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_complex_matrix_value ()).nnz ();
978 ilu_tp <SparseComplexMatrix, Complex>
979 (sm, L, U, nnz_u, nnz_l, rc_norm.
fortran_vec (), perm,
985 retval(0) = L + speye;
991 else if (nargout == 2)
1015 OCTAVE_END_NAMESPACE(
octave)
void ilu_0(octave_matrix_t &sm, const std::string milu="off")
void ilu_tp(octave_matrix_t &sm, octave_matrix_t &L, octave_matrix_t &U, octave_idx_type nnz_u, octave_idx_type nnz_l, T *cols_norm, Array< octave_idx_type > &perm_vec, const T droptol=T(0), const T thresh=T(0), const std::string milu="off", const double udiag=0)
void ilu_crout(octave_matrix_t &sm_l, octave_matrix_t &sm_u, octave_matrix_t &L, octave_matrix_t &U, T *cols_norm, T *rows_norm, const T droptol=0, const std::string milu="off")
octave_value_list Ftril(const octave_value_list &=octave_value_list(), int=0)
octave_value_list Ftriu(const octave_value_list &=octave_value_list(), int=0)
T * fortran_vec()
Size of the specified dimension.
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
octave_idx_type cols() const
Sparse< T, Alloc > index(const octave::idx_vector &i, bool resize_ok=false) const
Vector representing the dimensions (size) of an Array.
static const idx_vector colon
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
void() error(const char *fmt,...)
std::complex< double > Complex
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
RowVector xcolnorms(const Matrix &m, double p)
ColumnVector xrownorms(const Matrix &m, double p)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.