/[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 919 - (show annotations) (download) (as text)
Mon Nov 6 04:48:59 2006 UTC (16 years, 1 month ago) by johnpye
File MIME type: text/x-chdr
File size: 39557 byte(s)
Fixing bug #305 (CONOPT not working with testconopt.a4c).
Some effort to rearrange external 'solve' scripts, ongoing.
Note, relman_diff2 returns 0 on success, but relman_eval returns 1 on success!
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 #define LINSOLMTX_DEBUG FALSE
216 /**< Debug mode. */
217 #define LINQR_DROP_TOLERANCE 1.0e-16
218 /**< This is the default for drop tolerances in methods which use a drop tol */
219
220 typedef struct linsolqr_header *linsolqr_system_t;
221 /**< linsolqr_system_t is the linear system handle. */
222
223 enum factor_class {
224 unknown_c, /**< error handling class */
225 ranki = 100, /**< all ranki (and gauss until broken out) methods */
226 s_qr = 200 /**< all sparse qr methods */
227 };
228
229 enum reorder_method {
230 unknown_r, /**< error handling method */
231 natural = 1000, /**< do nothing reorder */
232 spk1 = 2000, /**< Stadtherr's SPK1 reordering */
233 tspk1 = 3000 /**< transpose of Stadtherr's SPK1 reordering good for gauss */
234 /* future work:
235 invspk1, spk1 then diagonally inverted
236 invtspk1, tspk1 then diagonally inverted
237 widespk1, spk1 of an MxN region, N > M
238 */
239 };
240
241 enum factor_method {
242 unknown_f = 0, /**< error handling method */
243 ranki_kw = 1, /**< original linsol method */
244 ranki_jz = 2, /**< original linsol method with pseudo-complete pivoting */
245 ranki_kw2 = 3, /**< better data structure version of ranki_kw, w/drop tol */
246 ranki_jz2 = 4, /**< better data structure version of ranki_jz, w/drop tol */
247 ranki_ka = 12, /**< kirks hacked verion of the basic method. */
248 plain_qr = 5, /**< rectangular col pivoted qr variants */
249 cond_qr = 6, /**< stewart-based sparse QR method new Coke */
250 ranki_ba2 = 7, /**< proper linked list implementation of ranki (dragfree) */
251 opt_qr = 8, /**< coming soon */
252 ls_qr = 9, /**< anticipated */
253 gauss_ba2 = 10, /**< anticipated */
254 symmetric_lu = 11 /**< anticipated */
255 };
256
257 ASC_DLLSPEC(int ) g_linsolqr_timing;
258 /**<
259 * If nonzero and certain internal defines are set, factorization
260 * generates a fill and timing message.
261 */
262
263 /* KAA_DEBUG */
264 /* unimplemented function
265 extern boolean linsolqr_col_is_a_spike (mtx_matrix_t mtx, int32 col);
266 */
267 /* Returns true if the column in question is a spike. */
268
269
270 /* Functions for managing interfaces */
271
272 extern char *linsolqr_rmethods(void);
273 /**<
274 * Returns a comma-separated list of the names of reordering methods
275 * implemented. If you implement a new method, update this
276 * function. Do not free the pointer returned.<br><br>
277 *
278 * Not all reorderings are appropriate to all factorizations.
279 */
280
281 ASC_DLLSPEC(char *) linsolqr_fmethods(void);
282 /**<
283 * Returns a comma-separated list of the names of factorization methods
284 * implemented. If you implement a new method, update this
285 * function. Do not free the pointer returned. The string returned
286 * will contain no whitespace of any sort, tabs, blanks, or \n.
287 */
288
289 extern enum reorder_method linsolqr_rmethod_to_enum(char *s);
290 /**<
291 * Returns the enum of a reorder method with the name s.
292 * If you implement a new method, update this function.
293 */
294
295 extern enum factor_method linsolqr_fmethod_to_enum(char *s);
296 /**<
297 * Returns the enum of a factor method with the name s.
298 * If you implement a new method, update this function.
299 */
300
301 extern enum factor_class linsolqr_fmethod_to_fclass(enum factor_method fm);
302 /**<
303 * Returns the enum of the factor class containing the method given.
304 * If you implement a new method or class, update this function.
305 */
306
307 ASC_DLLSPEC(char *) linsolqr_enum_to_rmethod(enum reorder_method m);
308 /**<
309 * <!-- s=linsolqr_enum_to_rmethod(m); -->
310 *
311 * Returns the name of a reorder method with the enum m.
312 * If you implement a new method, update this function.
313 * Do not free the name.
314 */
315
316 extern char *linsolqr_enum_to_fmethod(enum factor_method m);
317 /**<
318 * Returns the name of a factor method with the enum m.
319 * If you implement a new method, update this function.
320 * Do not free the name.
321 */
322
323 ASC_DLLSPEC(char *) linsolqr_rmethod_description(enum reorder_method meth);
324 /**<
325 * Returns a string describing the method inquired on. Do not mess
326 * with the string: linsolqr owns it.
327 * If you implement a new method, update this function.
328 */
329
330 ASC_DLLSPEC(char *) linsolqr_fmethod_description(enum factor_method meth);
331 /**<
332 * Returns a string describing the method inquired on. Do not mess
333 * with the string: linsolqr owns it.
334 * If you implement a new method, update this function.
335 */
336
337 /* Functions for specifying problems and controlling them */
338
339 extern linsolqr_system_t linsolqr_create(void);
340 /**<
341 * Creates a linear system and returns a pointer to it. Initially the
342 * system has no coefficient matrix and no rhs.
343 */
344
345 extern void linsolqr_destroy(linsolqr_system_t sys);
346 /**<
347 * Destroys the linear system. The coefficient matrix and each rhs are
348 * not destroyed by this call.
349 */
350
351 extern void linsolqr_set_matrix(linsolqr_system_t sys, mtx_matrix_t mtx);
352 /**<
353 * Sets the coefficient matrix to mtx.
354 */
355
356 ASC_DLLSPEC(void ) linsolqr_set_region(linsolqr_system_t sys, mtx_region_t region);
357 /**<
358 * Sets the reg to region.
359 */
360
361 ASC_DLLSPEC(mtx_matrix_t ) linsolqr_get_matrix(linsolqr_system_t sys);
362 /**<
363 * Returns the coefficient matrix.
364 */
365
366 ASC_DLLSPEC(void ) linsolqr_add_rhs(linsolqr_system_t sys,
367 real64 *rhs,
368 boolean transpose);
369 /**<
370 * Adds the given rhs to the collection of rhs's already part of the
371 * system.
372 *
373 * You continue to be responsible for deallocating rhs. We do not take
374 * over management of that memory. Do not free the rhs you have given
375 * us without calling linsolqr_remove_rhs first.<br><br>
376 *
377 * Rhs should point to an array of reals indexed by original
378 * column number if the linear system is to be solved using the transpose
379 * of the matrix or by original row number if the matrix is not to be
380 * transposed. This is determined using the boolean transpose. The
381 * rhs should be refered to in the future by its pointer.
382 * <pre>
383 * For the mathematically impaired:
384 * M' denotes Transpose(M).
385 *
386 * transpose==FALSE --> rhs will be solved for x in A x = b.
387 * --> rhs b is an org row indexed column vector.
388 * --> x is an org col indexed column vector.
389 * --> yields dx = Newton direction in J.dx = -f
390 * if the b given is -f.
391 *
392 * transpose==TRUE --> rhs will be solved for y in A' y = d.
393 * --> rhs d is an org column indexed column vector.
394 * --> y is an org row indexed column vector.
395 * --> yields dx = Newton direction in J'.dx = -f.
396 * if the d given is -f and f,dx are properly indexed.
397 * This may be useful if A was created using
398 * mtx_transpose in order to improve factorization.
399 *
400 * Useful matrix identity: (M')^-1 == (M^-1)' for invertible M.
401 * </pre>
402 */
403
404 ASC_DLLSPEC(void ) linsolqr_remove_rhs(linsolqr_system_t sys, real64 *rhs);
405 /**<
406 * Removes the given rhs from the system. The rhs is not destroyed, just
407 * removed from the system.
408 */
409
410 extern int32 linsolqr_number_of_rhs(linsolqr_system_t sys);
411 /**<
412 * Returns the number of rhs's currently part of the system.
413 */
414
415 ASC_DLLSPEC(real64 *) linsolqr_get_rhs(linsolqr_system_t sys, int n);
416 /**<
417 * Returns the n-th rhs, where rhs's are indexed in the order they were
418 * added using linsolqr_add_rhs() from 0 to (# rhs's)-1. NULL is returned
419 * if the index is out of range.
420 */
421
422 ASC_DLLSPEC(void ) linsolqr_matrix_was_changed(linsolqr_system_t sys);
423 /**<
424 * Informs the solver that a numerical value of a non-zero was changed.
425 * This must be called whenever any numerical changes to the matrix are
426 * made.
427 */
428
429 ASC_DLLSPEC(void ) linsolqr_rhs_was_changed(linsolqr_system_t sys,
430 real64 *rhs);
431 /**<
432 * Informs the solver that the given rhs has been modified. This must be
433 * called whenever the rhs is modified.
434 */
435
436 extern void linsolqr_set_pivot_zero(linsolqr_system_t sys,
437 real64 pivot_zero);
438 /**<
439 * Sets the pivot zero for the system. Pivots less than or equal to
440 * this value are regarded as zero. linsolqr_set_pivot_zero() will
441 * automatically call linsolqr_matrix_was_changed().
442 */
443 extern real64 linsolqr_pivot_zero(linsolqr_system_t sys);
444 /**<
445 * Gets the pivot zero for the system. Pivots less than or equal to
446 * this value are regarded as zero.
447 */
448
449 extern void linsolqr_set_pivot_tolerance(linsolqr_system_t sys, real64 ptol);
450 /**< See discussion under linsolqr_drop_tolerance(). */
451 extern real64 linsolqr_pivot_tolerance(linsolqr_system_t sys);
452 /**< See discussion under linsolqr_drop_tolerance(). */
453 extern void linsolqr_set_condition_tolerance(linsolqr_system_t sys, real64 ctol);
454 /**< See discussion under linsolqr_drop_tolerance(). */
455 extern real64 linsolqr_condition_tolerance(linsolqr_system_t sys);
456 /**< See discussion under linsolqr_drop_tolerance(). */
457 extern void linsolqr_set_drop_tolerance(linsolqr_system_t sys, real64 dtol);
458 /**< See discussion under linsolqr_drop_tolerance(). */
459 extern real64 linsolqr_drop_tolerance(linsolqr_system_t sys);
460 /**<
461 * <pre>
462 * linsolqr_set_pivot_tolerance(sys,ptol)
463 * ptol = linsolqr_pivot_tolerance(sys)
464 *
465 * linsolqr_set_condition_tolerance(sys,ctol)
466 * ctol = linsolqr_condition_tolerance(sys)
467 *
468 * linsolqr_set_drop_tolerance(sys,dtol)
469 * dtol = linsolqr_drop_tolerance(sys)
470 *
471 * linsolqr_system_t sys;
472 * real64 ptol, ctol,dtol;
473 *
474 * Sets/gets the pivot/condition/drop tolerance for the system. Semantics of
475 * tolerances vary with method. Not to be confused with pivot zero, epsilon.
476 *
477 * pivot_tolerance: Pivots less than this fraction of the maximum pivot
478 * value in the same row or column (depending on method) are disregarded.
479 *
480 * ranki_kw: pivot_tolerance applies to row. condition_tolerance ignored.
481 * ranki_jz: pivot_tolerance applies to row and col. condition ignored.
482 * ranki_ba2:
483 * ranki_kw2:
484 * ranki_jz2: as ranki_kw/ranki_jz except that matrix entries below
485 * dtol in magnitude are dropped.
486 * plain_qr: pivot_tolerance applies to cols. condition_tolerance used
487 * with a condition heuristic rather than actual condition.
488 *
489 * cond_qr and variants:
490 * Unpivoted columns are ordered by fill potential and then the first
491 * of these to meet the criterion CI*condition_tolerance <= min_CI
492 * is chosen as the next column to pivot with.
493 * Pivot_tolerance is applied to choose the pivot within the
494 * selected column.
495 *
496 * linsolqr_set_pivot/condition/drop_tolerance() will automatically call
497 * linsolqr_matrix_was_changed().
498 * </pre>
499 * @todo Separate documentation for these linsolqr functions?
500 */
501
502 /* Functions for analyzing and querying linear systems. */
503
504 extern enum factor_class linsolqr_fclass(linsolqr_system_t sys);
505 /**<
506 * Returns the most recently set factorization class of the system.
507 * The system should be previously prepped.
508 */
509
510 ASC_DLLSPEC(enum factor_method ) linsolqr_fmethod(linsolqr_system_t sys);
511 /**<
512 * Returns the most recently used factorization method of the system.
513 * The system should be previously prepped.
514 */
515
516 ASC_DLLSPEC(enum reorder_method ) linsolqr_rmethod(linsolqr_system_t sys);
517 /**<
518 * Returns the most recently set reorder method of the system.
519 * The system should be previously prepped.
520 */
521
522 extern int32 linsolqr_rank(linsolqr_system_t sys);
523 /**<
524 * Returns the rank of the system. The system must be previously
525 * factored.
526 */
527
528 extern real64 linsolqr_smallest_pivot(linsolqr_system_t sys);
529 /**<
530 * Returns the smallest pivot accepted in solving the system. The
531 * system must be previously factored. If no pivoting was performed,
532 * MAXDOUBLE is returned.
533 */
534
535 extern int linsolqr_prep(linsolqr_system_t sys,
536 enum factor_class fclass);
537 /**<
538 * This function is analogous to slv_select_solver. It
539 * takes care of allocations. The prep call should be done (once) at
540 * the beginning of any series of linear solutions being performed on
541 * on the same linsolqr system with the same factorization class.<br><br>
542 *
543 * You must prep before doing a reordering, factorization or solution
544 * as prep sets up the appropriate internal settings. You should set
545 * the matrix before you call prep.
546 * Prep (or subsequent preps) do not affect the right hand sides of
547 * the system.<br><br>
548 *
549 * If you wish to change from 1 factoring method to another and they
550 * are not part of the class of compatible methods, you should call
551 * prep again with the new class.
552 * After prep is called, reorder should be called before factorization.
553 * As most of the sparse routines depend for performance on the
554 * prior reordering.<br><br>
555 *
556 * Return 0 if ok, or 1 otherwise.
557 */
558
559 ASC_DLLSPEC(int ) linsolqr_reorder(linsolqr_system_t sys,
560 mtx_region_t *region,
561 enum reorder_method rmeth);
562 /**<
563 * The specified region of the coefficient matrix is reordered. This
564 * must be called before factoring the matrix. The specified region
565 * is assumed to contain only nonempty rows and columns and have a full
566 * diagonal.
567 * If the coefficient matrix in use is from a nonlinear system, the
568 * pattern in the coefficient matrix should be the structural one (as
569 * opposed to the numerically derived incidence which may be less.)<br><br>
570 *
571 * If you use the numerically derived incidence, you will need to reorder
572 * before every factorization. This is generally not cost effective.
573 * If region given is mtx_ENTIRE_MATRIX, a search will be done to find
574 * an appropriate bounding region in the coefficient mtx. This is
575 * not a particularly cheap search.<br><br>
576 *
577 * This function is analogous to slv_presolve. It
578 * takes care of any structural analysis necessary
579 * to the linear solution. The reorder call should be done (once) at
580 * the beginning of any series of linear solutions being performed on
581 * on structurally identical matrices.<br><br>
582 *
583 * The reordering done must be appropriate to the factorization class.
584 * You must reorder before doing a factorization or solution as reorder
585 * sets up the appropriate internal settings. Even were the internals
586 * method independent, the reordering is critical to the performance of
587 * these methods.<br><br>
588 * Return 0 if ok, 1 if not.
589 * <pre>
590 * Brief notes on the reorderings available.
591 * SPK1: The region you give becomes the region for the problem,
592 * TSPK1: but for factorization purposes rows and columns that
593 * do not intersect the main diagonal within the region
594 * are considered structurally (therefore numerically) dependent.
595 * Natural: Blesses the system and does nothing.
596 * Again, the rows/cols not in the diagonal are dependent.
597 * </pre>
598 */
599
600 ASC_DLLSPEC(int ) linsolqr_factor(linsolqr_system_t sys,
601 enum factor_method fmethod);
602 /**<
603 * Decompose the reordered region of a copy of the coefficient matrix
604 * into upper and lower triangular factors (if necessary) which can be
605 * inverted easily when applied to any rhs. Matrix must be factored in
606 * order to perform any of the operations below. The numerical rank and
607 * the smallest pivot encountered during pivoting are computed in the
608 * process. Factorization method used is that given if it is compatible
609 * with the class set when the prep was done, otherwise the call fails.<br><br>
610 *
611 * If you are handed a linsolqr system and want to refactor it using the
612 * usual method, but don't know what that method is, call like:
613 * status = linsolqr_factor(sys,linsolqr_fmethod(sys));<br><br>
614 *
615 * Return 0 if ok, 1 if not.
616 */
617
618 extern int linsolqr_get_pivot_sets(linsolqr_system_t sys,
619 unsigned *org_rowpivots,
620 unsigned *org_colpivots);
621 /**<
622 * Returns the set of original row numbers / original column numbers which
623 * have been pivoted. org_rowpivots and org_colpivots are assumed to be
624 * sets created by (or at least for) the set module with sufficient size
625 * before calling this function. They must also be previously NULLed.
626 * The system must be previously factored.
627 * The sets input should be the result of set_create(neqn),set_create(nvar).
628 * There is no association of rows with columns here.<br><br>
629 *
630 * @return Status is 0 if not factored, 1 if factored. If 0, sets will not be
631 * changed.
632 * This bizarre piece of functionality should be done away with as soon
633 * as the equivalents below have been implemented.
634 */
635
636 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_unpivoted_rows(linsolqr_system_t sys);
637 /**< See discussion under linsolqr_unpivoted_cols(). */
638 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_unpivoted_cols(linsolqr_system_t sys);
639 /**<
640 * Returns the set of original row numbers / original column numbers which
641 * have NOT been pivoted and the rejected pivots in an mtx_sparse_t.
642 * Return is NULL if sys not factored or if no unpivoted rows/cols exist.
643 * E.g. singrows->idata[i] are the original rows that were not pivoted,
644 * singrows->data[i] is the pivot that was rejected,
645 * for i = 0 to singrows->len-1.
646 * If len is 0, the data and idata pointers may be NULL.
647 *
648 * The CALLER is responsible for deallocating the mtx_sparse_t returned;
649 * linsolqr wants nothing further to do with it.
650 * @bug Only deals with ranki based square systems at the moment.
651 * Then again, that's all we have at the moment (10/95).
652 * Returns NULL from non-ranki systems.
653 * @todo Separate documentation for these linsolqr functions?
654 */
655
656 extern mtx_sparse_t *linsolqr_pivoted_rows(linsolqr_system_t sys);
657 /**< See discussion under linsolqr_pivoted_cols(). */
658 extern mtx_sparse_t *linsolqr_pivoted_cols(linsolqr_system_t sys);
659 /**<
660 * Returns the set of original row numbers / original column numbers which
661 * have been pivoted and the pivots in an mtx_sparse_t.
662 * Return is NULL if sys not factored or if no pivoted rows/cols exist.
663 * E.g. pivrows->idata[i] are the original rows that were pivoted,
664 * pivrows->data[i] is the pivot,
665 * for i = 0 to pivrows->len-1.
666 * If len is 0, the data and idata pointers may be NULL.
667 *
668 * The CALLER is responsible for deallocating the mtx_sparse_t returned;
669 * linsolqr wants nothing further to do with it.
670 * @bug Only deals with ranki based square systems at the moment.
671 * Then again, that's all we have at the moment (10/95).
672 * Returns NULL from non-ranki systems.
673 * @todo Separate documentation for these linsolqr functions?
674 */
675
676 extern int32 linsolqr_org_row_to_org_col(linsolqr_system_t sys,
677 int32 org_row);
678 /**< See discussion under linsolqr_org_col_to_org_row(). */
679 extern int32 linsolqr_org_col_to_org_row(linsolqr_system_t sys,
680 int32 org_col);
681 /**<
682 * Pivoted original columns and pivoted original rows can be associated
683 * with one another via the pivot sequence. These functions returned the
684 * org_col/org_row associated with the given org_row/org_col. If the given
685 * org_row/org_col is not pivoted, a meaningless value is returned. The
686 * system must be previously factored. If not factored, these functions
687 * will return a value, but linsolqr may reorder making the value wrong.
688 * @todo Separate documentation for these linsolqr functions?
689 */
690
691 ASC_DLLSPEC(void) linsolqr_calc_row_dependencies(linsolqr_system_t sys);
692 /**< See discussion under linsolqr_calc_col_dependencies(). */
693
694 ASC_DLLSPEC(void) linsolqr_calc_col_dependencies(linsolqr_system_t sys);
695 /**<
696 * Given a factored system for which dependencies are not yet
697 * calculated, calculates row/column dependencies. This must be
698 * called before either linsolqr_org_row/col_dependency
699 * or linsolqr_row/col_dependence_coefs can be called.
700 * All rows/columns in the region specified to reorder
701 * and not part of the final factorization have their dependencies
702 * calculated.
703 *
704 * The calculation method is fairly standard.
705 * We will give the version for LU column dependency. Transpose it
706 * for row dependency. Similar things can be done for QR.
707 * Given a matrix region A, factor it and arrive at
708 * A11 | A12 where A11 = L U and columns of A12 are dependent,
709 * --------- that is A12 = A11 . Y. (The row A2 need not exist,
710 * A21 | eps but if it does, A22 must be small or we could have
711 * factored further.) Solve for Y. The Yi are the coefficients of the
712 * linear combination of columns in A11 which sum to A12.
713 * And, note that since the columns of A12 were treated during
714 * factoring as if they were ultimately going to be pivoted in,
715 * we only need to substitute on the other triangle factor, half the
716 * work of a regular solve.
717 * @todo Separate documentation for these linsolqr functions?
718 */
719
720 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_row_dependence_coefs(
721 linsolqr_system_t sys, int32 orgrow);
722 /**< See discussion under linsolqr_col_dependence_coefs(). */
723
724 ASC_DLLSPEC(mtx_sparse_t *) linsolqr_col_dependence_coefs(
725 linsolqr_system_t sys, int32 orgcol
726 );
727 /**<
728 * Given an org row/col and a factored system, returns a mtx_sparse_t
729 * containing the org row/col indices and linear combination coefficients
730 * contributing to the given dependent row/col. If the orgrow/orgcol
731 * given is not dependent or dependencies have not been calculated,
732 * return is NULL.
733 * E.g. rowcoefs->idata[i] is the org row index of a contributing row,
734 * rowcoefs->data[i] is the dependency coefficient,
735 * for i = 0 to rowcoefs->len-1.
736 * Numeric dependency calculation is a numeric process with lots of room
737 * for interpretation of the results. Not everything that claims to
738 * contribute to a singularity really does so. We leave this interpre-
739 * tation to the the caller.
740 *
741 * The CALLER is responsible for deallocating the mtx_sparse_t returned;
742 * linsol wants nothing further to do with it.
743 *
744 * @todo Separate documentation for these linsolqr functions?
745 */
746
747 extern real64 linsolqr_org_row_dependency(linsolqr_system_t sys,
748 int32 dep, int32 ind);
749 /**< See discussion under linsolqr_org_col_dependency(). */
750 extern real64 linsolqr_org_col_dependency(linsolqr_system_t sys,
751 int32 dep, int32 ind);
752 /**<
753 * Any original row / column of the coefficient matrix which when submitted
754 * to the linear solver is not pivoted, is called dependent and can be
755 * written as a linear combination of the independent (pivoted) original
756 * rows / columns. These functions return the previously computed
757 * coefficients of the linear combination. The system must be previously
758 * factored and the independent row / column must be a member of the
759 * set of row / column pivots obtained by linsolqr_get_pivot_sets.
760 * This is a slow and clunky way to retrieve dependency info.
761 * This ought to be done away with when the above function is done.
762 *
763 * @todo Separate documentation for these linsolqr functions?
764 */
765
766 ASC_DLLSPEC(int ) linsolqr_solve(linsolqr_system_t sys, real64 *rhs);
767 /**<
768 * Solves the system of linear equations (if necessary) utilizing the
769 * specified rhs along with the previously factored matrix. The rhs
770 * is automatically checked if the matrix factors need to be transposed
771 * or not (see linsolqr_add_rhs.)
772 * Solution method will be appropriate to the factorization method used
773 * in linsolqr_factor.
774 * @return 0 if ok, 1 if not.
775 */
776
777 extern real64 linsolqr_var_value(linsolqr_system_t sys,
778 real64 *rhs, int32 var);
779 /**<
780 * Returns the value of the variable in the solution vector associated
781 * with the given rhs and either the matrix or its transpose. The rhs
782 * must be solved for first. If rhs specifies transpose, then var is
783 * expected to be an original row number, otherwise it should be an
784 * original column number.
785 * If sys, rhs, and var are not proper, the value returned is 0.0
786 * and a warning is issued to stderr.
787 */
788
789 ASC_DLLSPEC(boolean ) linsolqr_copy_solution(linsolqr_system_t sys,
790 real64 *rhs, real64 *vector);
791 /**<
792 * Once a sys has been factored and rhs solved, this
793 * fills in a copy of the solution vector associated with rhs. Caller
794 * must provide vector and vector must be of length at least as long
795 * as the order of the matrix that was solved. The vector entries
796 * will be in org_col order if the rhs is normal or in org_row order
797 * if the rhs is a transpose.
798 *
799 * @return TRUE if something is amiss, FALSE otherwise.
800 *
801 */
802
803 extern real64 linsolqr_eqn_residual(linsolqr_system_t sys,
804 real64 *rhs, int32 eqn);
805 /**<
806 * Returns the equation residual using the solution vector associated
807 * with the given rhs and either the matrix or its transpose.
808 * <pre>
809 * T
810 * residual = A x - b or residual = A x - b
811 * </pre>
812 * The rhs must be solved for first. If rhs specifies transpose, then
813 * eqn is expected to be an original column number, otherwise it should
814 * be an original row number.
815 * If the system and rhs and eqn are not properly solved, the return
816 * value is MAXDOUBLE.
817 */
818
819 extern boolean linsolqr_calc_residual(linsolqr_system_t sys,
820 real64 *rhs, real64 *vector);
821 /**<
822 * Returns the residuals using the solution associated
823 * with the given rhs and either the matrix or its transpose.
824 * <pre>
825 * T
826 * residual = A x - b or residual = A x - b
827 * </pre>
828 * The rhs must be solved for first. Caller
829 * must provide vector and vector must be of length at least as long
830 * as the order of the matrix that was solved. The vector entries
831 * will be in org_row order if the rhs is normal or in org_col order
832 * if the rhs is a transpose. Entries of the vector which do not
833 * correspond to rows/cols of factored system solved will not be modified.<br><br>
834 *
835 * @return If the system and rhs are not properly solved, or other is amiss
836 * return value is TRUE, else FALSE.
837 */
838
839 /* miscellaneous functions for C programmers wanting to know things. */
840
841 extern size_t linsolqr_size(linsolqr_system_t sys);
842 /**<
843 * Returns the amount of memory in use by a system and all its
844 * bits and pieces. User supplied RHS vectors and coefficient
845 * matrix are NOT included in the size calculation. The user
846 * must do accounting for those.
847 */
848
849 extern void linsolqr_free_reused_mem(void);
850 /**<
851 * Deallocates any memory that linsolqr may be squirrelling away for
852 * internal reuse. Calling this while any slv_system_t using linsolqr exists
853 * is likely to be fatal: handle with care.
854 * There isn't a way to query how many bytes this is.
855 */
856
857 /*-----------------------------------------------------------------------------
858 * The following calls exist to facilitate debugging of the linear
859 * solver when it is being tested on large systems. Do not use them
860 * in routine coding. If you need access to the factor/inverse matrices
861 * for computational purpose, you should probably consider adding that
862 * functionality to linsol.
863 */
864
865 ASC_DLLSPEC(mtx_matrix_t ) linsolqr_get_factors(linsolqr_system_t sys);
866 /**< See discussion under linsolqr_get_inverse(). */
867 extern mtx_matrix_t linsolqr_get_inverse(linsolqr_system_t sys);
868 /**<
869 * Returns the handle of the factor (L\U, Q\R) or inverse matrix.
870 * The handle may be NULL, and should be checked before use.
871 * The matrix should not be tampered (other than to look at it)
872 * with if any other mathematical operations will take place with
873 * sys. Linsol expects to deallocate both factors and inverse; do
874 * not do so yourself.
875 *
876 * @NOTE All the factorization methods use some sort of dense vectors
877 * for storing pivots and whatnot. As with a FORTRAN factorization,
878 * there's not much you can do with a factorization without
879 * also understanding in detail the factorization routine and getting
880 * your hands on the dense vectors.
881 *
882 * @todo Separate documentation of linsolqr_get_factors()
883 * and linsolqr_get_inverse()?
884 */
885
886 extern mtx_region_t *linsolqr_get_region(linsolqr_system_t sys);
887 /**<
888 * Returns a pointer to the current linsolqr region.
889 * This is being created for use in the check numeric dependency
890 * routine and may be removed once the new "problem manager" window
891 * is created to take over this functionality (and others).
892 */
893
894 extern int linsolqr_setup_ngslv(linsolqr_system_t sys,
895 real64 *rhs,
896 mtx_range_t *un_p_rng,
897 real64 *tmpvec);
898 /**< Sets up the NGSlv solver. */
899 extern real64 *linsolqr_get_varvalue(linsolqr_system_t sys, int n);
900 /**< Returns the value of the nth variable in sys. */
901
902 #endif /* ASC_LINSOLQR_H */

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