/[ascend]/trunk/base/generic/solver/linsolqr.h
ViewVC logotype

Contents of /trunk/base/generic/solver/linsolqr.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1013 - (show annotations) (download) (as text)
Wed Jan 3 03:41:35 2007 UTC (15 years, 7 months ago) by johnpye
File MIME type: text/x-chdr
File size: 39598 byte(s)
Added doxygen comments for linear routines in base/generic/solver.
Fixed up missing (still unimplemented) idalinear jacobian sjex.
1 /* ASCEND modelling environment
2 Copyright (C) 1990 Karl Michael Westerberg
3 Copyright (C) 1993 Joseph Zaher
4 Copyright (C) 1994 Boyd Safrit, Joseph Zaher, Benjamin Andrew Allan
5 Copyright (C) 1995 Benjamin Andrew Allan, Kirk Andre Abbott
6 Copyright (C) 2006 Carnegie Mellon University
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
22 *//** @file
23 * linsol II: Ascend Linear Equation Solver.
24 *
25 * A linear system consists of a coefficient matrix (A)
26 * and possibly several right-hand-sides (rhs). The
27 * solution vector x sought can be that of either
28 *<pre>
29 * T
30 * A x = rhs or A x = rhs
31 *</pre>
32 * depending on a specification inherent with rhs which
33 * dictates whether or not A should be transposed. If a
34 * rhs specifies transpose, then the vector itself is
35 * expected to be indexed by the original column numbers
36 * of the coefficient matrix and the solution vector shall
37 * be indexed by original row numbers. Otherwise, rhs
38 * is expected to be indexed by original row numbers while
39 * the solution can be referenced using original column
40 * numbers. The coefficient matrix and each rhs will be
41 * preserved throughout solving, except that the
42 * coefficient matrix may be permuted during reordering
43 * or (depending on the method) solving.
44 *
45 * The method of linear solution is an option new to
46 * linsolqr. Also, some of the data structures have been
47 * expanded as required. The factoring methods are
48 * enumerated and summarized below.
49 *
50 * Linsol is a general sparse solver. It uses mtx, though any
51 * proper sparse matrix package can be substituted. By
52 * proper, of course, we mean one with at least the
53 * functionality of mtx. If you find something with all
54 * the features of mtx that is faster than mtx, let us
55 * know, please. If you do any comparisons of linsol with
56 * other sparse codes (on sequential processors) also
57 * please let us know how you find its performance.
58 * You probably won't find algorithms for banded or
59 * symmetric matrices here. Why?
60 * The efficiency of most banded algorithms comes from
61 * the way they access memory with three assumptions:
62 * that all possible coefficient locations are known before
63 * a solution is attempted, that they are accessible
64 * in some ORDERED fashion, and that the matrix will not
65 * be reordered (except perhaps in very limited ways)
66 * during solution. Linsol is predicated on just
67 * the opposite assumptions at the moment.
68 * These assumptions would relieve the solver of
69 * memory allocation and a great deal of range checking.
70 * While we would do our flops efficiently with linsol/mtx
71 * on a banded matrix, the cost of accessing linear
72 * coefficients in an UNORDERED fashion is such that a good
73 * band, variable band, or symmetric skyline code making the
74 * ORDERED assumption will always beat linsol in speed,
75 * though perhaps not in robustness.
76 *
77 * Requires: #include <string.h>
78 * #include "utilities/ascConfig.h"
79 * #include "mtx.h"
80 *
81 * Each method is described here, including the unimplemented ones,
82 * however vaguely. By convention all methods assign unpivotable variables
83 * the value of 0.0 in the linear solution vector. This makes sense because
84 * the linear system usually arises from a nonlinear scheme wherein
85 * stepping in the unpivoted variables is left for a future iteration.
86 *
87 * The currently recommended methods are ranki_*2, in particular ba2.
88 *
89 * ranki_kw:
90 * Reordering method: SPK1, Stadtherr & Wood (1984), and like.
91 * The region used is confined to the main diagonal.
92 * The square region is reordered to lower triangular with spikes.
93 * Each spike is higher than or equal to all spikes to the left of it
94 * if the matrix is partitioned.
95 * Solution method: RANKI, Stadtherr & Wood
96 * Ref: Computers and Chemical Engineering (8)1 pp. 9-33 (1984)
97 * The square region is U/L factored with spikes dragged in to replace
98 * unacceptable pivots. Fill is in spike columns and
99 * dragged rows where it usually does take place.
100 * Numerically dependent rows and columns do not have dependencies
101 * automatically calculated. This is a change from linsol, so be
102 * careful in making comparisons.
103 * Authors: Karl Westerberg, Joe Zaher
104 * with some clean ups and restructuring by Ben Allan
105 *
106 * ranki_jz:
107 * As ranki_kw, except where ranki_kw looks only across the current row
108 * for pivots if the diagonal element is too small, ranki_jz also looks
109 * down the current column. This introduces additional spikes to the
110 * current block, but sometimes the overall effect is reduced fill. The
111 * main motivation is to broaden pivot choices on those problems
112 * where restricting the choice to the current row results in immediate
113 * explosions of fill due to a full subdiagonal and a moderately small
114 * pivot.
115 *
116 * ranki_kw2:
117 * ranki_jz2:
118 * As the ranki_XX factorizations, except uses drop tolerance and
119 * uses much faster bilevel matrices (master + slave matrix of mtx)
120 * to segregate the contents of U from L. Also, dependency information
121 * is not calculated automatically.
122 * Author: Ben Allan
123 *
124 * ranki_ba2:
125 * As the ranki_kw2 factorization, except pivot and row being eliminated
126 * are stored as linked lists/full org vectors (dual access) during
127 * elimination which removes the last significant quadratic effect from
128 * the ranki factorization.
129 *
130 * plain_qr:
131 * Reordering method: Transpose SPK1 (tspk1), LORA
132 * The region used may be rectangular, but will be modified
133 * if needed so that the upper left corner is on the diagonal.
134 * The region in sys->coef is not permuted in the solution process.
135 * Solution method:
136 * The rectangular region is QR factored with standard column pivoting
137 * modified by the pivot_tolerance. That is, at each step the column
138 * to factor in next is the leftmost col with norm alpha that satisfies
139 * alpha >= ptol * maxalpha.
140 * ptol = 1 --> Stewart's QRDC style pivoting.
141 * ptol = 0 --> no pivoting (Sometimes a dumb idea).
142 * plain_qr is to QRDC as ranki_kw is to LU factorization with strict
143 * partial pivoting.
144 * This implementation is best used on matrices where nrows about = ncols
145 * and data are not highly correlated.
146 * There are better QR methods (not available here) for vector processors,
147 * distributed processors, data fitting and so forth.
148 * Some care has been taken that the implementation here will scale up
149 * reasonably to larger matrices.
150 * Detailed references are given in the plain_qr section of the .c file.
151 * Author: Ben Allan
152 *
153 * cond_qr: (broken)
154 * Reordering method: Transpose SPK1 (tspk1)
155 * The region used is confined to the main diagonal.
156 * The square region is permuted in the solution process.
157 * Solution method:
158 * The square region is QR factored with pivoting by a local minimum
159 * fill criteria balanced against choosing pivots based on the
160 * incremental inverse R condition number.
161 * Ref:Incremental Condition Calculation and Column Selection,
162 * UMIACS TR 90-87, G.W.Stewart, July 1990)
163 * (Allan, Safrit, Westerberg, 1995)
164 * Authors: Ben Allan
165 *
166 * opt_qr:
167 * As cond_qr, except region may be underspecified (MxN, M < N)
168 * The region's upper left corner should be (or will be forced to be)
169 * on the main diagonal. The columns pivoted are expected to be a
170 * good basis. Solution is not a least squares solution of the
171 * transpose NxM problem; for this we need rowwise Householder
172 * transforms and spk1 reordering.
173 * Authors: Ben Allan
174 *
175 * ls_qr:
176 * As cond_qr, except region may be overspecified (MxN, M > N)
177 * Solves the system in a linear least squares sense.
178 * Authors: Ben Allan
179 *
180 * band_lu:
181 * symmetric_lu:
182 * (cholesky?)
183 * The best codes we can find already implemented to complement and/or
184 * verify our own. More detailed semantics unknown at this time.
185 *
186 * The parameters pivot_tolerance, condition_tolerance and drop_tolerance
187 * have semantics varying with the method.
188 * See the header of linsolqr_set_pivot_tolerance below for details.
189 * </pre>
190 *//*
191 by Karl Westerberg
192 Created: 2/6/90
193 Last in CVS: $Revision: 1.13 $ $Date: 1997/07/25 17:23:49 $ $Author: ballan $
194 QR options by Ben Allan
195 C version based on sqr.pas v1.5, Boyd Safrit (1994)
196
197 Dates: 06/90 - original version (KW)
198 04/91 - removed output assignment and partitioning
199 (belong in structural analysis) (JZ)
200 08/92 - added transpose ability (JZ)
201 01/94 - broke out linsol_invert() and linsol_solve() (JZ)
202 10/94 - reorganized for multiple methods and QR (BA)
203 moved drag operator to mtx (BA,JZ)
204 11/94 - added linsolqr_get_factors/inverse for debugging.BA
205 09/95 - added factor_class to better manage families. BA
206 09/95 - added ranki_*2 methods (BA)
207 09/95 - added gauss (broken) (KA)
208 11/96 - added ranki_ba2 method (BA)
209
210 */
211
212 #ifndef ASC_LINSOLQR_H
213 #define ASC_LINSOLQR_H
214
215 /** @addtogroup linear @{ */
216
217 #define LINSOLMTX_DEBUG FALSE
218 /**< Debug mode. */
219 #define LINQR_DROP_TOLERANCE 1.0e-16
220 /**< This is the default for drop tolerances in methods which use a drop tol */
221
222 typedef struct linsolqr_header *linsolqr_system_t;
223 /**< linsolqr_system_t is the linear system handle. */
224
225 enum factor_class {
226 unknown_c, /**< error handling class */
227 ranki = 100, /**< all ranki (and gauss until broken out) methods */
228 s_qr = 200 /**< all sparse qr methods */
229 };
230
231 enum reorder_method {
232 unknown_r, /**< error handling method */
233 natural = 1000, /**< do nothing reorder */
234 spk1 = 2000, /**< Stadtherr's SPK1 reordering */
235 tspk1 = 3000 /**< transpose of Stadtherr's SPK1 reordering good for gauss */
236 /* future work:
237 invspk1, spk1 then diagonally inverted
238 invtspk1, tspk1 then diagonally inverted
239 widespk1, spk1 of an MxN region, N > M
240 */
241 };
242
243 enum factor_method {
244 unknown_f = 0, /**< error handling method */
245 ranki_kw = 1, /**< original linsol method */
246 ranki_jz = 2, /**< original linsol method with pseudo-complete pivoting */
247 ranki_kw2 = 3, /**< better data structure version of ranki_kw, w/drop tol */
248 ranki_jz2 = 4, /**< better data structure version of ranki_jz, w/drop tol */
249 ranki_ka = 12, /**< kirks hacked verion of the basic method. */
250 plain_qr = 5, /**< rectangular col pivoted qr variants */
251 cond_qr = 6, /**< stewart-based sparse QR method new Coke */
252 ranki_ba2 = 7, /**< proper linked list implementation of ranki (dragfree) */
253 opt_qr = 8, /**< coming soon */
254 ls_qr = 9, /**< anticipated */
255 gauss_ba2 = 10, /**< anticipated */
256 symmetric_lu = 11 /**< anticipated */
257 };
258
259 ASC_DLLSPEC(int ) g_linsolqr_timing;
260 /**<
261 * If nonzero and certain internal defines are set, factorization
262 * generates a fill and timing message.
263 */
264
265 /* KAA_DEBUG */
266 /* unimplemented function
267 extern boolean linsolqr_col_is_a_spike (mtx_matrix_t mtx, int32 col);
268 */
269 /* Returns true if the column in question is a spike. */
270
271
272 /* Functions for managing interfaces */
273
274 extern char *linsolqr_rmethods(void);
275 /**<
276 * Returns a comma-separated list of the names of reordering methods
277 * implemented. If you implement a new method, update this
278 * function. Do not free the pointer returned.<br><br>
279 *
280 * Not all reorderings are appropriate to all factorizations.
281 */
282
283 ASC_DLLSPEC(char *) linsolqr_fmethods(void);
284 /**<
285 * Returns a comma-separated list of the names of factorization methods
286 * implemented. If you implement a new method, update this
287 * function. Do not free the pointer returned. The string returned
288 * will contain no whitespace of any sort, tabs, blanks, or \n.
289 */
290
291 extern enum reorder_method linsolqr_rmethod_to_enum(char *s);
292 /**<
293 * Returns the enum of a reorder method with the name s.
294 * If you implement a new method, update this function.
295 */
296
297 extern enum factor_method linsolqr_fmethod_to_enum(char *s);
298 /**<
299 * Returns the enum of a factor method with the name s.
300 * If you implement a new method, update this function.
301 */
302
303 extern enum factor_class linsolqr_fmethod_to_fclass(enum factor_method fm);
304 /**<
305 * Returns the enum of the factor class containing the method given.
306 * If you implement a new method or class, update this function.
307 */
308
309 ASC_DLLSPEC(char *) linsolqr_enum_to_rmethod(enum reorder_method m);
310 /**<
311 * <!-- s=linsolqr_enum_to_rmethod(m); -->
312 *
313 * Returns the name of a reorder method with the enum m.
314 * If you implement a new method, update this function.
315 * Do not free the name.
316 */
317
318 extern char *linsolqr_enum_to_fmethod(enum factor_method m);
319 /**<
320 * Returns the name of a factor method with the enum m.
321 * If you implement a new method, update this function.
322 * Do not free the name.
323 */
324
325 ASC_DLLSPEC(char *) linsolqr_rmethod_description(enum reorder_method meth);
326 /**<
327 * Returns a string describing the method inquired on. Do not mess
328 * with the string: linsolqr owns it.
329 * If you implement a new method, update this function.
330 */
331
332 ASC_DLLSPEC(char *) linsolqr_fmethod_description(enum factor_method meth);
333 /**<
334 * Returns a string describing the method inquired on. Do not mess
335 * with the string: linsolqr owns it.
336 * If you implement a new method, update this function.
337 */
338
339 /* Functions for specifying problems and controlling them */
340
341 extern linsolqr_system_t linsolqr_create(void);
342 /**<
343 * Creates a linear system and returns a pointer to it. Initially the
344 * system has no coefficient matrix and no rhs.
345 */
346
347 extern void linsolqr_destroy(linsolqr_system_t sys);
348 /**<
349 * Destroys the linear system. The coefficient matrix and each rhs are
350 * not destroyed by this call.
351 */
352
353 extern void linsolqr_set_matrix(linsolqr_system_t sys, mtx_matrix_t mtx);
354 /**<
355 * Sets the coefficient matrix to mtx.
356 */
357
358 ASC_DLLSPEC(void ) linsolqr_set_region(linsolqr_system_t sys, mtx_region_t region);
359 /**<
360 * Sets the reg to region.
361 */
362
363 ASC_DLLSPEC(mtx_matrix_t ) linsolqr_get_matrix(linsolqr_system_t sys);
364 /**<
365 * Returns the coefficient matrix.
366 */
367
368 ASC_DLLSPEC(void ) linsolqr_add_rhs(linsolqr_system_t sys,
369 real64 *rhs,
370 boolean transpose);
371 /**<
372 * Adds the given rhs to the collection of rhs's already part of the
373 * system.
374 *
375 * You continue to be responsible for deallocating rhs. We do not take
376 * over management of that memory. Do not free the rhs you have given
377 * us without calling linsolqr_remove_rhs first.<br><br>
378 *
379 * Rhs should point to an array of reals indexed by original
380 * column number if the linear system is to be solved using the transpose
381 * of the matrix or by original row number if the matrix is not to be
382 * transposed. This is determined using the boolean transpose. The
383 * rhs should be refered to in the future by its pointer.
384 * <pre>
385 * For the mathematically impaired:
386 * M' denotes Transpose(M).
387 *
388 * transpose==FALSE --> rhs will be solved for x in A x = b.
389 * --> rhs b is an org row indexed column vector.
390 * --> x is an org col indexed column vector.
391 * --> yields dx = Newton direction in J.dx = -f
392 * if the b given is -f.
393 *
394 * transpose==TRUE --> rhs will be solved for y in A' y = d.
395 * --> rhs d is an org column indexed column vector.
396 * --> y is an org row indexed column vector.
397 * --> yields dx = Newton direction in J'.dx = -f.
398 * if the d given is -f and f,dx are properly indexed.
399 * This may be useful if A was created using
400 * mtx_transpose in order to improve factorization.
401 *
402 * Useful matrix identity: (M')^-1 == (M^-1)' for invertible M.
403 * </pre>
404 */
405
406 ASC_DLLSPEC(void ) linsolqr_remove_rhs(linsolqr_system_t sys, real64 *rhs);
407 /**<
408 * Removes the given rhs from the system. The rhs is not destroyed, just
409 * removed from the system.
410 */
411
412 extern int32 linsolqr_number_of_rhs(linsolqr_system_t sys);
413 /**<
414 * Returns the number of rhs's currently part of the system.
415 */
416
417 ASC_DLLSPEC(real64 *) linsolqr_get_rhs(linsolqr_system_t sys, int n);
418 /**<
419 * Returns the n-th rhs, where rhs's are indexed in the order they were
420 * added using linsolqr_add_rhs() from 0 to (# rhs's)-1. NULL is returned
421 * if the index is out of range.
422 */
423
424 ASC_DLLSPEC(void ) linsolqr_matrix_was_changed(linsolqr_system_t sys);
425 /**<
426 * Informs the solver that a numerical value of a non-zero was changed.
427 * This must be called whenever any numerical changes to the matrix are
428 * made.
429 */
430
431 ASC_DLLSPEC(void ) linsolqr_rhs_was_changed(linsolqr_system_t sys,
432 real64 *rhs);
433 /**<
434 * Informs the solver that the given rhs has been modified. This must be
435 * called whenever the rhs is modified.
436 */
437
438 extern void linsolqr_set_pivot_zero(linsolqr_system_t sys,
439 real64 pivot_zero);
440 /**<
441 * Sets the pivot zero for the system. Pivots less than or equal to
442 * this value are regarded as zero. linsolqr_set_pivot_zero() will
443 * automatically call linsolqr_matrix_was_changed().
444 */
445 extern real64 linsolqr_pivot_zero(linsolqr_system_t sys);
446 /**<
447 * Gets the pivot zero for the system. Pivots less than or equal to
448 * this value are regarded as zero.
449 */
450
451 extern void linsolqr_set_pivot_tolerance(linsolqr_system_t sys, real64 ptol);
452 /**< See discussion under linsolqr_drop_tolerance(). */
453 extern real64 linsolqr_pivot_tolerance(linsolqr_system_t sys);
454 /**< See discussion under linsolqr_drop_tolerance(). */
455 extern void linsolqr_set_condition_tolerance(linsolqr_system_t sys, real64 ctol);
456 /**< See discussion under linsolqr_drop_tolerance(). */
457 extern real64 linsolqr_condition_tolerance(linsolqr_system_t sys);
458 /**< See discussion under linsolqr_drop_tolerance(). */
459 extern void linsolqr_set_drop_tolerance(linsolqr_system_t sys, real64 dtol);
460 /**< See discussion under linsolqr_drop_tolerance(). */
461 extern real64 linsolqr_drop_tolerance(linsolqr_system_t sys);
462 /**<
463 * <pre>
464 * linsolqr_set_pivot_tolerance(sys,ptol)
465 * ptol = linsolqr_pivot_tolerance(sys)
466 *
467 * linsolqr_set_condition_tolerance(sys,ctol)
468 * ctol = linsolqr_condition_tolerance(sys)
469 *
470 * linsolqr_set_drop_tolerance(sys,dtol)
471 * dtol = linsolqr_drop_tolerance(sys)
472 *
473 * linsolqr_system_t sys;
474 * real64 ptol, ctol,dtol;
475 *
476 * Sets/gets the pivot/condition/drop tolerance for the system. Semantics of
477 * tolerances vary with method. Not to be confused with pivot zero, epsilon.
478 *
479 * pivot_tolerance: Pivots less than this fraction of the maximum pivot
480 * value in the same row or column (depending on method) are disregarded.
481 *
482 * ranki_kw: pivot_tolerance applies to row. condition_tolerance ignored.
483 * ranki_jz: pivot_tolerance applies to row and col. condition ignored.
484 * ranki_ba2:
485 * ranki_kw2:
486 * ranki_jz2: as ranki_kw/ranki_jz except that matrix entries below
487 * dtol in magnitude are dropped.
488 * plain_qr: pivot_tolerance applies to cols. condition_tolerance used
489 * with a condition heuristic rather than actual condition.
490 *
491 * cond_qr and variants:
492 * Unpivoted columns are ordered by fill potential and then the first
493 * of these to meet the criterion CI*condition_tolerance <= min_CI
494 * is chosen as the next column to pivot with.
495 * Pivot_tolerance is applied to choose the pivot within the
496 * selected column.
497 *
498 * linsolqr_set_pivot/condition/drop_tolerance() will automatically call
499 * linsolqr_matrix_was_changed().
500 * </pre>
501 * @todo Separate documentation for these linsolqr functions?
502 */
503
504 /* Functions for analyzing and querying linear systems. */
505
506 extern enum factor_class linsolqr_fclass(linsolqr_system_t sys);
507 /**<
508 * Returns the most recently set factorization class of the system.
509 * The system should be previously prepped.
510 */
511
512 ASC_DLLSPEC(enum factor_method ) linsolqr_fmethod(linsolqr_system_t sys);
513 /**<
514 * Returns the most recently used factorization method of the system.
515 * The system should be previously prepped.
516 */
517
518 ASC_DLLSPEC(enum reorder_method ) linsolqr_rmethod(linsolqr_system_t sys);
519 /**<
520 * Returns the most recently set reorder method of the system.
521 * The system should be previously prepped.
522 */
523
524 extern int32 linsolqr_rank(linsolqr_system_t sys);
525 /**<
526 * Returns the rank of the system. The system must be previously
527 * factored.
528 */
529
530 extern real64 linsolqr_smallest_pivot(linsolqr_system_t sys);
531 /**<
532 * Returns the smallest pivot accepted in solving the system. The
533 * system must be previously factored. If no pivoting was performed,
534 * MAXDOUBLE is returned.
535 */
536
537 extern int linsolqr_prep(linsolqr_system_t sys,
538 enum factor_class fclass);
539 /**<
540 * This function is analogous to slv_select_solver. It
541 * takes care of allocations. The prep call should be done (once) at
542 * the beginning of any series of linear solutions being performed on
543 * on the same linsolqr system with the same factorization class.<br><br>
544 *
545 * You must prep before doing a reordering, factorization or solution
546 * as prep sets up the appropriate internal settings. You should set
547 * the matrix before you call prep.
548 * Prep (or subsequent preps) do not affect the right hand sides of
549 * the system.<br><br>
550 *
551 * If you wish to change from 1 factoring method to another and they
552 * are not part of the class of compatible methods, you should call
553 * prep again with the new class.
554 * After prep is called, reorder should be called before factorization.
555 * As most of the sparse routines depend for performance on the
556 * prior reordering.<br><br>
557 *
558 * Return 0 if ok, or 1 otherwise.
559 */
560
561 ASC_DLLSPEC(int ) linsolqr_reorder(linsolqr_system_t sys,
562 mtx_region_t *region,
563 enum reorder_method rmeth);
564 /**<
565 * The specified region of the coefficient matrix is reordered. This
566 * must be called before factoring the matrix. The specified region
567 * is assumed to contain only nonempty rows and columns and have a full
568 * diagonal.
569 * If the coefficient matrix in use is from a nonlinear system, the
570 * pattern in the coefficient matrix should be the structural one (as
571 * opposed to the numerically derived incidence which may be less.)<br><br>
572 *
573 * If you use the numerically derived incidence, you will need to reorder
574 * before every factorization. This is generally not cost effective.
575 * If region given is mtx_ENTIRE_MATRIX, a search will be done to find
576 * an appropriate bounding region in the coefficient mtx. This is
577 * not a particularly cheap search.<br><br>
578 *
579 * This function is analogous to slv_presolve. It
580 * takes care of any structural analysis necessary
581 * to the linear solution. The reorder call should be done (once) at
582 * the beginning of any series of linear solutions being performed on
583 * on structurally identical matrices.<br><br>
584 *
585 * The reordering done must be appropriate to the factorization class.
586 * You must reorder before doing a factorization or solution as reorder
587 * sets up the appropriate internal settings. Even were the internals
588 * method independent, the reordering is critical to the performance of
589 * these methods.<br><br>
590 * Return 0 if ok, 1 if not.
591 * <pre>
592 * Brief notes on the reorderings available.
593 * SPK1: The region you give becomes the region for the problem,
594 * TSPK1: but for factorization purposes rows and columns that
595 * do not intersect the main diagonal within the region
596 * are considered structurally (therefore numerically) dependent.
597 * Natural: Blesses the system and does nothing.
598 * Again, the rows/cols not in the diagonal are dependent.
599 * </pre>
600 */
601
602 ASC_DLLSPEC(int ) linsolqr_factor(linsolqr_system_t sys,
603 enum factor_method fmethod);
604 /**<
605 * Decompose the reordered region of a copy of the coefficient matrix
606 * into upper and lower triangular factors (if necessary) which can be
607 * inverted easily when applied to any rhs. Matrix must be factored in
608 * order to perform any of the operations below. The numerical rank and
609 * the smallest pivot encountered during pivoting are computed in the
610 * process. Factorization method used is that given if it is compatible
611 * with the class set when the prep was done, otherwise the call fails.<br><br>
612 *
613 * If you are handed a linsolqr system and want to refactor it using the
614 * usual method, but don't know what that method is, call like:
615 * status = linsolqr_factor(sys,linsolqr_fmethod(sys));<br><br>
616 *
617 * Return 0 if ok, 1 if not.
618 */
619
620 extern int linsolqr_get_pivot_sets(linsolqr_system_t sys,
621 unsigned *org_rowpivots,
622 unsigned *org_colpivots);
623 /**<
624 * Returns the set of original row numbers / original column numbers which
625 * have been pivoted. org_rowpivots and org_colpivots are assumed to be
626 * sets created by (or at least for) the set module with sufficient size
627 * before calling this function. They must also be previously NULLed.
628 * The system must be previously factored.
629 * The sets input should be the result of set_create(neqn),set_create(nvar).
630 * There is no association of rows with columns here.<br><br>
631 *
632 * @return Status is 0 if not factored, 1 if factored. If 0, sets will not be
633 * changed.
634 * This bizarre piece of functionality should be done away with as soon
635 * as the equivalents below have been implemented.
636 */
637
638 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_unpivoted_rows(linsolqr_system_t sys);
639 /**< See discussion under linsolqr_unpivoted_cols(). */
640 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_unpivoted_cols(linsolqr_system_t sys);
641 /**<
642 * Returns the set of original row numbers / original column numbers which
643 * have NOT been pivoted and the rejected pivots in an mtx_sparse_t.
644 * Return is NULL if sys not factored or if no unpivoted rows/cols exist.
645 * E.g. singrows->idata[i] are the original rows that were not pivoted,
646 * singrows->data[i] is the pivot that was rejected,
647 * for i = 0 to singrows->len-1.
648 * If len is 0, the data and idata pointers may be NULL.
649 *
650 * The CALLER is responsible for deallocating the mtx_sparse_t returned;
651 * linsolqr wants nothing further to do with it.
652 * @bug Only deals with ranki based square systems at the moment.
653 * Then again, that's all we have at the moment (10/95).
654 * Returns NULL from non-ranki systems.
655 * @todo Separate documentation for these linsolqr functions?
656 */
657
658 extern mtx_sparse_t *linsolqr_pivoted_rows(linsolqr_system_t sys);
659 /**< See discussion under linsolqr_pivoted_cols(). */
660 extern mtx_sparse_t *linsolqr_pivoted_cols(linsolqr_system_t sys);
661 /**<
662 * Returns the set of original row numbers / original column numbers which
663 * have been pivoted and the pivots in an mtx_sparse_t.
664 * Return is NULL if sys not factored or if no pivoted rows/cols exist.
665 * E.g. pivrows->idata[i] are the original rows that were pivoted,
666 * pivrows->data[i] is the pivot,
667 * for i = 0 to pivrows->len-1.
668 * If len is 0, the data and idata pointers may be NULL.
669 *
670 * The CALLER is responsible for deallocating the mtx_sparse_t returned;
671 * linsolqr wants nothing further to do with it.
672 * @bug Only deals with ranki based square systems at the moment.
673 * Then again, that's all we have at the moment (10/95).
674 * Returns NULL from non-ranki systems.
675 * @todo Separate documentation for these linsolqr functions?
676 */
677
678 extern int32 linsolqr_org_row_to_org_col(linsolqr_system_t sys,
679 int32 org_row);
680 /**< See discussion under linsolqr_org_col_to_org_row(). */
681 extern int32 linsolqr_org_col_to_org_row(linsolqr_system_t sys,
682 int32 org_col);
683 /**<
684 * Pivoted original columns and pivoted original rows can be associated
685 * with one another via the pivot sequence. These functions returned the
686 * org_col/org_row associated with the given org_row/org_col. If the given
687 * org_row/org_col is not pivoted, a meaningless value is returned. The
688 * system must be previously factored. If not factored, these functions
689 * will return a value, but linsolqr may reorder making the value wrong.
690 * @todo Separate documentation for these linsolqr functions?
691 */
692
693 ASC_DLLSPEC(void) linsolqr_calc_row_dependencies(linsolqr_system_t sys);
694 /**< See discussion under linsolqr_calc_col_dependencies(). */
695
696 ASC_DLLSPEC(void) linsolqr_calc_col_dependencies(linsolqr_system_t sys);
697 /**<
698 * Given a factored system for which dependencies are not yet
699 * calculated, calculates row/column dependencies. This must be
700 * called before either linsolqr_org_row/col_dependency
701 * or linsolqr_row/col_dependence_coefs can be called.
702 * All rows/columns in the region specified to reorder
703 * and not part of the final factorization have their dependencies
704 * calculated.
705 *
706 * The calculation method is fairly standard.
707 * We will give the version for LU column dependency. Transpose it
708 * for row dependency. Similar things can be done for QR.
709 * Given a matrix region A, factor it and arrive at
710 * A11 | A12 where A11 = L U and columns of A12 are dependent,
711 * --------- that is A12 = A11 . Y. (The row A2 need not exist,
712 * A21 | eps but if it does, A22 must be small or we could have
713 * factored further.) Solve for Y. The Yi are the coefficients of the
714 * linear combination of columns in A11 which sum to A12.
715 * And, note that since the columns of A12 were treated during
716 * factoring as if they were ultimately going to be pivoted in,
717 * we only need to substitute on the other triangle factor, half the
718 * work of a regular solve.
719 * @todo Separate documentation for these linsolqr functions?
720 */
721
722 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_row_dependence_coefs(
723 linsolqr_system_t sys, int32 orgrow);
724 /**< See discussion under linsolqr_col_dependence_coefs(). */
725
726 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_col_dependence_coefs(
727 linsolqr_system_t sys, int32 orgcol
728 );
729 /**<
730 * Given an org row/col and a factored system, returns a mtx_sparse_t
731 * containing the org row/col indices and linear combination coefficients
732 * contributing to the given dependent row/col. If the orgrow/orgcol
733 * given is not dependent or dependencies have not been calculated,
734 * return is NULL.
735 * E.g. rowcoefs->idata[i] is the org row index of a contributing row,
736 * rowcoefs->data[i] is the dependency coefficient,
737 * for i = 0 to rowcoefs->len-1.
738 * Numeric dependency calculation is a numeric process with lots of room
739 * for interpretation of the results. Not everything that claims to
740 * contribute to a singularity really does so. We leave this interpre-
741 * tation to the the caller.
742 *
743 * The CALLER is responsible for deallocating the mtx_sparse_t returned;
744 * linsol wants nothing further to do with it.
745 *
746 * @todo Separate documentation for these linsolqr functions?
747 */
748
749 extern real64 linsolqr_org_row_dependency(linsolqr_system_t sys,
750 int32 dep, int32 ind);
751 /**< See discussion under linsolqr_org_col_dependency(). */
752 extern real64 linsolqr_org_col_dependency(linsolqr_system_t sys,
753 int32 dep, int32 ind);
754 /**<
755 * Any original row / column of the coefficient matrix which when submitted
756 * to the linear solver is not pivoted, is called dependent and can be
757 * written as a linear combination of the independent (pivoted) original
758 * rows / columns. These functions return the previously computed
759 * coefficients of the linear combination. The system must be previously
760 * factored and the independent row / column must be a member of the
761 * set of row / column pivots obtained by linsolqr_get_pivot_sets.
762 * This is a slow and clunky way to retrieve dependency info.
763 * This ought to be done away with when the above function is done.
764 *
765 * @todo Separate documentation for these linsolqr functions?
766 */
767
768 ASC_DLLSPEC(int ) linsolqr_solve(linsolqr_system_t sys, real64 *rhs);
769 /**<
770 * Solves the system of linear equations (if necessary) utilizing the
771 * specified rhs along with the previously factored matrix. The rhs
772 * is automatically checked if the matrix factors need to be transposed
773 * or not (see linsolqr_add_rhs.)
774 * Solution method will be appropriate to the factorization method used
775 * in linsolqr_factor.
776 * @return 0 if ok, 1 if not.
777 */
778
779 extern real64 linsolqr_var_value(linsolqr_system_t sys,
780 real64 *rhs, int32 var);
781 /**<
782 * Returns the value of the variable in the solution vector associated
783 * with the given rhs and either the matrix or its transpose. The rhs
784 * must be solved for first. If rhs specifies transpose, then var is
785 * expected to be an original row number, otherwise it should be an
786 * original column number.
787 * If sys, rhs, and var are not proper, the value returned is 0.0
788 * and a warning is issued to stderr.
789 */
790
791 ASC_DLLSPEC(boolean ) linsolqr_copy_solution(linsolqr_system_t sys,
792 real64 *rhs, real64 *vector);
793 /**<
794 * Once a sys has been factored and rhs solved, this
795 * fills in a copy of the solution vector associated with rhs. Caller
796 * must provide vector and vector must be of length at least as long
797 * as the order of the matrix that was solved. The vector entries
798 * will be in org_col order if the rhs is normal or in org_row order
799 * if the rhs is a transpose.
800 *
801 * @return TRUE if something is amiss, FALSE otherwise.
802 *
803 */
804
805 extern real64 linsolqr_eqn_residual(linsolqr_system_t sys,
806 real64 *rhs, int32 eqn);
807 /**<
808 * Returns the equation residual using the solution vector associated
809 * with the given rhs and either the matrix or its transpose.
810 * <pre>
811 * T
812 * residual = A x - b or residual = A x - b
813 * </pre>
814 * The rhs must be solved for first. If rhs specifies transpose, then
815 * eqn is expected to be an original column number, otherwise it should
816 * be an original row number.
817 * If the system and rhs and eqn are not properly solved, the return
818 * value is MAXDOUBLE.
819 */
820
821 extern boolean linsolqr_calc_residual(linsolqr_system_t sys,
822 real64 *rhs, real64 *vector);
823 /**<
824 * Returns the residuals using the solution associated
825 * with the given rhs and either the matrix or its transpose.
826 * <pre>
827 * T
828 * residual = A x - b or residual = A x - b
829 * </pre>
830 * The rhs must be solved for first. Caller
831 * must provide vector and vector must be of length at least as long
832 * as the order of the matrix that was solved. The vector entries
833 * will be in org_row order if the rhs is normal or in org_col order
834 * if the rhs is a transpose. Entries of the vector which do not
835 * correspond to rows/cols of factored system solved will not be modified.<br><br>
836 *
837 * @return If the system and rhs are not properly solved, or other is amiss
838 * return value is TRUE, else FALSE.
839 */
840
841 /* miscellaneous functions for C programmers wanting to know things. */
842
843 extern size_t linsolqr_size(linsolqr_system_t sys);
844 /**<
845 * Returns the amount of memory in use by a system and all its
846 * bits and pieces. User supplied RHS vectors and coefficient
847 * matrix are NOT included in the size calculation. The user
848 * must do accounting for those.
849 */
850
851 extern void linsolqr_free_reused_mem(void);
852 /**<
853 * Deallocates any memory that linsolqr may be squirrelling away for
854 * internal reuse. Calling this while any slv_system_t using linsolqr exists
855 * is likely to be fatal: handle with care.
856 * There isn't a way to query how many bytes this is.
857 */
858
859 /*-----------------------------------------------------------------------------
860 * The following calls exist to facilitate debugging of the linear
861 * solver when it is being tested on large systems. Do not use them
862 * in routine coding. If you need access to the factor/inverse matrices
863 * for computational purpose, you should probably consider adding that
864 * functionality to linsol.
865 */
866
867 ASC_DLLSPEC(mtx_matrix_t ) linsolqr_get_factors(linsolqr_system_t sys);
868 /**< See discussion under linsolqr_get_inverse(). */
869 extern mtx_matrix_t linsolqr_get_inverse(linsolqr_system_t sys);
870 /**<
871 * Returns the handle of the factor (L\U, Q\R) or inverse matrix.
872 * The handle may be NULL, and should be checked before use.
873 * The matrix should not be tampered (other than to look at it)
874 * with if any other mathematical operations will take place with
875 * sys. Linsol expects to deallocate both factors and inverse; do
876 * not do so yourself.
877 *
878 * @NOTE All the factorization methods use some sort of dense vectors
879 * for storing pivots and whatnot. As with a FORTRAN factorization,
880 * there's not much you can do with a factorization without
881 * also understanding in detail the factorization routine and getting
882 * your hands on the dense vectors.
883 *
884 * @todo Separate documentation of linsolqr_get_factors()
885 * and linsolqr_get_inverse()?
886 */
887
888 extern mtx_region_t *linsolqr_get_region(linsolqr_system_t sys);
889 /**<
890 * Returns a pointer to the current linsolqr region.
891 * This is being created for use in the check numeric dependency
892 * routine and may be removed once the new "problem manager" window
893 * is created to take over this functionality (and others).
894 */
895
896 extern int linsolqr_setup_ngslv(linsolqr_system_t sys,
897 real64 *rhs,
898 mtx_range_t *un_p_rng,
899 real64 *tmpvec);
900 /**< Sets up the NGSlv solver. */
901 extern real64 *linsolqr_get_varvalue(linsolqr_system_t sys, int n);
902 /**< Returns the value of the nth variable in sys. */
903
904 /** @} */
905
906 #endif /* ASC_LINSOLQR_H */

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22