00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
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
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
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
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 }