26#if defined (HAVE_CONFIG_H)
36#include "builtin-defun-decls.h"
46template <
typename octave_matrix_t,
typename T>
47void 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 ();
142DEFUN (__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 ();
185template <
typename octave_matrix_t,
typename T>
186void 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];
467DEFUN (__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 ())
486 ilu_crout <SparseMatrix, double> (sm_l, sm_u, L, U,
493 return ovl (L + speye, U);
504 ilu_crout <SparseComplexMatrix, Complex> (sm_l, sm_u, L, U,
511 return ovl (L + speye, U);
523template <
typename octave_matrix_t,
typename T>
524void ilu_tp (octave_matrix_t& sm, octave_matrix_t& L, octave_matrix_t& U,
527 const T thresh = T(0),
const std::string milu =
"off",
528 const double udiag = 0)
531 enum {OFF, ROW, COL};
534 else if (milu ==
"col")
543 sm = sm.transpose ();
548 T *data_in = sm.data ();
549 octave_idx_type jrow, i, j, k, jj, c, total_len_l, total_len_u, p_perm,
550 max_ind, max_len_l, max_len_u;
553 T tl = zero, aux, maximum;
556 max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
558 max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
578 T total_sum, partial_col_sum = zero, partial_row_sum = zero;
579 std::set <octave_idx_type> iw_l;
580 std::set <octave_idx_type> iw_u;
581 std::set <octave_idx_type>::iterator it, it2;
588 cidx_l[0] = cidx_in[0];
589 cidx_u[0] = cidx_in[0];
590 for (i = 0; i < n; i++)
600 for (k = 0; k < n; k++)
602 for (j = cidx_in[k]; j < cidx_in[k+1]; j++)
604 p_perm = iperm[ridx_in[j]];
605 w_data[iperm[ridx_in[j]]] = data_in[j];
607 iw_l.insert (ridx_in[j]);
609 iw_u.insert (p_perm);
615 while ((jrow < k) && (it != iw_u.end ()))
618 partial_col_sum = w_data[jrow];
619 if (w_data[jrow] != zero)
623 partial_row_sum = w_data[jrow];
624 tl = w_data[jrow] / data_u[uptr[jrow]];
626 for (jj = cidx_l[jrow]; jj < cidx_l[jrow+1]; jj++)
628 p_perm = iperm[ridx_l[jj]];
629 aux = w_data[p_perm];
632 w_data[p_perm] -= tl * data_l[jj];
633 partial_row_sum += tl * data_l[jj];
637 tl = data_l[jj] * w_data[jrow];
638 w_data[p_perm] -= tl;
640 partial_col_sum += tl;
643 if ((aux == zero) && (w_data[p_perm] != zero))
646 iw_l.insert (ridx_l[jj]);
648 iw_u.insert (p_perm);
654 if ((
std::abs (w_data[jrow]) < (droptol * cols_norm[k]))
655 && (w_data[jrow] != zero))
658 total_sum += partial_col_sum;
660 total_sum += partial_row_sum;
679 if ((thresh > zero) && (k < (n - 1)))
681 maximum =
std::abs (w_data[k]) / thresh;
683 for (it = iw_l.begin (); it != iw_l.end (); ++it)
686 if (
std::abs (w_data[p_perm]) > maximum)
688 maximum =
std::abs (w_data[p_perm]);
694 p_perm = iperm[max_ind];
695 if (max_ind != perm[k])
698 if (w_data[k] != zero)
699 iw_l.insert (perm[k]);
704 iperm[perm[p_perm]] = k;
705 iperm[perm[k]] = p_perm;
707 perm[k] = perm[p_perm];
709 w_data[k] = w_data[p_perm];
710 w_data[p_perm] = aux;
718 while (it != iw_l.end ())
722 if (
std::abs (w_data[p_perm]) < (droptol * cols_norm[k]))
725 total_sum += w_data[p_perm];
726 w_data[p_perm] = zero;
740 if ((total_sum > zero) && (w_data[k] == zero))
742 w_data[k] += total_sum;
748 if (w_data[k] == zero)
751 error (
"ilu: encountered a pivot equal to 0");
759 for (it = iw_l.begin (); it != iw_l.end (); ++it)
762 w_data[p_perm] = w_data[p_perm] / w_data[k];
765 if ((max_len_u - total_len_u) < n)
767 max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
774 if ((max_len_l - total_len_l) < n)
776 max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
785 for (it = iw_u.begin (); it != iw_u.end (); ++it)
787 if (w_data[*it] != zero)
789 data_u[total_len_u + w_len_u] = w_data[*it];
790 ridx_u[total_len_u + w_len_u] = *it;
798 for (it = iw_l.begin (); it != iw_l.end (); ++it)
801 if (w_data[p_perm] != zero)
803 data_l[total_len_l + w_len_l] = w_data[p_perm];
804 ridx_l[total_len_l + w_len_l] = *it;
809 total_len_u += w_len_u;
810 total_len_l += w_len_l;
814 if (total_len_l < 0 || total_len_u < 0)
815 error (
"ilu: Integer overflow. Too many fill-in elements in L or U");
818 uptr[k] = total_len_u - 1;
820 cidx_u[k+1] = cidx_u[k] - cidx_u[0] + w_len_u;
821 cidx_l[k+1] = cidx_l[k] - cidx_l[0] + w_len_l;
827 octave_matrix_t *L_ptr;
828 octave_matrix_t *U_ptr;
829 octave_matrix_t diag (n, n, n);
838 L = octave_matrix_t (n, n, total_len_u - n);
839 U = octave_matrix_t (n, n, total_len_l);
845 L = octave_matrix_t (n, n, total_len_l);
846 U = octave_matrix_t (n, n, total_len_u);
849 for (i = 0; i <= n; i++)
851 L_ptr->cidx (i) = cidx_l[i];
852 U_ptr->cidx (i) = cidx_u[i];
854 U_ptr->cidx (i) -= i;
857 for (i = 0; i < n; i++)
860 diag.elem (i, i) = data_u[uptr[i]];
863 while (j < cidx_l[i+1])
865 L_ptr->ridx (j) = ridx_l[j];
866 L_ptr->data (j) = data_l[j];
871 while (j < cidx_u[i+1])
887 U_ptr->data (c) = data_u[j];
888 U_ptr->ridx (c) = ridx_u[j];
902DEFUN (__ilutp__, args, nargout,
909 if (args.length () != 5)
913 double droptol = args(1).double_value ();
914 double thresh = args(2).double_value ();
915 std::string milu = args(3).string_value ();
916 double udiag = args(4).double_value ();
920 if (! args(0).iscomplex ())
924 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_matrix_value ()).nnz ();
925 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_matrix_value ()).nnz ();
933 ilu_tp <SparseMatrix, double> (sm, L, U, nnz_u, nnz_l,
935 perm, droptol, thresh, milu, udiag);
940 retval(0) = L + speye;
965 nnz_u = (
Ftriu (
ovl (sm))(0).sparse_complex_matrix_value ()).nnz ();
966 nnz_l = (
Ftril (
ovl (sm, -1))(0).sparse_complex_matrix_value ()).nnz ();
974 ilu_tp <SparseComplexMatrix, Complex>
975 (sm, L, U, nnz_u, nnz_l, rc_norm.
fortran_vec (), perm,
981 retval(0) = L + speye;
987 else if (nargout == 2)
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_NAMESPACE_BEGIN void ilu_0(octave_matrix_t &sm, 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
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,...)
ColumnVector xrownorms(const Matrix &m, double p)
RowVector xcolnorms(const Matrix &m, double p)
std::complex< double > Complex
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
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)