SparsedbleLU.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2004-2012 David Bateman
00004 Copyright (C) 1998-2004 Andy Adler
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <vector>
00029 
00030 #include "lo-error.h"
00031 #include "oct-locbuf.h"
00032 
00033 #include "SparsedbleLU.h"
00034 #include "oct-spparms.h"
00035 
00036 // Instantiate the base LU class for the types we need.
00037 
00038 #include "sparse-base-lu.h"
00039 #include "sparse-base-lu.cc"
00040 
00041 template class sparse_base_lu <SparseMatrix, double, SparseMatrix, double>;
00042 
00043 #include "oct-sparse.h"
00044 
00045 SparseLU::SparseLU (const SparseMatrix& a, const Matrix& piv_thres, bool scale)
00046 {
00047 #ifdef HAVE_UMFPACK
00048   octave_idx_type nr = a.rows ();
00049   octave_idx_type nc = a.cols ();
00050 
00051   // Setup the control parameters
00052   Matrix Control (UMFPACK_CONTROL, 1);
00053   double *control = Control.fortran_vec ();
00054   UMFPACK_DNAME (defaults) (control);
00055 
00056   double tmp = octave_sparse_params::get_key ("spumoni");
00057   if (!xisnan (tmp))
00058     Control (UMFPACK_PRL) = tmp;
00059 
00060   if (piv_thres.nelem() == 2)
00061     {
00062       tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));
00063       if (!xisnan (tmp))
00064         Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
00065       tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));
00066       if (!xisnan (tmp))
00067         Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
00068     }
00069   else
00070     {
00071       tmp = octave_sparse_params::get_key ("piv_tol");
00072       if (!xisnan (tmp))
00073         Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
00074 
00075       tmp = octave_sparse_params::get_key ("sym_tol");
00076       if (!xisnan (tmp))
00077           Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
00078     }
00079 
00080   // Set whether we are allowed to modify Q or not
00081   tmp = octave_sparse_params::get_key ("autoamd");
00082   if (!xisnan (tmp))
00083     Control (UMFPACK_FIXQ) = tmp;
00084 
00085   if (scale)
00086     Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
00087   else
00088     Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
00089 
00090   UMFPACK_DNAME (report_control) (control);
00091 
00092   const octave_idx_type *Ap = a.cidx ();
00093   const octave_idx_type *Ai = a.ridx ();
00094   const double *Ax = a.data ();
00095 
00096   UMFPACK_DNAME (report_matrix) (nr, nc, Ap, Ai, Ax, 1, control);
00097 
00098   void *Symbolic;
00099   Matrix Info (1, UMFPACK_INFO);
00100   double *info = Info.fortran_vec ();
00101   int status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, Ax, 0,
00102                                      &Symbolic, control, info);
00103 
00104   if (status < 0)
00105     {
00106       (*current_liboctave_error_handler)
00107             ("SparseLU::SparseLU symbolic factorization failed");
00108 
00109       UMFPACK_DNAME (report_status) (control, status);
00110       UMFPACK_DNAME (report_info) (control, info);
00111 
00112       UMFPACK_DNAME (free_symbolic) (&Symbolic) ;
00113     }
00114   else
00115     {
00116       UMFPACK_DNAME (report_symbolic) (Symbolic, control);
00117 
00118       void *Numeric;
00119       status = UMFPACK_DNAME (numeric) (Ap, Ai, Ax, Symbolic,
00120                                    &Numeric, control, info) ;
00121       UMFPACK_DNAME (free_symbolic) (&Symbolic) ;
00122 
00123       cond = Info (UMFPACK_RCOND);
00124 
00125       if (status < 0)
00126         {
00127           (*current_liboctave_error_handler)
00128             ("SparseLU::SparseLU numeric factorization failed");
00129 
00130           UMFPACK_DNAME (report_status) (control, status);
00131           UMFPACK_DNAME (report_info) (control, info);
00132 
00133           UMFPACK_DNAME (free_numeric) (&Numeric);
00134         }
00135       else
00136         {
00137           UMFPACK_DNAME (report_numeric) (Numeric, control);
00138 
00139           octave_idx_type lnz, unz, ignore1, ignore2, ignore3;
00140           status = UMFPACK_DNAME (get_lunz) (&lnz, &unz, &ignore1,
00141                                         &ignore2, &ignore3, Numeric) ;
00142 
00143           if (status < 0)
00144             {
00145               (*current_liboctave_error_handler)
00146                 ("SparseLU::SparseLU extracting LU factors failed");
00147 
00148               UMFPACK_DNAME (report_status) (control, status);
00149               UMFPACK_DNAME (report_info) (control, info);
00150 
00151               UMFPACK_DNAME (free_numeric) (&Numeric);
00152             }
00153           else
00154             {
00155               octave_idx_type n_inner = (nr < nc ? nr : nc);
00156 
00157               if (lnz < 1)
00158                 Lfact = SparseMatrix (n_inner, nr,
00159                                       static_cast<octave_idx_type> (1));
00160               else
00161                 Lfact = SparseMatrix (n_inner, nr, lnz);
00162 
00163               octave_idx_type *Ltp = Lfact.cidx ();
00164               octave_idx_type *Ltj = Lfact.ridx ();
00165               double *Ltx = Lfact.data ();
00166 
00167               if (unz < 1)
00168                 Ufact = SparseMatrix (n_inner, nc,
00169                                       static_cast<octave_idx_type> (1));
00170               else
00171                 Ufact = SparseMatrix (n_inner, nc, unz);
00172 
00173               octave_idx_type *Up = Ufact.cidx ();
00174               octave_idx_type *Uj = Ufact.ridx ();
00175               double *Ux = Ufact.data ();
00176 
00177               Rfact = SparseMatrix (nr, nr, nr);
00178               for (octave_idx_type i = 0; i < nr; i++)
00179                 {
00180                   Rfact.xridx (i) = i;
00181                   Rfact.xcidx (i) = i;
00182                 }
00183               Rfact.xcidx (nr) = nr;
00184               double *Rx = Rfact.data ();
00185 
00186               P.resize (dim_vector (nr, 1));
00187               octave_idx_type *p = P.fortran_vec ();
00188 
00189               Q.resize (dim_vector (nc, 1));
00190               octave_idx_type *q = Q.fortran_vec ();
00191 
00192               octave_idx_type do_recip;
00193               status = UMFPACK_DNAME (get_numeric) (Ltp, Ltj, Ltx,
00194                                                Up, Uj, Ux, p, q, 0,
00195                                                &do_recip, Rx,
00196                                                Numeric) ;
00197 
00198               UMFPACK_DNAME (free_numeric) (&Numeric) ;
00199 
00200               if (status < 0)
00201                 {
00202                   (*current_liboctave_error_handler)
00203                     ("SparseLU::SparseLU extracting LU factors failed");
00204 
00205                   UMFPACK_DNAME (report_status) (control, status);
00206                 }
00207               else
00208                 {
00209                   Lfact = Lfact.transpose ();
00210 
00211                   if (do_recip)
00212                     for (octave_idx_type i = 0; i < nr; i++)
00213                       Rx[i] = 1.0 / Rx[i];
00214 
00215                   UMFPACK_DNAME (report_matrix) (nr, n_inner,
00216                                             Lfact.cidx (), Lfact.ridx (),
00217                                             Lfact.data (), 1, control);
00218                   UMFPACK_DNAME (report_matrix) (n_inner, nc,
00219                                             Ufact.cidx (), Ufact.ridx (),
00220                                             Ufact.data (), 1, control);
00221                   UMFPACK_DNAME (report_perm) (nr, p, control);
00222                   UMFPACK_DNAME (report_perm) (nc, q, control);
00223                 }
00224 
00225               UMFPACK_DNAME (report_info) (control, info);
00226             }
00227         }
00228     }
00229 #else
00230   (*current_liboctave_error_handler) ("UMFPACK not installed");
00231 #endif
00232 }
00233 
00234 SparseLU::SparseLU (const SparseMatrix& a, const ColumnVector& Qinit,
00235                     const Matrix& piv_thres, bool scale, bool FixedQ,
00236                     double droptol, bool milu, bool udiag)
00237 {
00238 #ifdef HAVE_UMFPACK
00239   if (milu)
00240     (*current_liboctave_error_handler)
00241       ("Modified incomplete LU not implemented");
00242   else
00243     {
00244       octave_idx_type nr = a.rows ();
00245       octave_idx_type nc = a.cols ();
00246 
00247       // Setup the control parameters
00248       Matrix Control (UMFPACK_CONTROL, 1);
00249       double *control = Control.fortran_vec ();
00250       UMFPACK_DNAME (defaults) (control);
00251 
00252       double tmp = octave_sparse_params::get_key ("spumoni");
00253       if (!xisnan (tmp))
00254         Control (UMFPACK_PRL) = tmp;
00255 
00256       if (piv_thres.nelem() == 2)
00257         {
00258           tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));
00259           if (!xisnan (tmp))
00260             Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
00261           tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));
00262           if (!xisnan (tmp))
00263             Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
00264         }
00265       else
00266         {
00267           tmp = octave_sparse_params::get_key ("piv_tol");
00268           if (!xisnan (tmp))
00269             Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
00270 
00271           tmp = octave_sparse_params::get_key ("sym_tol");
00272           if (!xisnan (tmp))
00273             Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
00274         }
00275 
00276       if (droptol >= 0.)
00277         Control (UMFPACK_DROPTOL) = droptol;
00278 
00279 
00280       // Set whether we are allowed to modify Q or not
00281       if (FixedQ)
00282         Control (UMFPACK_FIXQ) = 1.0;
00283       else
00284         {
00285           tmp = octave_sparse_params::get_key ("autoamd");
00286           if (!xisnan (tmp))
00287             Control (UMFPACK_FIXQ) = tmp;
00288         }
00289 
00290       if (scale)
00291         Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
00292       else
00293         Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
00294 
00295       UMFPACK_DNAME (report_control) (control);
00296 
00297       const octave_idx_type *Ap = a.cidx ();
00298       const octave_idx_type *Ai = a.ridx ();
00299       const double *Ax = a.data ();
00300 
00301       UMFPACK_DNAME (report_matrix) (nr, nc, Ap, Ai, Ax, 1,
00302                                                      control);
00303 
00304       void *Symbolic;
00305       Matrix Info (1, UMFPACK_INFO);
00306       double *info = Info.fortran_vec ();
00307       int status;
00308 
00309       // Null loop so that qinit is imediately deallocated when not needed
00310       do {
00311         OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc);
00312 
00313         for (octave_idx_type i = 0; i < nc; i++)
00314           qinit [i] = static_cast<octave_idx_type> (Qinit (i));
00315 
00316         status = UMFPACK_DNAME (qsymbolic) (nr, nc, Ap, Ai, Ax,
00317                                        qinit, &Symbolic, control, info);
00318       } while (0);
00319 
00320       if (status < 0)
00321         {
00322           (*current_liboctave_error_handler)
00323             ("SparseLU::SparseLU symbolic factorization failed");
00324 
00325           UMFPACK_DNAME (report_status) (control, status);
00326           UMFPACK_DNAME (report_info) (control, info);
00327 
00328           UMFPACK_DNAME (free_symbolic) (&Symbolic) ;
00329         }
00330       else
00331         {
00332           UMFPACK_DNAME (report_symbolic) (Symbolic, control);
00333 
00334           void *Numeric;
00335           status = UMFPACK_DNAME (numeric) (Ap, Ai, Ax, Symbolic,
00336                                        &Numeric, control, info) ;
00337           UMFPACK_DNAME (free_symbolic) (&Symbolic) ;
00338 
00339           cond = Info (UMFPACK_RCOND);
00340 
00341           if (status < 0)
00342             {
00343               (*current_liboctave_error_handler)
00344                 ("SparseLU::SparseLU numeric factorization failed");
00345 
00346               UMFPACK_DNAME (report_status) (control, status);
00347               UMFPACK_DNAME (report_info) (control, info);
00348 
00349               UMFPACK_DNAME (free_numeric) (&Numeric);
00350             }
00351           else
00352             {
00353               UMFPACK_DNAME (report_numeric) (Numeric, control);
00354 
00355               octave_idx_type lnz, unz, ignore1, ignore2, ignore3;
00356               status = UMFPACK_DNAME (get_lunz) (&lnz, &unz, &ignore1, &ignore2,
00357                                                  &ignore3, Numeric) ;
00358 
00359               if (status < 0)
00360                 {
00361                   (*current_liboctave_error_handler)
00362                     ("SparseLU::SparseLU extracting LU factors failed");
00363 
00364                   UMFPACK_DNAME (report_status) (control, status);
00365                   UMFPACK_DNAME (report_info) (control, info);
00366 
00367                   UMFPACK_DNAME (free_numeric) (&Numeric);
00368                 }
00369               else
00370                 {
00371                   octave_idx_type n_inner = (nr < nc ? nr : nc);
00372 
00373                   if (lnz < 1)
00374                     Lfact = SparseMatrix (n_inner, nr,
00375                                           static_cast<octave_idx_type> (1));
00376                   else
00377                     Lfact = SparseMatrix (n_inner, nr, lnz);
00378 
00379                   octave_idx_type *Ltp = Lfact.cidx ();
00380                   octave_idx_type *Ltj = Lfact.ridx ();
00381                   double *Ltx = Lfact.data ();
00382 
00383                   if (unz < 1)
00384                     Ufact = SparseMatrix (n_inner, nc,
00385                                           static_cast<octave_idx_type> (1));
00386                   else
00387                     Ufact = SparseMatrix (n_inner, nc, unz);
00388 
00389                   octave_idx_type *Up = Ufact.cidx ();
00390                   octave_idx_type *Uj = Ufact.ridx ();
00391                   double *Ux = Ufact.data ();
00392 
00393                   Rfact = SparseMatrix (nr, nr, nr);
00394                   for (octave_idx_type i = 0; i < nr; i++)
00395                     {
00396                       Rfact.xridx (i) = i;
00397                       Rfact.xcidx (i) = i;
00398                     }
00399                   Rfact.xcidx (nr) = nr;
00400                   double *Rx = Rfact.data ();
00401 
00402                   P.resize (dim_vector (nr, 1));
00403                   octave_idx_type *p = P.fortran_vec ();
00404 
00405                   Q.resize (dim_vector (nc, 1));
00406                   octave_idx_type *q = Q.fortran_vec ();
00407 
00408                   octave_idx_type do_recip;
00409                   status = UMFPACK_DNAME (get_numeric) (Ltp, Ltj,
00410                                                    Ltx, Up, Uj, Ux, p, q,
00411                                                    0, &do_recip,
00412                                                    Rx, Numeric) ;
00413 
00414                   UMFPACK_DNAME (free_numeric) (&Numeric) ;
00415 
00416                   if (status < 0)
00417                     {
00418                       (*current_liboctave_error_handler)
00419                         ("SparseLU::SparseLU extracting LU factors failed");
00420 
00421                       UMFPACK_DNAME (report_status) (control, status);
00422                     }
00423                   else
00424                     {
00425                       Lfact = Lfact.transpose ();
00426 
00427                       if (do_recip)
00428                         for (octave_idx_type i = 0; i < nr; i++)
00429                           Rx[i] = 1.0 / Rx[i];
00430 
00431                       UMFPACK_DNAME (report_matrix) (nr, n_inner,
00432                                                 Lfact.cidx (),
00433                                                 Lfact.ridx (),
00434                                                 Lfact.data (),
00435                                                 1, control);
00436                       UMFPACK_DNAME (report_matrix) (n_inner, nc,
00437                                                 Ufact.cidx (),
00438                                                 Ufact.ridx (),
00439                                                 Ufact.data (),
00440                                                 1, control);
00441                       UMFPACK_DNAME (report_perm) (nr, p, control);
00442                       UMFPACK_DNAME (report_perm) (nc, q, control);
00443                     }
00444 
00445                   UMFPACK_DNAME (report_info) (control, info);
00446                 }
00447             }
00448         }
00449 
00450       if (udiag)
00451         (*current_liboctave_error_handler)
00452           ("Option udiag of incomplete LU not implemented");
00453     }
00454 #else
00455   (*current_liboctave_error_handler) ("UMFPACK not installed");
00456 #endif
00457 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines