SparseCmplxLU.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 "SparseCmplxLU.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 <SparseComplexMatrix, Complex, SparseMatrix, double>;
00042 
00043 #include "oct-sparse.h"
00044 
00045 SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a,
00046                                   const Matrix& piv_thres, bool scale)
00047 {
00048 #ifdef HAVE_UMFPACK
00049   octave_idx_type nr = a.rows ();
00050   octave_idx_type nc = a.cols ();
00051 
00052   // Setup the control parameters
00053   Matrix Control (UMFPACK_CONTROL, 1);
00054   double *control = Control.fortran_vec ();
00055   UMFPACK_ZNAME (defaults) (control);
00056 
00057   double tmp = octave_sparse_params::get_key ("spumoni");
00058   if (!xisnan (tmp))
00059     Control (UMFPACK_PRL) = tmp;
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   // Turn-off UMFPACK scaling for LU
00086   if (scale)
00087     Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
00088   else
00089     Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
00090 
00091   UMFPACK_ZNAME (report_control) (control);
00092 
00093   const octave_idx_type *Ap = a.cidx ();
00094   const octave_idx_type *Ai = a.ridx ();
00095   const Complex *Ax = a.data ();
00096 
00097   UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai,
00098                                  reinterpret_cast<const double *> (Ax),
00099                                  0, 1, control);
00100 
00101   void *Symbolic;
00102   Matrix Info (1, UMFPACK_INFO);
00103   double *info = Info.fortran_vec ();
00104   int status = UMFPACK_ZNAME (qsymbolic) (nr, nc, Ap, Ai,
00105                                           reinterpret_cast<const double *> (Ax),
00106                                           0, 0,
00107                                           &Symbolic, control, info);
00108 
00109   if (status < 0)
00110     {
00111       (*current_liboctave_error_handler)
00112             ("SparseComplexLU::SparseComplexLU symbolic factorization failed");
00113 
00114       UMFPACK_ZNAME (report_status) (control, status);
00115       UMFPACK_ZNAME (report_info) (control, info);
00116 
00117       UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
00118     }
00119   else
00120     {
00121       UMFPACK_ZNAME (report_symbolic) (Symbolic, control);
00122 
00123       void *Numeric;
00124       status = UMFPACK_ZNAME (numeric) (Ap, Ai,
00125                                         reinterpret_cast<const double *> (Ax),
00126                                         0, Symbolic, &Numeric, control,
00127                                         info);
00128       UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
00129 
00130       cond = Info (UMFPACK_RCOND);
00131 
00132       if (status < 0)
00133         {
00134           (*current_liboctave_error_handler)
00135             ("SparseComplexLU::SparseComplexLU numeric factorization failed");
00136 
00137           UMFPACK_ZNAME (report_status) (control, status);
00138           UMFPACK_ZNAME (report_info) (control, info);
00139 
00140           UMFPACK_ZNAME (free_numeric) (&Numeric);
00141         }
00142       else
00143         {
00144           UMFPACK_ZNAME (report_numeric) (Numeric, control);
00145 
00146           octave_idx_type lnz, unz, ignore1, ignore2, ignore3;
00147           status = UMFPACK_ZNAME (get_lunz) (&lnz, &unz, &ignore1,
00148                                         &ignore2, &ignore3, Numeric) ;
00149 
00150           if (status < 0)
00151             {
00152               (*current_liboctave_error_handler)
00153                 ("SparseComplexLU::SparseComplexLU extracting LU factors failed");
00154 
00155               UMFPACK_ZNAME (report_status) (control, status);
00156               UMFPACK_ZNAME (report_info) (control, info);
00157 
00158               UMFPACK_ZNAME (free_numeric) (&Numeric);
00159             }
00160           else
00161             {
00162               octave_idx_type n_inner = (nr < nc ? nr : nc);
00163 
00164               if (lnz < 1)
00165                 Lfact = SparseComplexMatrix (n_inner, nr,
00166                                              static_cast<octave_idx_type> (1));
00167               else
00168                 Lfact = SparseComplexMatrix (n_inner, nr, lnz);
00169 
00170               octave_idx_type *Ltp = Lfact.cidx ();
00171               octave_idx_type *Ltj = Lfact.ridx ();
00172               Complex *Ltx = Lfact.data ();
00173 
00174               if (unz < 1)
00175                 Ufact = SparseComplexMatrix (n_inner, nc,
00176                                              static_cast<octave_idx_type> (1));
00177               else
00178                 Ufact = SparseComplexMatrix (n_inner, nc, unz);
00179 
00180               octave_idx_type *Up = Ufact.cidx ();
00181               octave_idx_type *Uj = Ufact.ridx ();
00182               Complex *Ux = Ufact.data ();
00183 
00184               Rfact = SparseMatrix (nr, nr, nr);
00185               for (octave_idx_type i = 0; i < nr; i++)
00186                 {
00187                   Rfact.xridx (i) = i;
00188                   Rfact.xcidx (i) = i;
00189                 }
00190               Rfact.xcidx (nr) = nr;
00191               double *Rx = Rfact.data ();
00192 
00193               P.resize (dim_vector (nr, 1));
00194               octave_idx_type *p = P.fortran_vec ();
00195 
00196               Q.resize (dim_vector (nc, 1));
00197               octave_idx_type *q = Q.fortran_vec ();
00198 
00199               octave_idx_type do_recip;
00200               status = UMFPACK_ZNAME (get_numeric) (Ltp, Ltj,
00201                                                     reinterpret_cast<double *> (Ltx),
00202                                                     0, Up, Uj,
00203                                                     reinterpret_cast <double *> (Ux),
00204                                                     0, p, q, 0, 0,
00205                                                     &do_recip, Rx, Numeric);
00206 
00207               UMFPACK_ZNAME (free_numeric) (&Numeric) ;
00208 
00209               if (status < 0)
00210                 {
00211                   (*current_liboctave_error_handler)
00212                     ("SparseComplexLU::SparseComplexLU extracting LU factors failed");
00213 
00214                   UMFPACK_ZNAME (report_status) (control, status);
00215                 }
00216               else
00217                 {
00218                   Lfact = Lfact.transpose ();
00219 
00220                   if (do_recip)
00221                     for (octave_idx_type i = 0; i < nr; i++)
00222                       Rx[i] = 1.0 / Rx[i];
00223 
00224                   UMFPACK_ZNAME (report_matrix) (nr, n_inner,
00225                                             Lfact.cidx (), Lfact.ridx (),
00226                                             reinterpret_cast<double *> (Lfact.data()),
00227                                             0, 1, control);
00228 
00229                   UMFPACK_ZNAME (report_matrix) (n_inner, nc,
00230                                             Ufact.cidx (), Ufact.ridx (),
00231                                             reinterpret_cast<double *> (Ufact.data()),
00232                                             0, 1, control);
00233                   UMFPACK_ZNAME (report_perm) (nr, p, control);
00234                   UMFPACK_ZNAME (report_perm) (nc, q, control);
00235                 }
00236 
00237               UMFPACK_ZNAME (report_info) (control, info);
00238             }
00239         }
00240     }
00241 #else
00242   (*current_liboctave_error_handler) ("UMFPACK not installed");
00243 #endif
00244 }
00245 
00246 SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a,
00247                                   const ColumnVector& Qinit,
00248                                   const Matrix& piv_thres, bool scale,
00249                                   bool FixedQ, double droptol,
00250                                   bool milu, bool udiag)
00251 {
00252 #ifdef HAVE_UMFPACK
00253   if (milu)
00254     (*current_liboctave_error_handler)
00255       ("Modified incomplete LU not implemented");
00256   else
00257     {
00258       octave_idx_type nr = a.rows ();
00259       octave_idx_type nc = a.cols ();
00260 
00261       // Setup the control parameters
00262       Matrix Control (UMFPACK_CONTROL, 1);
00263       double *control = Control.fortran_vec ();
00264       UMFPACK_ZNAME (defaults) (control);
00265 
00266       double tmp = octave_sparse_params::get_key ("spumoni");
00267       if (!xisnan (tmp))
00268         Control (UMFPACK_PRL) = tmp;
00269       if (piv_thres.nelem() == 2)
00270         {
00271           tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0));
00272           if (!xisnan (tmp))
00273             Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
00274           tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1));
00275           if (!xisnan (tmp))
00276             Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
00277         }
00278       else
00279         {
00280           tmp = octave_sparse_params::get_key ("piv_tol");
00281           if (!xisnan (tmp))
00282             Control (UMFPACK_PIVOT_TOLERANCE) = tmp;
00283 
00284           tmp = octave_sparse_params::get_key ("sym_tol");
00285           if (!xisnan (tmp))
00286             Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp;
00287         }
00288 
00289       if (droptol >= 0.)
00290         Control (UMFPACK_DROPTOL) = droptol;
00291 
00292       // Set whether we are allowed to modify Q or not
00293       if (FixedQ)
00294         Control (UMFPACK_FIXQ) = 1.0;
00295       else
00296         {
00297           tmp = octave_sparse_params::get_key ("autoamd");
00298           if (!xisnan (tmp))
00299             Control (UMFPACK_FIXQ) = tmp;
00300         }
00301 
00302       // Turn-off UMFPACK scaling for LU
00303       if (scale)
00304         Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM;
00305       else
00306         Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE;
00307 
00308       UMFPACK_ZNAME (report_control) (control);
00309 
00310       const octave_idx_type *Ap = a.cidx ();
00311       const octave_idx_type *Ai = a.ridx ();
00312       const Complex *Ax = a.data ();
00313 
00314       UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai,
00315                                 reinterpret_cast<const double *> (Ax), 0,
00316                                 1, control);
00317 
00318       void *Symbolic;
00319       Matrix Info (1, UMFPACK_INFO);
00320       double *info = Info.fortran_vec ();
00321       int status;
00322 
00323       // Null loop so that qinit is imediately deallocated when not
00324       // needed
00325       do {
00326         OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc);
00327 
00328         for (octave_idx_type i = 0; i < nc; i++)
00329           qinit [i] = static_cast<octave_idx_type> (Qinit (i));
00330 
00331         status = UMFPACK_ZNAME (qsymbolic) (nr, nc, Ap, Ai,
00332                                        reinterpret_cast<const double *> (Ax),
00333                                        0, qinit, &Symbolic, control,
00334                                        info);
00335       } while (0);
00336 
00337       if (status < 0)
00338         {
00339           (*current_liboctave_error_handler)
00340             ("SparseComplexLU::SparseComplexLU symbolic factorization failed");
00341 
00342           UMFPACK_ZNAME (report_status) (control, status);
00343           UMFPACK_ZNAME (report_info) (control, info);
00344 
00345           UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
00346         }
00347       else
00348         {
00349           UMFPACK_ZNAME (report_symbolic) (Symbolic, control);
00350 
00351           void *Numeric;
00352           status = UMFPACK_ZNAME (numeric) (Ap, Ai,
00353                                        reinterpret_cast<const double *> (Ax), 0,
00354                                        Symbolic, &Numeric, control, info) ;
00355           UMFPACK_ZNAME (free_symbolic) (&Symbolic) ;
00356 
00357           cond = Info (UMFPACK_RCOND);
00358 
00359           if (status < 0)
00360             {
00361               (*current_liboctave_error_handler)
00362                 ("SparseComplexLU::SparseComplexLU numeric factorization failed");
00363 
00364               UMFPACK_ZNAME (report_status) (control, status);
00365               UMFPACK_ZNAME (report_info) (control, info);
00366 
00367               UMFPACK_ZNAME (free_numeric) (&Numeric);
00368             }
00369           else
00370             {
00371               UMFPACK_ZNAME (report_numeric) (Numeric, control);
00372 
00373               octave_idx_type lnz, unz, ignore1, ignore2, ignore3;
00374               status = UMFPACK_ZNAME (get_lunz) (&lnz, &unz,
00375                                             &ignore1, &ignore2, &ignore3, Numeric);
00376 
00377               if (status < 0)
00378                 {
00379                   (*current_liboctave_error_handler)
00380                     ("SparseComplexLU::SparseComplexLU extracting LU factors failed");
00381 
00382                   UMFPACK_ZNAME (report_status) (control, status);
00383                   UMFPACK_ZNAME (report_info) (control, info);
00384 
00385                   UMFPACK_ZNAME (free_numeric) (&Numeric);
00386                 }
00387               else
00388                 {
00389                   octave_idx_type n_inner = (nr < nc ? nr : nc);
00390 
00391                   if (lnz < 1)
00392                     Lfact = SparseComplexMatrix (n_inner, nr,
00393                        static_cast<octave_idx_type> (1));
00394                   else
00395                     Lfact = SparseComplexMatrix (n_inner, nr, lnz);
00396 
00397                   octave_idx_type *Ltp = Lfact.cidx ();
00398                   octave_idx_type *Ltj = Lfact.ridx ();
00399                   Complex *Ltx = Lfact.data ();
00400 
00401                   if (unz < 1)
00402                     Ufact = SparseComplexMatrix (n_inner, nc,
00403                        static_cast<octave_idx_type> (1));
00404                   else
00405                     Ufact = SparseComplexMatrix  (n_inner, nc, unz);
00406 
00407                   octave_idx_type *Up = Ufact.cidx ();
00408                   octave_idx_type *Uj = Ufact.ridx ();
00409                   Complex *Ux = Ufact.data ();
00410 
00411                   Rfact = SparseMatrix (nr, nr, nr);
00412                   for (octave_idx_type i = 0; i < nr; i++)
00413                     {
00414                       Rfact.xridx (i) = i;
00415                       Rfact.xcidx (i) = i;
00416                     }
00417                   Rfact.xcidx (nr) = nr;
00418                   double *Rx = Rfact.data ();
00419 
00420                   P.resize (dim_vector (nr, 1));
00421                   octave_idx_type *p = P.fortran_vec ();
00422 
00423                   Q.resize (dim_vector (nc, 1));
00424                   octave_idx_type *q = Q.fortran_vec ();
00425 
00426                   octave_idx_type do_recip;
00427                   status =
00428                     UMFPACK_ZNAME (get_numeric) (Ltp, Ltj,
00429                                             reinterpret_cast<double *> (Ltx),
00430                                             0, Up, Uj,
00431                                             reinterpret_cast<double *> (Ux),
00432                                             0, p, q, 0, 0,
00433                                             &do_recip, Rx, Numeric) ;
00434 
00435                   UMFPACK_ZNAME (free_numeric) (&Numeric) ;
00436 
00437                   if (status < 0)
00438                     {
00439                       (*current_liboctave_error_handler)
00440                         ("SparseComplexLU::SparseComplexLU extracting LU factors failed");
00441 
00442                       UMFPACK_ZNAME (report_status) (control, status);
00443                     }
00444                   else
00445                     {
00446                       Lfact = Lfact.transpose ();
00447 
00448                       if (do_recip)
00449                         for (octave_idx_type i = 0; i < nr; i++)
00450                           Rx[i] = 1.0 / Rx[i];
00451 
00452                       UMFPACK_ZNAME (report_matrix) (nr, n_inner,
00453                                                 Lfact.cidx (),
00454                                                 Lfact.ridx (),
00455                                                 reinterpret_cast<double *> (Lfact.data()),
00456                                                 0, 1, control);
00457 
00458                       UMFPACK_ZNAME (report_matrix) (n_inner, nc,
00459                                                 Ufact.cidx (),
00460                                                 Ufact.ridx (),
00461                                                 reinterpret_cast<double *> (Ufact.data()),
00462                                                 0, 1, control);
00463                       UMFPACK_ZNAME (report_perm) (nr, p, control);
00464                       UMFPACK_ZNAME (report_perm) (nc, q, control);
00465                     }
00466 
00467                   UMFPACK_ZNAME (report_info) (control, info);
00468                 }
00469             }
00470         }
00471 
00472       if (udiag)
00473         (*current_liboctave_error_handler)
00474           ("Option udiag of incomplete LU not implemented");
00475     }
00476 #else
00477   (*current_liboctave_error_handler) ("UMFPACK not installed");
00478 #endif
00479 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines