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 "SparseCmplxLU.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 <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
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
00081 tmp = octave_sparse_params::get_key ("autoamd");
00082 if (!xisnan (tmp))
00083 Control (UMFPACK_FIXQ) = tmp;
00084
00085
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
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
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
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
00324
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 }