26 #if defined (HAVE_CONFIG_H)
36 #include "builtin-defun-decls.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>
186 void ilu_crout (octave_matrix_t& sm_l, octave_matrix_t& sm_u,
187 octave_matrix_t& L, octave_matrix_t& U, T *cols_norm,
188 T *rows_norm,
const T droptol = 0,
189 const std::string milu =
"off")
193 enum {OFF, ROW, COL};
196 else if (milu ==
"col")
201 octave_idx_type jrow, i, j, k, jj, total_len_l, total_len_u, max_len_u,
202 max_len_l, w_len_u, w_len_l, cols_list_len, rows_list_len;
205 sm_u = sm_u.transpose ();
207 max_len_u = sm_u.nnz ();
208 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
209 max_len_l = sm_l.nnz ();
210 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
215 T *data_in_u = sm_u.data ();
218 T *data_in_l = sm_l.data ();
246 cidx_u[0] = cidx_in_u[0];
247 cidx_l[0] = cidx_in_l[0];
248 for (i = 0; i <
n; i++)
261 for (k = 0; k <
n; k++)
264 for (i = cidx_in_l[k]; i < cidx_in_l[k+1]; i++)
265 w_data_l[ridx_in_l[i]] = data_in_l[i];
267 for (i = cidx_in_u[k]; i < cidx_in_u[k+1]; i++)
268 w_data_u[ridx_in_u[i]] = data_in_u[i];
271 for (j = 0; j < rows_list_len; j++)
273 if ((Ufirst[rows_list[j]] != -1))
274 for (jj = Ufirst[rows_list[j]]; jj < cidx_u[rows_list[j]+1]; jj++)
277 w_data_u[jrow] -= data_u[jj] * data_l[Lfirst[rows_list[j]]];
281 for (j = 0; j < cols_list_len; j++)
283 if (Lfirst[cols_list[j]] != -1)
284 for (jj = Lfirst[cols_list[j]]; jj < cidx_l[cols_list[j]+1]; jj++)
287 w_data_l[jrow] -= data_l[jj] * data_u[Ufirst[cols_list[j]]];
291 if ((max_len_u - total_len_u) <
n)
293 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
300 if ((max_len_l - total_len_l) <
n)
302 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
311 data_u[total_len_u] = w_data_u[k];
312 ridx_u[total_len_u] = k;
314 for (i = k + 1; i <
n; i++)
316 if (w_data_u[i] != zero)
318 if (
std::abs (w_data_u[i]) < (droptol * rows_norm[k]))
321 cr_sum[k] += w_data_u[i];
323 cr_sum[i] += w_data_u[i];
327 data_u[total_len_u + w_len_u] = w_data_u[i];
328 ridx_u[total_len_u + w_len_u] = i;
334 if (w_data_l[i] != zero)
336 if (
std::abs (w_data_l[i]) < (droptol * cols_norm[k]))
339 cr_sum[k] += w_data_l[i];
341 cr_sum[i] += w_data_l[i];
345 data_l[total_len_l + w_len_l] = w_data_l[i];
346 ridx_l[total_len_l + w_len_l] = i;
355 if (opt == COL || opt == ROW)
356 data_u[total_len_u] += cr_sum[k];
359 if (data_u[total_len_u] == zero)
360 error (
"ilu: encountered a pivot equal to 0");
363 for (i = total_len_l ; i < (total_len_l + w_len_l); i++)
364 data_l[i] /= data_u[total_len_u];
366 total_len_u += w_len_u;
367 total_len_l += w_len_l;
370 if (total_len_l < 0 || total_len_u < 0)
371 error (
"ilu: integer overflow. Too many fill-in elements in L or U");
373 cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
374 cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
387 Ufirst[k] = cidx_u[k];
391 Lfirst[k] = cidx_l[k];
396 for (i = 0; i <= k; i++)
400 jj = ridx_u[Ufirst[i]];
403 if (Ufirst[i] < (cidx_u[i+1]))
406 if (Ufirst[i] == cidx_u[i+1])
409 jj = ridx_u[Ufirst[i]];
414 cols_list[cols_list_len] = i;
421 jj = ridx_l[Lfirst[i]];
423 if (Lfirst[i] < (cidx_l[i+1]))
426 if (Lfirst[i] == cidx_l[i+1])
429 jj = ridx_l[Lfirst[i]];
433 rows_list[rows_list_len] = i;
442 L = octave_matrix_t (
n,
n, total_len_l);
443 U = octave_matrix_t (
n,
n, total_len_u);
446 for (i = 0; i <=
n; i++)
447 L.cidx (i) = cidx_l[i];
449 for (i = 0; i < total_len_l; i++)
451 L.ridx (i) = ridx_l[i];
452 L.data (i) = data_l[i];
455 for (i = 0; i <=
n; i++)
456 U.cidx (i) = cidx_u[i];
458 for (i = 0; i < total_len_u; i++)
460 U.ridx (i) = ridx_u[i];
461 U.data (i) = data_u[i];
467 DEFUN (__iluc__, args, ,
473 if (args.length () != 3)
476 double droptol = args(1).double_value ();
477 std::string milu = args(2).string_value ();
479 if (! args(0).iscomplex ())
488 ilu_crout <SparseMatrix, double> (sm_l, sm_u, L, U,
495 return ovl (L + speye, U);
506 ilu_crout <SparseComplexMatrix, Complex> (sm_l, sm_u, L, U,
513 return ovl (L + speye, U);
525 template <
typename octave_matrix_t,
typename T>
526 void ilu_tp (octave_matrix_t& sm, octave_matrix_t& L, octave_matrix_t& U,
529 const T thresh = T(0),
const std::string milu =
"off",
530 const double udiag = 0)
533 enum {OFF, ROW, COL};
536 else if (milu ==
"col")
545 sm = sm.transpose ();
550 T *data_in = sm.data ();
551 octave_idx_type jrow, i, j, k, jj, c, total_len_l, total_len_u, p_perm,
552 max_ind, max_len_l, max_len_u;
555 T tl = zero, aux, maximum;
558 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
560 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
580 T total_sum, partial_col_sum = zero, partial_row_sum = zero;
581 std::set <octave_idx_type> iw_l;
582 std::set <octave_idx_type> iw_u;
583 std::set <octave_idx_type>::iterator it, it2;
590 cidx_l[0] = cidx_in[0];
591 cidx_u[0] = cidx_in[0];
592 for (i = 0; i <
n; i++)
602 for (k = 0; k <
n; k++)
604 for (j = cidx_in[k]; j < cidx_in[k+1]; j++)
606 p_perm = iperm[ridx_in[j]];
607 w_data[iperm[ridx_in[j]]] = data_in[j];
609 iw_l.insert (ridx_in[j]);
611 iw_u.insert (p_perm);
617 while ((jrow < k) && (it != iw_u.end ()))
620 partial_col_sum = w_data[jrow];
621 if (w_data[jrow] != zero)
625 partial_row_sum = w_data[jrow];
626 tl = w_data[jrow] / data_u[uptr[jrow]];
628 for (jj = cidx_l[jrow]; jj < cidx_l[jrow+1]; jj++)
630 p_perm = iperm[ridx_l[jj]];
631 aux = w_data[p_perm];
634 w_data[p_perm] -= tl * data_l[jj];
635 partial_row_sum += tl * data_l[jj];
639 tl = data_l[jj] * w_data[jrow];
640 w_data[p_perm] -= tl;
642 partial_col_sum += tl;
645 if ((aux == zero) && (w_data[p_perm] != zero))
648 iw_l.insert (ridx_l[jj]);
650 iw_u.insert (p_perm);
656 if ((
std::abs (w_data[jrow]) < (droptol * cols_norm[k]))
657 && (w_data[jrow] != zero))
660 total_sum += partial_col_sum;
662 total_sum += partial_row_sum;
681 if ((thresh > zero) && (k < (
n - 1)))
683 maximum =
std::abs (w_data[k]) / thresh;
685 for (it = iw_l.begin (); it != iw_l.end (); ++it)
688 if (
std::abs (w_data[p_perm]) > maximum)
690 maximum =
std::abs (w_data[p_perm]);
696 p_perm = iperm[max_ind];
697 if (max_ind != perm[k])
700 if (w_data[k] != zero)
701 iw_l.insert (perm[k]);
706 iperm[perm[p_perm]] = k;
707 iperm[perm[k]] = p_perm;
709 perm[k] = perm[p_perm];
711 w_data[k] = w_data[p_perm];
712 w_data[p_perm] = aux;
720 while (it != iw_l.end ())
724 if (
std::abs (w_data[p_perm]) < (droptol * cols_norm[k]))
727 total_sum += w_data[p_perm];
728 w_data[p_perm] = zero;
742 if ((total_sum > zero) && (w_data[k] == zero))
744 w_data[k] += total_sum;
750 if (w_data[k] == zero)
753 error (
"ilu: encountered a pivot equal to 0");
761 for (it = iw_l.begin (); it != iw_l.end (); ++it)
764 w_data[p_perm] = w_data[p_perm] / w_data[k];
767 if ((max_len_u - total_len_u) <
n)
769 max_len_u += (0.1 * max_len_u) >
n ? 0.1 * max_len_u :
n;
776 if ((max_len_l - total_len_l) <
n)
778 max_len_l += (0.1 * max_len_l) >
n ? 0.1 * max_len_l :
n;
787 for (it = iw_u.begin (); it != iw_u.end (); ++it)
789 if (w_data[*it] != zero)
791 data_u[total_len_u + w_len_u] = w_data[*it];
792 ridx_u[total_len_u + w_len_u] = *it;
800 for (it = iw_l.begin (); it != iw_l.end (); ++it)
803 if (w_data[p_perm] != zero)
805 data_l[total_len_l + w_len_l] = w_data[p_perm];
806 ridx_l[total_len_l + w_len_l] = *it;
811 total_len_u += w_len_u;
812 total_len_l += w_len_l;
816 if (total_len_l < 0 || total_len_u < 0)
817 error (
"ilu: Integer overflow. Too many fill-in elements in L or U");
820 uptr[k] = total_len_u - 1;
822 cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
823 cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
829 octave_matrix_t *L_ptr;
830 octave_matrix_t *U_ptr;
831 octave_matrix_t diag (
n,
n,
n);
840 L = octave_matrix_t (
n,
n, total_len_u -
n);
841 U = octave_matrix_t (
n,
n, total_len_l);
847 L = octave_matrix_t (
n,
n, total_len_l);
848 U = octave_matrix_t (
n,
n, total_len_u);
851 for (i = 0; i <=
n; i++)
853 L_ptr->cidx (i) = cidx_l[i];
854 U_ptr->cidx (i) = cidx_u[i];
856 U_ptr->cidx (i) -= i;
859 for (i = 0; i <
n; i++)
862 diag.elem (i, i) = data_u[uptr[i]];
865 while (j < cidx_l[i+1])
867 L_ptr->ridx (j) = ridx_l[j];
868 L_ptr->data (j) = data_l[j];
873 while (j < cidx_u[i+1])
889 U_ptr->data (c) = data_u[j];
890 U_ptr->ridx (c) = ridx_u[j];
904 DEFUN (__ilutp__, args, nargout,
911 if (args.length () != 5)
915 double droptol = args(1).double_value ();
916 double thresh = args(2).double_value ();
917 std::string milu = args(3).string_value ();
918 double udiag = args(4).double_value ();
922 if (! args(0).iscomplex ())
926 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_matrix_value ()).nnz ();
927 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_matrix_value ()).nnz ();
935 ilu_tp <SparseMatrix, double> (sm, L, U, nnz_u, nnz_l,
937 perm, droptol, thresh, milu, udiag);
942 retval(0) = L + speye;
967 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_complex_matrix_value ()).nnz ();
968 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_complex_matrix_value ()).nnz ();
976 ilu_tp <SparseComplexMatrix, Complex>
977 (sm, L, U, nnz_u, nnz_l, rc_norm.
fortran_vec (), perm,
983 retval(0) = L + speye;
989 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")
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
OCTARRAY_API T * fortran_vec(void)
Size of the specified dimension.
OCTAVE_API Sparse< T, Alloc > index(const octave::idx_vector &i, bool resize_ok=false) const
octave_idx_type cols(void) const
Vector representing the dimensions (size) of an Array.
static const idx_vector colon
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
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)
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.
OCTAVE_EXPORT octave_value_list Ftriu(const octave_value_list &args, int)
OCTAVE_EXPORT octave_value_list Ftril(const octave_value_list &args, int)