5164
|
1 /* |
|
2 |
7017
|
3 Copyright (C) 2004, 2005, 2006, 2007 David Bateman |
7016
|
4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Andy Adler |
|
5 |
|
6 This file is part of Octave. |
5164
|
7 |
|
8 Octave is free software; you can redistribute it and/or modify it |
|
9 under the terms of the GNU General Public License as published by the |
7016
|
10 Free Software Foundation; either version 3 of the License, or (at your |
|
11 option) any later version. |
5164
|
12 |
|
13 Octave is distributed in the hope that it will be useful, but WITHOUT |
|
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
16 for more details. |
|
17 |
|
18 You should have received a copy of the GNU General Public License |
7016
|
19 along with Octave; see the file COPYING. If not, see |
|
20 <http://www.gnu.org/licenses/>. |
5164
|
21 |
|
22 */ |
|
23 |
|
24 #ifdef HAVE_CONFIG_H |
|
25 #include <config.h> |
|
26 #endif |
|
27 |
|
28 #include <vector> |
|
29 |
|
30 #include "lo-error.h" |
|
31 |
|
32 #include "SparseCmplxLU.h" |
|
33 #include "oct-spparms.h" |
|
34 |
|
35 // Instantiate the base LU class for the types we need. |
|
36 |
|
37 #include "sparse-base-lu.h" |
|
38 #include "sparse-base-lu.cc" |
|
39 |
|
40 template class sparse_base_lu <SparseComplexMatrix, Complex, SparseMatrix, double>; |
|
41 |
5451
|
42 #include "oct-sparse.h" |
5164
|
43 |
|
44 SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a, |
|
45 double piv_thres) |
|
46 { |
5203
|
47 #ifdef HAVE_UMFPACK |
5275
|
48 octave_idx_type nr = a.rows (); |
|
49 octave_idx_type nc = a.cols (); |
5164
|
50 |
|
51 // Setup the control parameters |
|
52 Matrix Control (UMFPACK_CONTROL, 1); |
|
53 double *control = Control.fortran_vec (); |
5322
|
54 UMFPACK_ZNAME (defaults) (control); |
5164
|
55 |
5893
|
56 double tmp = octave_sparse_params::get_key ("spumoni"); |
5164
|
57 if (!xisnan (tmp)) |
|
58 Control (UMFPACK_PRL) = tmp; |
|
59 if (piv_thres >= 0.) |
|
60 { |
|
61 piv_thres = (piv_thres > 1. ? 1. : piv_thres); |
|
62 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; |
|
63 Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; |
|
64 } |
|
65 else |
|
66 { |
5893
|
67 tmp = octave_sparse_params::get_key ("piv_tol"); |
5164
|
68 if (!xisnan (tmp)) |
|
69 { |
|
70 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; |
|
71 Control (UMFPACK_PIVOT_TOLERANCE) = tmp; |
|
72 } |
|
73 } |
|
74 |
|
75 // Set whether we are allowed to modify Q or not |
5893
|
76 tmp = octave_sparse_params::get_key ("autoamd"); |
5164
|
77 if (!xisnan (tmp)) |
|
78 Control (UMFPACK_FIXQ) = tmp; |
|
79 |
|
80 // Turn-off UMFPACK scaling for LU |
|
81 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; |
|
82 |
5322
|
83 UMFPACK_ZNAME (report_control) (control); |
5164
|
84 |
5275
|
85 const octave_idx_type *Ap = a.cidx (); |
|
86 const octave_idx_type *Ai = a.ridx (); |
5164
|
87 const Complex *Ax = a.data (); |
|
88 |
5322
|
89 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai, |
5760
|
90 reinterpret_cast<const double *> (Ax), |
|
91 NULL, 1, control); |
5164
|
92 |
|
93 void *Symbolic; |
|
94 Matrix Info (1, UMFPACK_INFO); |
|
95 double *info = Info.fortran_vec (); |
5322
|
96 int status = UMFPACK_ZNAME (qsymbolic) (nr, nc, Ap, Ai, |
5760
|
97 reinterpret_cast<const double *> (Ax), |
|
98 NULL, NULL, |
|
99 &Symbolic, control, info); |
5164
|
100 |
|
101 if (status < 0) |
|
102 { |
|
103 (*current_liboctave_error_handler) |
|
104 ("SparseComplexLU::SparseComplexLU symbolic factorization failed"); |
|
105 |
5322
|
106 UMFPACK_ZNAME (report_status) (control, status); |
|
107 UMFPACK_ZNAME (report_info) (control, info); |
5164
|
108 |
5322
|
109 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; |
5164
|
110 } |
|
111 else |
|
112 { |
5322
|
113 UMFPACK_ZNAME (report_symbolic) (Symbolic, control); |
5164
|
114 |
|
115 void *Numeric; |
5322
|
116 status = UMFPACK_ZNAME (numeric) (Ap, Ai, |
5760
|
117 reinterpret_cast<const double *> (Ax), |
|
118 NULL, Symbolic, &Numeric, control, |
|
119 info); |
5322
|
120 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; |
5164
|
121 |
|
122 cond = Info (UMFPACK_RCOND); |
|
123 |
|
124 if (status < 0) |
|
125 { |
|
126 (*current_liboctave_error_handler) |
|
127 ("SparseComplexLU::SparseComplexLU numeric factorization failed"); |
|
128 |
5322
|
129 UMFPACK_ZNAME (report_status) (control, status); |
|
130 UMFPACK_ZNAME (report_info) (control, info); |
5164
|
131 |
5322
|
132 UMFPACK_ZNAME (free_numeric) (&Numeric); |
5164
|
133 } |
|
134 else |
|
135 { |
5322
|
136 UMFPACK_ZNAME (report_numeric) (Numeric, control); |
5164
|
137 |
5322
|
138 octave_idx_type lnz, unz, ignore1, ignore2, ignore3; |
|
139 status = UMFPACK_ZNAME (get_lunz) (&lnz, &unz, &ignore1, |
|
140 &ignore2, &ignore3, Numeric) ; |
5164
|
141 |
|
142 if (status < 0) |
|
143 { |
|
144 (*current_liboctave_error_handler) |
|
145 ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); |
|
146 |
5322
|
147 UMFPACK_ZNAME (report_status) (control, status); |
|
148 UMFPACK_ZNAME (report_info) (control, info); |
5164
|
149 |
5322
|
150 UMFPACK_ZNAME (free_numeric) (&Numeric); |
5164
|
151 } |
|
152 else |
|
153 { |
5322
|
154 octave_idx_type n_inner = (nr < nc ? nr : nc); |
5164
|
155 |
|
156 if (lnz < 1) |
5322
|
157 Lfact = SparseComplexMatrix (n_inner, nr, |
5275
|
158 static_cast<octave_idx_type> (1)); |
5164
|
159 else |
5322
|
160 Lfact = SparseComplexMatrix (n_inner, nr, lnz); |
5164
|
161 |
5275
|
162 octave_idx_type *Ltp = Lfact.cidx (); |
|
163 octave_idx_type *Ltj = Lfact.ridx (); |
5164
|
164 Complex *Ltx = Lfact.data (); |
|
165 |
|
166 if (unz < 1) |
5322
|
167 Ufact = SparseComplexMatrix (n_inner, nc, |
5275
|
168 static_cast<octave_idx_type> (1)); |
5164
|
169 else |
5322
|
170 Ufact = SparseComplexMatrix (n_inner, nc, unz); |
5164
|
171 |
5275
|
172 octave_idx_type *Up = Ufact.cidx (); |
|
173 octave_idx_type *Uj = Ufact.ridx (); |
5164
|
174 Complex *Ux = Ufact.data (); |
|
175 |
|
176 P.resize (nr); |
5322
|
177 octave_idx_type *p = P.fortran_vec (); |
5164
|
178 |
|
179 Q.resize (nc); |
5322
|
180 octave_idx_type *q = Q.fortran_vec (); |
5164
|
181 |
5322
|
182 octave_idx_type do_recip; |
|
183 status = UMFPACK_ZNAME (get_numeric) (Ltp, Ltj, |
5760
|
184 reinterpret_cast<double *> (Ltx), |
|
185 NULL, Up, Uj, |
|
186 reinterpret_cast <double *> (Ux), |
|
187 NULL, p, q, NULL, NULL, |
|
188 &do_recip, NULL, Numeric); |
5164
|
189 |
5322
|
190 UMFPACK_ZNAME (free_numeric) (&Numeric) ; |
5164
|
191 |
|
192 if (status < 0 || do_recip) |
|
193 { |
|
194 (*current_liboctave_error_handler) |
|
195 ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); |
|
196 |
5322
|
197 UMFPACK_ZNAME (report_status) (control, status); |
5164
|
198 } |
|
199 else |
|
200 { |
|
201 Lfact = Lfact.transpose (); |
|
202 |
5322
|
203 UMFPACK_ZNAME (report_matrix) (nr, n_inner, |
|
204 Lfact.cidx (), Lfact.ridx (), |
5760
|
205 reinterpret_cast<double *> (Lfact.data()), |
5164
|
206 NULL, 1, control); |
|
207 |
5322
|
208 UMFPACK_ZNAME (report_matrix) (n_inner, nc, |
|
209 Ufact.cidx (), Ufact.ridx (), |
5760
|
210 reinterpret_cast<double *> (Ufact.data()), |
5164
|
211 NULL, 1, control); |
5322
|
212 UMFPACK_ZNAME (report_perm) (nr, p, control); |
|
213 UMFPACK_ZNAME (report_perm) (nc, q, control); |
5164
|
214 } |
|
215 |
5322
|
216 UMFPACK_ZNAME (report_info) (control, info); |
5164
|
217 } |
|
218 } |
|
219 } |
5203
|
220 #else |
|
221 (*current_liboctave_error_handler) ("UMFPACK not installed"); |
|
222 #endif |
5164
|
223 } |
|
224 |
|
225 SparseComplexLU::SparseComplexLU (const SparseComplexMatrix& a, |
|
226 const ColumnVector& Qinit, |
5282
|
227 double piv_thres, bool FixedQ, |
|
228 double droptol, bool milu, bool udiag) |
5164
|
229 { |
5203
|
230 #ifdef HAVE_UMFPACK |
5282
|
231 if (milu) |
|
232 (*current_liboctave_error_handler) |
|
233 ("Modified incomplete LU not implemented"); |
5164
|
234 else |
|
235 { |
5282
|
236 octave_idx_type nr = a.rows (); |
|
237 octave_idx_type nc = a.cols (); |
5164
|
238 |
5282
|
239 // Setup the control parameters |
|
240 Matrix Control (UMFPACK_CONTROL, 1); |
|
241 double *control = Control.fortran_vec (); |
5322
|
242 UMFPACK_ZNAME (defaults) (control); |
5164
|
243 |
5893
|
244 double tmp = octave_sparse_params::get_key ("spumoni"); |
5282
|
245 if (!xisnan (tmp)) |
|
246 Control (UMFPACK_PRL) = tmp; |
|
247 if (piv_thres >= 0.) |
|
248 { |
|
249 piv_thres = (piv_thres > 1. ? 1. : piv_thres); |
|
250 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = piv_thres; |
|
251 Control (UMFPACK_PIVOT_TOLERANCE) = piv_thres; |
|
252 } |
|
253 else |
|
254 { |
5893
|
255 tmp = octave_sparse_params::get_key ("piv_tol"); |
5282
|
256 if (!xisnan (tmp)) |
|
257 { |
|
258 Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; |
|
259 Control (UMFPACK_PIVOT_TOLERANCE) = tmp; |
|
260 } |
|
261 } |
5164
|
262 |
5282
|
263 if (droptol >= 0.) |
|
264 Control (UMFPACK_DROPTOL) = droptol; |
5164
|
265 |
5282
|
266 // Set whether we are allowed to modify Q or not |
|
267 if (FixedQ) |
|
268 Control (UMFPACK_FIXQ) = 1.0; |
|
269 else |
|
270 { |
5893
|
271 tmp = octave_sparse_params::get_key ("autoamd"); |
5282
|
272 if (!xisnan (tmp)) |
|
273 Control (UMFPACK_FIXQ) = tmp; |
|
274 } |
5164
|
275 |
5282
|
276 // Turn-off UMFPACK scaling for LU |
|
277 Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; |
5164
|
278 |
5322
|
279 UMFPACK_ZNAME (report_control) (control); |
5282
|
280 |
|
281 const octave_idx_type *Ap = a.cidx (); |
|
282 const octave_idx_type *Ai = a.ridx (); |
|
283 const Complex *Ax = a.data (); |
5164
|
284 |
5322
|
285 UMFPACK_ZNAME (report_matrix) (nr, nc, Ap, Ai, |
5760
|
286 reinterpret_cast<const double *> (Ax), NULL, |
5282
|
287 1, control); |
|
288 |
|
289 void *Symbolic; |
|
290 Matrix Info (1, UMFPACK_INFO); |
|
291 double *info = Info.fortran_vec (); |
|
292 int status; |
5164
|
293 |
5282
|
294 // Null loop so that qinit is imediately deallocated when not |
|
295 // needed |
|
296 do { |
5322
|
297 OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc); |
5164
|
298 |
5322
|
299 for (octave_idx_type i = 0; i < nc; i++) |
|
300 qinit [i] = static_cast<octave_idx_type> (Qinit (i)); |
5164
|
301 |
5322
|
302 status = UMFPACK_ZNAME (qsymbolic) (nr, nc, Ap, Ai, |
5760
|
303 reinterpret_cast<const double *> (Ax), |
5282
|
304 NULL, qinit, &Symbolic, control, |
|
305 info); |
|
306 } while (0); |
5164
|
307 |
|
308 if (status < 0) |
|
309 { |
|
310 (*current_liboctave_error_handler) |
5282
|
311 ("SparseComplexLU::SparseComplexLU symbolic factorization failed"); |
5164
|
312 |
5322
|
313 UMFPACK_ZNAME (report_status) (control, status); |
|
314 UMFPACK_ZNAME (report_info) (control, info); |
5164
|
315 |
5322
|
316 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; |
5164
|
317 } |
|
318 else |
|
319 { |
5322
|
320 UMFPACK_ZNAME (report_symbolic) (Symbolic, control); |
5164
|
321 |
5282
|
322 void *Numeric; |
5322
|
323 status = UMFPACK_ZNAME (numeric) (Ap, Ai, |
5760
|
324 reinterpret_cast<const double *> (Ax), NULL, |
5282
|
325 Symbolic, &Numeric, control, info) ; |
5322
|
326 UMFPACK_ZNAME (free_symbolic) (&Symbolic) ; |
5282
|
327 |
|
328 cond = Info (UMFPACK_RCOND); |
|
329 |
5164
|
330 if (status < 0) |
|
331 { |
|
332 (*current_liboctave_error_handler) |
5282
|
333 ("SparseComplexLU::SparseComplexLU numeric factorization failed"); |
5164
|
334 |
5322
|
335 UMFPACK_ZNAME (report_status) (control, status); |
|
336 UMFPACK_ZNAME (report_info) (control, info); |
5164
|
337 |
5322
|
338 UMFPACK_ZNAME (free_numeric) (&Numeric); |
5164
|
339 } |
|
340 else |
|
341 { |
5322
|
342 UMFPACK_ZNAME (report_numeric) (Numeric, control); |
5164
|
343 |
5322
|
344 octave_idx_type lnz, unz, ignore1, ignore2, ignore3; |
|
345 status = UMFPACK_ZNAME (get_lunz) (&lnz, &unz, |
|
346 &ignore1, &ignore2, &ignore3, Numeric); |
5282
|
347 |
|
348 if (status < 0) |
5164
|
349 { |
|
350 (*current_liboctave_error_handler) |
|
351 ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); |
|
352 |
5322
|
353 UMFPACK_ZNAME (report_status) (control, status); |
|
354 UMFPACK_ZNAME (report_info) (control, info); |
5282
|
355 |
5322
|
356 UMFPACK_ZNAME (free_numeric) (&Numeric); |
5164
|
357 } |
|
358 else |
|
359 { |
5322
|
360 octave_idx_type n_inner = (nr < nc ? nr : nc); |
5282
|
361 |
|
362 if (lnz < 1) |
5322
|
363 Lfact = SparseComplexMatrix (n_inner, nr, |
5282
|
364 static_cast<octave_idx_type> (1)); |
|
365 else |
5322
|
366 Lfact = SparseComplexMatrix (n_inner, nr, lnz); |
5282
|
367 |
|
368 octave_idx_type *Ltp = Lfact.cidx (); |
|
369 octave_idx_type *Ltj = Lfact.ridx (); |
|
370 Complex *Ltx = Lfact.data (); |
5164
|
371 |
5282
|
372 if (unz < 1) |
5322
|
373 Ufact = SparseComplexMatrix (n_inner, nc, |
5282
|
374 static_cast<octave_idx_type> (1)); |
|
375 else |
5322
|
376 Ufact = SparseComplexMatrix (n_inner, nc, unz); |
5282
|
377 |
|
378 octave_idx_type *Up = Ufact.cidx (); |
|
379 octave_idx_type *Uj = Ufact.ridx (); |
|
380 Complex *Ux = Ufact.data (); |
|
381 |
|
382 P.resize (nr); |
5322
|
383 octave_idx_type *p = P.fortran_vec (); |
5282
|
384 |
|
385 Q.resize (nc); |
5322
|
386 octave_idx_type *q = Q.fortran_vec (); |
5164
|
387 |
5322
|
388 octave_idx_type do_recip; |
5282
|
389 status = |
5322
|
390 UMFPACK_ZNAME (get_numeric) (Ltp, Ltj, |
5760
|
391 reinterpret_cast<double *> (Ltx), |
5282
|
392 NULL, Up, Uj, |
5760
|
393 reinterpret_cast<double *> (Ux), |
5282
|
394 NULL, p, q, NULL, NULL, |
|
395 &do_recip, NULL, Numeric) ; |
|
396 |
5322
|
397 UMFPACK_ZNAME (free_numeric) (&Numeric) ; |
5282
|
398 |
|
399 if (status < 0 || do_recip) |
|
400 { |
|
401 (*current_liboctave_error_handler) |
|
402 ("SparseComplexLU::SparseComplexLU extracting LU factors failed"); |
|
403 |
5322
|
404 UMFPACK_ZNAME (report_status) (control, |
|
405 status); |
5282
|
406 } |
|
407 else |
|
408 { |
|
409 Lfact = Lfact.transpose (); |
|
410 |
5322
|
411 UMFPACK_ZNAME (report_matrix) (nr, n_inner, |
5282
|
412 Lfact.cidx (), |
|
413 Lfact.ridx (), |
5760
|
414 reinterpret_cast<double *> (Lfact.data()), |
5282
|
415 NULL, 1, control); |
|
416 |
5322
|
417 UMFPACK_ZNAME (report_matrix) (n_inner, nc, |
5282
|
418 Ufact.cidx (), |
|
419 Ufact.ridx (), |
5760
|
420 reinterpret_cast<double *> (Ufact.data()), |
5282
|
421 NULL, 1, control); |
5322
|
422 UMFPACK_ZNAME (report_perm) (nr, p, control); |
|
423 UMFPACK_ZNAME (report_perm) (nc, q, control); |
5282
|
424 } |
|
425 |
5322
|
426 UMFPACK_ZNAME (report_info) (control, info); |
5164
|
427 } |
|
428 } |
|
429 } |
5282
|
430 |
|
431 if (udiag) |
|
432 (*current_liboctave_error_handler) |
|
433 ("Option udiag of incomplete LU not implemented"); |
5164
|
434 } |
5203
|
435 #else |
|
436 (*current_liboctave_error_handler) ("UMFPACK not installed"); |
|
437 #endif |
5164
|
438 } |
|
439 |
|
440 /* |
|
441 ;;; Local Variables: *** |
|
442 ;;; mode: C++ *** |
|
443 ;;; End: *** |
|
444 */ |
|
445 |