26 #if defined (HAVE_CONFIG_H)
36 #include "builtin-defun-decls.h"
44 template <
typename octave_matrix_t,
typename T>
45 void ilu_0 (octave_matrix_t& sm,
const std::string milu =
"off")
59 else if (milu ==
"col")
74 for (i = 0; i <
n; i++)
78 for (k = 0; k <
n; k++)
84 error (
"ilu: A has a zero on the diagonal");
86 for (j = j1; j < j2; j++)
92 while ((jrow < k) && (j < j2))
96 tl = data[j] / data[uptr[jrow]];
99 for (jj = uptr[jrow] + 1; jj < cidx[jrow+1]; jj++)
104 data[jw] -= tl * data[jj];
106 data[jw] -= data[j] * data[jj];
113 r += data[j] * data[jj];
123 for (jj = uptr[k] + 1; jj < cidx[k+1]; jj++)
124 data[jj] /= data[uptr[k]];
127 error (
"ilu: A has a zero on the diagonal");
130 error (
"ilu: encountered a pivot equal to 0");
132 for (i = j1; i < j2; i++)
137 sm = sm.transpose ();
140 DEFUN (__ilu0__, args, ,
147 if (args.length () != 2)
152 std::string milu = args(1).string_value ();
158 if (! args(0).iscomplex ())
163 ilu_0 <SparseMatrix, double> (sm, milu);
165 retval(0) = speye +
Ftril (
ovl (sm, -1))(0).sparse_matrix_value ();
173 ilu_0 <SparseComplexMatrix, Complex> (sm, milu);
176 Ftril (
ovl (sm, -1))(0).sparse_complex_matrix_value ();
183 template <
typename octave_matrix_t,
typename T>
184 void ilu_crout (octave_matrix_t& sm_l, octave_matrix_t& sm_u,
185 octave_matrix_t& L, octave_matrix_t& U, T *cols_norm,
186 T *rows_norm,
const T droptol = 0,
187 const std::string milu =
"off")
191 enum {OFF, ROW, COL};
194 else if (milu ==
"col")
199 octave_idx_type jrow, i, j, k, jj, total_len_l, total_len_u, max_len_u,
200 max_len_l, w_len_u, w_len_l, cols_list_len, rows_list_len;
203 sm_u = sm_u.transpose ();
205 max_len_u = sm_u.nnz ();
206 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
207 max_len_l = sm_l.nnz ();
208 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
213 T *data_in_u = sm_u.data ();
216 T *data_in_l = sm_l.data ();
244 cidx_u[0] = cidx_in_u[0];
245 cidx_l[0] = cidx_in_l[0];
246 for (i = 0; i <
n; i++)
259 for (k = 0; k <
n; k++)
262 for (i = cidx_in_l[k]; i < cidx_in_l[k+1]; i++)
263 w_data_l[ridx_in_l[i]] = data_in_l[i];
265 for (i = cidx_in_u[k]; i < cidx_in_u[k+1]; i++)
266 w_data_u[ridx_in_u[i]] = data_in_u[i];
269 for (j = 0; j < rows_list_len; j++)
271 if ((Ufirst[rows_list[j]] != -1))
272 for (jj = Ufirst[rows_list[j]]; jj < cidx_u[rows_list[j]+1]; jj++)
275 w_data_u[jrow] -= data_u[jj] * data_l[Lfirst[rows_list[j]]];
279 for (j = 0; j < cols_list_len; j++)
281 if (Lfirst[cols_list[j]] != -1)
282 for (jj = Lfirst[cols_list[j]]; jj < cidx_l[cols_list[j]+1]; jj++)
285 w_data_l[jrow] -= data_l[jj] * data_u[Ufirst[cols_list[j]]];
289 if ((max_len_u - total_len_u) <
n)
291 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
298 if ((max_len_l - total_len_l) <
n)
300 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
309 data_u[total_len_u] = w_data_u[k];
310 ridx_u[total_len_u] = k;
312 for (i = k + 1; i <
n; i++)
314 if (w_data_u[i] != zero)
316 if (
std::abs (w_data_u[i]) < (droptol * rows_norm[k]))
319 cr_sum[k] += w_data_u[i];
321 cr_sum[i] += w_data_u[i];
325 data_u[total_len_u + w_len_u] = w_data_u[i];
326 ridx_u[total_len_u + w_len_u] = i;
332 if (w_data_l[i] != zero)
334 if (
std::abs (w_data_l[i]) < (droptol * cols_norm[k]))
337 cr_sum[k] += w_data_l[i];
339 cr_sum[i] += w_data_l[i];
343 data_l[total_len_l + w_len_l] = w_data_l[i];
344 ridx_l[total_len_l + w_len_l] = i;
353 if (opt == COL || opt == ROW)
354 data_u[total_len_u] += cr_sum[k];
357 if (data_u[total_len_u] == zero)
358 error (
"ilu: encountered a pivot equal to 0");
361 for (i = total_len_l ; i < (total_len_l + w_len_l); i++)
362 data_l[i] /= data_u[total_len_u];
364 total_len_u += w_len_u;
365 total_len_l += w_len_l;
368 if (total_len_l < 0 || total_len_u < 0)
369 error (
"ilu: integer overflow. Too many fill-in elements in L or U");
371 cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
372 cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
385 Ufirst[k] = cidx_u[k];
389 Lfirst[k] = cidx_l[k];
394 for (i = 0; i <= k; i++)
398 jj = ridx_u[Ufirst[i]];
401 if (Ufirst[i] < (cidx_u[i+1]))
404 if (Ufirst[i] == cidx_u[i+1])
407 jj = ridx_u[Ufirst[i]];
412 cols_list[cols_list_len] = i;
419 jj = ridx_l[Lfirst[i]];
421 if (Lfirst[i] < (cidx_l[i+1]))
424 if (Lfirst[i] == cidx_l[i+1])
427 jj = ridx_l[Lfirst[i]];
431 rows_list[rows_list_len] = i;
440 L = octave_matrix_t (
n,
n, total_len_l);
441 U = octave_matrix_t (
n,
n, total_len_u);
444 for (i = 0; i <=
n; i++)
445 L.cidx (i) = cidx_l[i];
447 for (i = 0; i < total_len_l; i++)
449 L.ridx (i) = ridx_l[i];
450 L.data (i) = data_l[i];
453 for (i = 0; i <=
n; i++)
454 U.cidx (i) = cidx_u[i];
456 for (i = 0; i < total_len_u; i++)
458 U.ridx (i) = ridx_u[i];
459 U.data (i) = data_u[i];
465 DEFUN (__iluc__, args, ,
471 if (args.length () != 3)
474 double droptol = args(1).double_value ();
475 std::string milu = args(2).string_value ();
477 if (! args(0).iscomplex ())
484 ilu_crout <SparseMatrix, double> (sm_l, sm_u, L, U,
491 return ovl (L + speye, U);
502 ilu_crout <SparseComplexMatrix, Complex> (sm_l, sm_u, L, U,
509 return ovl (L + speye, U);
521 template <
typename octave_matrix_t,
typename T>
522 void ilu_tp (octave_matrix_t& sm, octave_matrix_t& L, octave_matrix_t& U,
525 const T thresh = T(0),
const std::string milu =
"off",
526 const double udiag = 0)
529 enum {OFF, ROW, COL};
532 else if (milu ==
"col")
541 sm = sm.transpose ();
546 T *data_in = sm.data ();
547 octave_idx_type jrow, i, j, k, jj, c, total_len_l, total_len_u, p_perm,
548 max_ind, max_len_l, max_len_u;
551 T tl = zero, aux, maximum;
554 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
556 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
576 T total_sum, partial_col_sum = zero, partial_row_sum = zero;
577 std::set <octave_idx_type> iw_l;
578 std::set <octave_idx_type> iw_u;
579 std::set <octave_idx_type>::iterator it, it2;
586 cidx_l[0] = cidx_in[0];
587 cidx_u[0] = cidx_in[0];
588 for (i = 0; i <
n; i++)
598 for (k = 0; k <
n; k++)
600 for (j = cidx_in[k]; j < cidx_in[k+1]; j++)
602 p_perm = iperm[ridx_in[j]];
603 w_data[iperm[ridx_in[j]]] = data_in[j];
605 iw_l.insert (ridx_in[j]);
607 iw_u.insert (p_perm);
613 while ((jrow < k) && (it != iw_u.end ()))
616 partial_col_sum = w_data[jrow];
617 if (w_data[jrow] != zero)
621 partial_row_sum = w_data[jrow];
622 tl = w_data[jrow] / data_u[uptr[jrow]];
624 for (jj = cidx_l[jrow]; jj < cidx_l[jrow+1]; jj++)
626 p_perm = iperm[ridx_l[jj]];
627 aux = w_data[p_perm];
630 w_data[p_perm] -= tl * data_l[jj];
631 partial_row_sum += tl * data_l[jj];
635 tl = data_l[jj] * w_data[jrow];
636 w_data[p_perm] -= tl;
638 partial_col_sum += tl;
641 if ((aux == zero) && (w_data[p_perm] != zero))
644 iw_l.insert (ridx_l[jj]);
646 iw_u.insert (p_perm);
652 if ((
std::abs (w_data[jrow]) < (droptol * cols_norm[k]))
653 && (w_data[jrow] != zero))
656 total_sum += partial_col_sum;
658 total_sum += partial_row_sum;
677 if ((thresh > zero) && (k < (
n - 1)))
679 maximum =
std::abs (w_data[k]) / thresh;
681 for (it = iw_l.begin (); it != iw_l.end (); ++it)
684 if (
std::abs (w_data[p_perm]) > maximum)
686 maximum =
std::abs (w_data[p_perm]);
692 p_perm = iperm[max_ind];
693 if (max_ind != perm[k])
696 if (w_data[k] != zero)
697 iw_l.insert (perm[k]);
702 iperm[perm[p_perm]] = k;
703 iperm[perm[k]] = p_perm;
705 perm[k] = perm[p_perm];
707 w_data[k] = w_data[p_perm];
708 w_data[p_perm] = aux;
716 while (it != iw_l.end ())
720 if (
std::abs (w_data[p_perm]) < (droptol * cols_norm[k]))
723 total_sum += w_data[p_perm];
724 w_data[p_perm] = zero;
738 if ((total_sum > zero) && (w_data[k] == zero))
740 w_data[k] += total_sum;
746 if (w_data[k] == zero)
749 error (
"ilu: encountered a pivot equal to 0");
757 for (it = iw_l.begin (); it != iw_l.end (); ++it)
760 w_data[p_perm] = w_data[p_perm] / w_data[k];
763 if ((max_len_u - total_len_u) <
n)
765 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
772 if ((max_len_l - total_len_l) <
n)
774 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
783 for (it = iw_u.begin (); it != iw_u.end (); ++it)
785 if (w_data[*it] != zero)
787 data_u[total_len_u + w_len_u] = w_data[*it];
788 ridx_u[total_len_u + w_len_u] = *it;
796 for (it = iw_l.begin (); it != iw_l.end (); ++it)
799 if (w_data[p_perm] != zero)
801 data_l[total_len_l + w_len_l] = w_data[p_perm];
802 ridx_l[total_len_l + w_len_l] = *it;
807 total_len_u += w_len_u;
808 total_len_l += w_len_l;
812 if (total_len_l < 0 || total_len_u < 0)
813 error (
"ilu: Integer overflow. Too many fill-in elements in L or U");
816 uptr[k] = total_len_u - 1;
818 cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
819 cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
825 octave_matrix_t *L_ptr;
826 octave_matrix_t *U_ptr;
827 octave_matrix_t diag (
n,
n,
n);
836 L = octave_matrix_t (
n,
n, total_len_u -
n);
837 U = octave_matrix_t (
n,
n, total_len_l);
843 L = octave_matrix_t (
n,
n, total_len_l);
844 U = octave_matrix_t (
n,
n, total_len_u);
847 for (i = 0; i <=
n; i++)
849 L_ptr->cidx (i) = cidx_l[i];
850 U_ptr->cidx (i) = cidx_u[i];
852 U_ptr->cidx (i) -= i;
855 for (i = 0; i <
n; i++)
858 diag.elem (i,i) = data_u[uptr[i]];
861 while (j < cidx_l[i+1])
863 L_ptr->ridx (j) = ridx_l[j];
864 L_ptr->data (j) = data_l[j];
869 while (j < cidx_u[i+1])
885 U_ptr->data (c) = data_u[j];
886 U_ptr->ridx (c) = ridx_u[j];
900 DEFUN (__ilutp__, args, nargout,
907 if (args.length () != 5)
911 double droptol = args(1).double_value ();
912 double thresh = args(2).double_value ();
913 std::string milu = args(3).string_value ();
914 double udiag = args(4).double_value ();
918 if (! args(0).iscomplex ())
922 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_matrix_value ()).nnz ();
923 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_matrix_value ()).nnz ();
931 ilu_tp <SparseMatrix, double> (sm, L, U, nnz_u, nnz_l,
933 perm, droptol, thresh, milu, udiag);
963 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_complex_matrix_value ()).nnz ();
964 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_complex_matrix_value ()).nnz ();
972 ilu_tp <SparseComplexMatrix, Complex>
973 (sm, L, U, nnz_u, nnz_l, rc_norm.
fortran_vec (), perm,
985 else if (nargout == 2)
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")
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Array< T > index(const idx_vector &i) const
Indexing without resizing.
const T * fortran_vec(void) const
Size of the specified dimension.
octave_idx_type cols(void) const
Sparse< T > index(const idx_vector &i, bool resize_ok=false) const
Vector representing the dimensions (size) of an Array.
static const idx_vector colon
OCTINTERP_API void print_usage(void)
#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)
OCTAVE_API RowVector xcolnorms(const Matrix &m, double p)
OCTAVE_API ColumnVector xrownorms(const Matrix &m, double p)
octave_value::octave_value(const Array< char > &chm, char type) return retval
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
OCTAVE_EXPORT octave_value_list Ftriu(const octave_value_list &args, int)
OCTAVE_EXPORT octave_value_list Ftril(const octave_value_list &args, int)