Mercurial > hg > octave-nkf
diff liboctave/SparsedbleLU.cc @ 5164:57077d0ddc8e
[project @ 2005-02-25 19:55:24 by jwe]
author | jwe |
---|---|
date | Fri, 25 Feb 2005 19:55:28 +0000 |
parents | |
children | dbeafbc0ff64 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/liboctave/SparsedbleLU.cc @@ -0,0 +1,392 @@ +/* + +Copyright (C) 2004 David Bateman +Copyright (C) 1998-2004 Andy Adler + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <vector> + +#include "lo-error.h" + +#include "SparsedbleLU.h" +#include "oct-spparms.h" + +// Instantiate the base LU class for the types we need. + +#include "sparse-base-lu.h" +#include "sparse-base-lu.cc" + +template class sparse_base_lu <SparseMatrix, double, SparseMatrix, double>; + +// Include the UMFPACK functions +extern "C" { +#include "umfpack.h" +} + +SparseLU::SparseLU (const SparseMatrix& a, double piv_thres) +{ + int nr = a.rows (); + int nc = a.cols (); + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_di_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + + if (piv_thres >= 0.) + { + piv_thres = (piv_thres > 1. ? 1. : piv_thres); + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; + Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + } + else + { + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + } + + // Set whether we are allowed to modify Q or not + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_di_report_control (control); + + const int *Ap = a.cidx (); + const int *Ai = a.ridx (); + const double *Ax = a.data (); + + umfpack_di_report_matrix (nr, nc, Ap, Ai, Ax, 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_di_qsymbolic (nr, nc, Ap, Ai, Ax, NULL, + &Symbolic, control, info); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU symbolic factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_symbolic (&Symbolic) ; + } + else + { + umfpack_di_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + control, info) ; + umfpack_di_free_symbolic (&Symbolic) ; + + cond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU numeric factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + umfpack_di_report_numeric (Numeric, control); + + int lnz, unz, ignore1, ignore2, ignore3; + status = umfpack_di_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + int n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + Lfact = SparseMatrix (n_inner, nr, 1); + else + Lfact = SparseMatrix (n_inner, nr, lnz); + + int *Ltp = Lfact.cidx (); + int *Ltj = Lfact.ridx (); + double *Ltx = Lfact.data (); + + if (unz < 1) + Ufact = SparseMatrix (n_inner, nc, 1); + else + Ufact = SparseMatrix (n_inner, nc, unz); + + int *Up = Ufact.cidx (); + int *Uj = Ufact.ridx (); + double *Ux = Ufact.data (); + + P.resize (nr); + int *p = P.fortran_vec (); + + Q.resize (nc); + int *q = Q.fortran_vec (); + + int do_recip; + status = umfpack_di_get_numeric (Ltp, Ltj, Ltx, Up, Uj, + Ux, p, q, (double *) NULL, + &do_recip, (double *) NULL, + Numeric) ; + + umfpack_di_free_numeric (&Numeric) ; + + if (status < 0 || do_recip) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + } + else + { + Lfact = Lfact.transpose (); + + umfpack_di_report_matrix (nr, n_inner, Lfact.cidx (), + Lfact.ridx (), Lfact.data (), + 1, control); + umfpack_di_report_matrix (n_inner, nc, Ufact.cidx (), + Ufact.ridx (), Ufact.data (), + 1, control); + umfpack_di_report_perm (nr, p, control); + umfpack_di_report_perm (nc, q, control); + } + + umfpack_di_report_info (control, info); + } + } + } +} + +SparseLU::SparseLU (const SparseMatrix& a, const ColumnVector& Qinit, + double piv_thres, bool FixedQ) +{ + int nr = a.rows (); + int nc = a.cols (); + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_di_defaults (control); + + double tmp = Voctave_sparse_controls.get_key ("spumoni"); + if (!xisnan (tmp)) + Control (UMFPACK_PRL) = tmp; + if (piv_thres >= 0.) + { + piv_thres = (piv_thres > 1. ? 1. : piv_thres); + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; + Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; + } + else + { + tmp = Voctave_sparse_controls.get_key ("piv_tol"); + if (!xisnan (tmp)) + { + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + } + } + + // Set whether we are allowed to modify Q or not + if (FixedQ) + Control (UMFPACK_FIXQ) = 1.0; + else + { + tmp = Voctave_sparse_controls.get_key ("autoamd"); + if (!xisnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + } + + // Turn-off UMFPACK scaling for LU + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_di_report_control (control); + + const int *Ap = a.cidx (); + const int *Ai = a.ridx (); + const double *Ax = a.data (); + + umfpack_di_report_matrix (nr, nc, Ap, Ai, Ax, 1, control); + + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status; + + // Null loop so that qinit is imediately deallocated when not needed + do { + OCTAVE_LOCAL_BUFFER (int, qinit, nc); + + for (int i = 0; i < nc; i++) + qinit [i] = static_cast<int> (Qinit (i)); + + status = umfpack_di_qsymbolic (nr, nc, Ap, Ai, Ax, qinit, + &Symbolic, control, info); + } while (0); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU symbolic factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_symbolic (&Symbolic) ; + } + else + { + umfpack_di_report_symbolic (Symbolic, control); + + void *Numeric; + status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, + control, info) ; + umfpack_di_free_symbolic (&Symbolic) ; + + cond = Info (UMFPACK_RCOND); + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU numeric factorization failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + umfpack_di_report_numeric (Numeric, control); + + int lnz, unz, ignore1, ignore2, ignore3; + status = umfpack_di_get_lunz (&lnz, &unz, &ignore1, &ignore2, + &ignore3, Numeric) ; + + if (status < 0) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + umfpack_di_report_info (control, info); + + umfpack_di_free_numeric (&Numeric); + } + else + { + int n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + Lfact = SparseMatrix (n_inner, nr, 1); + else + Lfact = SparseMatrix (n_inner, nr, lnz); + + int *Ltp = Lfact.cidx (); + int *Ltj = Lfact.ridx (); + double *Ltx = Lfact.data (); + + if (unz < 1) + Ufact = SparseMatrix (n_inner, nc, 1); + else + Ufact = SparseMatrix (n_inner, nc, unz); + + int *Up = Ufact.cidx (); + int *Uj = Ufact.ridx (); + double *Ux = Ufact.data (); + + P.resize (nr); + int *p = P.fortran_vec (); + + Q.resize (nc); + int *q = Q.fortran_vec (); + + int do_recip; + status = umfpack_di_get_numeric (Ltp, Ltj, Ltx, Up, Uj, + Ux, p, q, (double *) NULL, + &do_recip, (double *) NULL, + Numeric) ; + + umfpack_di_free_numeric (&Numeric) ; + + if (status < 0 || do_recip) + { + (*current_liboctave_error_handler) + ("SparseLU::SparseLU extracting LU factors failed"); + + umfpack_di_report_status (control, status); + } + else + { + Lfact = Lfact.transpose (); + umfpack_di_report_matrix (nr, n_inner, Lfact.cidx (), + Lfact.ridx (), Lfact.data (), + 1, control); + umfpack_di_report_matrix (n_inner, nc, Ufact.cidx (), + Ufact.ridx (), Ufact.data (), + 1, control); + umfpack_di_report_perm (nr, p, control); + umfpack_di_report_perm (nc, q, control); + } + + umfpack_di_report_info (control, info); + } + } + } +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ +