Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/umfpack/demo/umf4.c
3196 views
1
/* ========================================================================== */
2
/* === umf4 ================================================================= */
3
/* ========================================================================== */
4
5
/* -------------------------------------------------------------------------- */
6
/* UMFPACK Version 4.4, Copyright (c) 2005 by Timothy A. Davis. CISE Dept, */
7
/* Univ. of Florida. All Rights Reserved. See ../Doc/License for License. */
8
/* web: http://www.cise.ufl.edu/research/sparse/umfpack */
9
/* -------------------------------------------------------------------------- */
10
11
/* Demo program for UMFPACK. Reads in a triplet-form matrix in the
12
* directory tmp/A, whose size and # of nonzeros are in the file tmp/Asize.
13
* Then calls UMFPACK to analyze, factor, and solve the system.
14
*
15
* Syntax:
16
*
17
* umf4 default "auto" strategy, 1-norm row scaling
18
* umf4 a default "auto" strategy, 1-norm row scaling
19
* umf4 u unsymmetric strategy, 1-norm row scaling
20
* umf4 s symmetric strategy, 1-norm row scaling
21
* umf4 2 2-by-2 strategy, maxnorm row scaling
22
* umf4 A default "auto" strategy, maxnorm row scaling
23
* umf4 U unsymmetric strategy, maxnorm row scaling
24
* umf4 S symmetric strategy, maxnorm row scaling
25
* umf4 T 2-by-2 strategy , maxnorm row scaling
26
*
27
* To test a matrix in the Harwell/Boeing format, do the following:
28
*
29
* readhb < HB/arc130.rua > tmp/A
30
* readhb_size < HB/arc130.rua > tmp/Asize
31
* umf4
32
*
33
* The above options do not drop any nonzero entry in L or U. To compute an
34
* incomplete factorization, you can add a second argument to give the drop
35
* tolerance. Entries less than or equal to the drop tolerance are then
36
* removed from L and U during factorization, unless dropping those entries
37
* does not save any memory space. For example:
38
*
39
* umf4 a 1e-6 default "auto" strategy, 1-norm row scaling,
40
* drop tolerance of 1e-6.
41
*
42
* Note that adding a drop tolerance can lead to an apparent (but not real)
43
* increase in peak memory usage. This is illustrated in the arc130.rua
44
* matrix. With a drop tolerance, garbage collection happens to be avoided
45
* for this matrix. During garbage collection, both internal and external
46
* fragmentation in the memory space is removed. Peak memory usage includes
47
* all internal memory fragmentation, even though this can be removed via
48
* garbage collection.
49
*
50
* Control parameters can also be set in the optional tmp/control.umf4 file.
51
* The right-hand-side can be provided in the optional tmp/b file. The solution
52
* is written to tmp/x, and the output statistics are written to tmp/info.umf4.
53
*
54
* After the matrix is factorized, solved, and the LU factors deallocated,
55
* this program then test the AMD ordering routine. This call to AMD is NOT
56
* part of the UMFPACK analysis, factorize, or solve steps. It is just a
57
* separate test of the AMD ordering routine. If the matrix is unsymmetric,
58
* AMD orders the pattern of A+A'.
59
*/
60
61
#include <stdio.h>
62
#include <stdlib.h>
63
#include <math.h>
64
#include "umfpack.h"
65
#include "amd.h"
66
67
#define SMAX 256
68
#define ABS(x) ((x) >= 0 ? (x) : -(x))
69
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
70
71
#define XTRUE(i,n) (1.0 + ((double) i) / ((double) n))
72
73
#ifndef FALSE
74
#define FALSE 0
75
#endif
76
77
#ifndef TRUE
78
#define TRUE 1
79
#endif
80
81
/* -------------------------------------------------------------------------- */
82
/* err: compute the relative error, ||x-xtrue||/||xtrue|| */
83
/* -------------------------------------------------------------------------- */
84
85
static double err
86
(
87
int n,
88
double x [ ]
89
)
90
{
91
int i ;
92
double enorm, e, abse, absxtrue, xnorm ;
93
enorm = 0 ;
94
xnorm = 0 ;
95
96
for (i = 0 ; i < n ; i++)
97
{
98
if (isnan (x [i]))
99
{
100
enorm = x [i] ;
101
break ;
102
}
103
e = x [i] - XTRUE (i,n) ;
104
abse = ABS (e) ;
105
enorm = MAX (enorm, abse) ;
106
}
107
108
for (i = 0 ; i < n ; i++)
109
{
110
/* XTRUE is positive, but do this in case XTRUE is redefined */
111
absxtrue = ABS (XTRUE (i,n)) ;
112
xnorm = MAX (xnorm, absxtrue) ;
113
}
114
115
if (xnorm == 0)
116
{
117
xnorm = 1 ;
118
}
119
return (enorm / xnorm) ;
120
}
121
122
123
/* -------------------------------------------------------------------------- */
124
/* resid: compute the relative residual, ||Ax-b||/||b|| or ||A'x-b||/||b|| */
125
/* -------------------------------------------------------------------------- */
126
127
static double resid
128
(
129
int n,
130
int Ap [ ],
131
int Ai [ ],
132
double Ax [ ],
133
double x [ ],
134
double r [ ],
135
double b [ ],
136
int transpose
137
)
138
{
139
int i, j, p ;
140
double rnorm, absr, absb, bnorm ;
141
for (i = 0 ; i < n ; i++)
142
{
143
r [i] = 0 ;
144
}
145
146
if (transpose)
147
{
148
for (j = 0 ; j < n ; j++)
149
{
150
for (p = Ap [j] ; p < Ap [j+1] ; p++)
151
{
152
i = Ai [p] ;
153
r [j] += Ax [p] * x [i] ;
154
}
155
}
156
}
157
else
158
{
159
for (j = 0 ; j < n ; j++)
160
{
161
for (p = Ap [j] ; p < Ap [j+1] ; p++)
162
{
163
i = Ai [p] ;
164
r [i] += Ax [p] * x [j] ;
165
}
166
}
167
}
168
169
for (i = 0 ; i < n ; i++)
170
{
171
r [i] -= b [i] ;
172
}
173
rnorm = 0. ;
174
bnorm = 0. ;
175
for (i = 0 ; i < n ; i++)
176
{
177
if (isnan (r [i]))
178
{
179
rnorm = r [i] ;
180
break ;
181
}
182
absr = ABS (r [i]) ;
183
rnorm = MAX (rnorm, absr) ;
184
}
185
for (i = 0 ; i < n ; i++)
186
{
187
if (isnan (b [i]))
188
{
189
bnorm = b [i] ;
190
break ;
191
}
192
absb = ABS (b [i]) ;
193
bnorm = MAX (bnorm, absb) ;
194
}
195
if (bnorm == 0)
196
{
197
bnorm = 1 ;
198
}
199
return (rnorm / bnorm) ;
200
}
201
202
203
/* -------------------------------------------------------------------------- */
204
/* Atimesx: compute y = A*x or A'*x, where x (i) = 1 + i/n */
205
/* -------------------------------------------------------------------------- */
206
207
static void Atimesx
208
(
209
int n,
210
int Ap [ ],
211
int Ai [ ],
212
double Ax [ ],
213
double y [ ],
214
int transpose
215
)
216
{
217
int i, j, p ;
218
for (i = 0 ; i < n ; i++)
219
{
220
y [i] = 0 ;
221
}
222
if (transpose)
223
{
224
for (j = 0 ; j < n ; j++)
225
{
226
for (p = Ap [j] ; p < Ap [j+1] ; p++)
227
{
228
i = Ai [p] ;
229
y [j] += Ax [p] * XTRUE (i,n) ;
230
}
231
}
232
}
233
else
234
{
235
for (j = 0 ; j < n ; j++)
236
{
237
for (p = Ap [j] ; p < Ap [j+1] ; p++)
238
{
239
i = Ai [p] ;
240
y [i] += Ax [p] * XTRUE (j,n) ;
241
}
242
}
243
}
244
}
245
246
/* -------------------------------------------------------------------------- */
247
/* main program */
248
/* -------------------------------------------------------------------------- */
249
250
int main (int argc, char **argv)
251
{
252
int i, j, k, n, nz, *Ap, *Ai, *Ti, *Tj, status, *Pamd, nrow, ncol, rhs ;
253
double *Ax, *b, *x, Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], aij,
254
*Tx, *r, amd_Control [AMD_CONTROL], amd_Info [AMD_INFO], tamd [2],
255
stats [2], droptol ;
256
void *Symbolic, *Numeric ;
257
FILE *f, *f2 ;
258
char s [SMAX] ;
259
260
/* ---------------------------------------------------------------------- */
261
/* set controls */
262
/* ---------------------------------------------------------------------- */
263
264
printf ("\n===========================================================\n"
265
"=== UMFPACK v4.4 ==========================================\n"
266
"===========================================================\n") ;
267
268
umfpack_di_defaults (Control) ;
269
Control [UMFPACK_PRL] = 3 ;
270
Control [UMFPACK_BLOCK_SIZE] = 32 ;
271
272
f = fopen ("tmp/control.umf4", "r") ;
273
if (f != (FILE *) NULL)
274
{
275
printf ("Reading control file tmp/control.umf4\n") ;
276
for (i = 0 ; i < UMFPACK_CONTROL ; i++)
277
{
278
fscanf (f, "%lg\n", & Control [i]) ;
279
}
280
fclose (f) ;
281
}
282
283
if (argc > 1)
284
{
285
char *s = argv [1] ;
286
287
/* get the strategy */
288
if (s [0] == 'u')
289
{
290
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ;
291
}
292
else if (s [0] == 'a')
293
{
294
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ;
295
}
296
else if (s [0] == 's')
297
{
298
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ;
299
}
300
else if (s [0] == '2')
301
{
302
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2 ;
303
}
304
else if (s [0] == 'U')
305
{
306
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_UNSYMMETRIC ;
307
Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ;
308
}
309
else if (s [0] == 'A')
310
{
311
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_AUTO ;
312
Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ;
313
}
314
else if (s [0] == 'S')
315
{
316
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_SYMMETRIC ;
317
Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ;
318
}
319
else if (s [0] == 'T')
320
{
321
Control [UMFPACK_STRATEGY] = UMFPACK_STRATEGY_2BY2 ;
322
Control [UMFPACK_SCALE] = UMFPACK_SCALE_MAX ;
323
}
324
else
325
{
326
printf ("unrecognized strategy: %s\n", argv [1]) ;
327
}
328
329
if (s [1] == 'n')
330
{
331
/* no aggressive absorption */
332
Control [UMFPACK_AGGRESSIVE] = FALSE ;
333
}
334
}
335
336
if (argc > 2)
337
{
338
/* get the drop tolerance */
339
sscanf (argv [2], "%lg", &droptol) ;
340
printf ("droptol %g\n", droptol) ;
341
Control [UMFPACK_DROPTOL] = droptol ;
342
}
343
344
umfpack_di_report_control (Control) ;
345
346
/* ---------------------------------------------------------------------- */
347
/* open the matrix file (tmp/A) */
348
/* ---------------------------------------------------------------------- */
349
350
printf ("File: tmp/A\n") ;
351
f = fopen ("tmp/A", "r") ;
352
if (!f)
353
{
354
printf ("Unable to open file\n") ;
355
exit (1) ;
356
}
357
358
/* ---------------------------------------------------------------------- */
359
/* get n and nz */
360
/* ---------------------------------------------------------------------- */
361
362
printf ("File: tmp/Asize\n") ;
363
f2 = fopen ("tmp/Asize", "r") ;
364
if (f2)
365
{
366
fscanf (f2, "%d %d %d\n", &nrow, &ncol, &nz) ;
367
fclose (f2) ;
368
}
369
else
370
{
371
nrow = 1 ;
372
ncol = 1 ;
373
}
374
nz = 0 ;
375
while (fgets (s, SMAX, f) != (char *) NULL)
376
{
377
sscanf (s, "%d %d %lg", &i, &j, &aij) ;
378
#ifdef ZERO_BASED
379
/* matrix is zero based */
380
i++ ;
381
j++ ;
382
#endif
383
nrow = MAX (nrow, i) ;
384
ncol = MAX (ncol, j) ;
385
nz++ ;
386
}
387
fclose (f) ;
388
n = MAX (nrow, ncol) ;
389
390
printf ("n %d nrow %d ncol %d nz %d\n", n, nrow, ncol, nz) ;
391
392
/* ---------------------------------------------------------------------- */
393
/* allocate space for the input triplet form */
394
/* ---------------------------------------------------------------------- */
395
396
Ti = (int *) malloc (nz * sizeof (int)) ;
397
Tj = (int *) malloc (nz * sizeof (int)) ;
398
Tx = (double *) malloc (nz * sizeof (double)) ;
399
if (!Ti || !Tj || !Tx)
400
{
401
printf ("out of memory for input matrix\n") ;
402
exit (1) ;
403
}
404
405
/* ---------------------------------------------------------------------- */
406
/* read in the triplet form */
407
/* ---------------------------------------------------------------------- */
408
409
f2 = fopen ("tmp/A", "r") ;
410
if (!f2)
411
{
412
printf ("Unable to open file\n") ;
413
exit (1) ;
414
}
415
416
k = 0 ;
417
while (fgets (s, SMAX, f2) != (char *) NULL)
418
{
419
sscanf (s, "%d %d %lg", &i, &j, &aij) ;
420
#ifndef ZERO_BASED
421
i-- ; /* convert to 0-based */
422
j-- ;
423
#endif
424
if (k >= nz)
425
{
426
printf ("Error! Matrix size is wrong\n") ;
427
exit (1) ;
428
}
429
Ti [k] = i ;
430
Tj [k] = j ;
431
Tx [k] = aij ;
432
k++ ;
433
}
434
fclose (f2) ;
435
436
(void) umfpack_di_report_triplet (nrow, ncol, nz, Ti, Tj, Tx, Control) ;
437
438
/* ---------------------------------------------------------------------- */
439
/* convert to column form */
440
/* ---------------------------------------------------------------------- */
441
442
/* convert to column form */
443
Ap = (int *) malloc ((n+1) * sizeof (int)) ;
444
Ai = (int *) malloc (nz * sizeof (int)) ;
445
Ax = (double *) malloc (nz * sizeof (double)) ;
446
b = (double *) malloc (n * sizeof (double)) ;
447
r = (double *) malloc (n * sizeof (double)) ;
448
x = (double *) malloc (n * sizeof (double)) ;
449
if (!Ap || !Ai || !Ax || !b || !r)
450
{
451
printf ("out of memory") ;
452
exit (1) ;
453
}
454
umfpack_tic (stats) ;
455
status = umfpack_di_triplet_to_col (nrow, ncol, nz, Ti, Tj, Tx, Ap, Ai, Ax,
456
(int *) NULL) ;
457
umfpack_toc (stats) ;
458
printf ("triplet-to-col time: wall %g cpu %g\n", stats [0], stats [1]) ;
459
if (status != UMFPACK_OK)
460
{
461
umfpack_di_report_status (Control, status) ;
462
printf ("umfpack_di_triplet_to_col failed") ;
463
exit (1) ;
464
}
465
466
/* print the column-form of A */
467
(void) umfpack_di_report_matrix (nrow, ncol, Ap, Ai, Ax, 1, Control) ;
468
469
/* b = A * xtrue */
470
rhs = FALSE ;
471
if (nrow == ncol)
472
{
473
f = fopen ("tmp/b", "r") ;
474
if (f != (FILE *) NULL)
475
{
476
printf ("Reading tmp/b\n") ;
477
rhs = TRUE ;
478
for (i = 0 ; i < n ; i++)
479
{
480
fscanf (f, "%lg\n", &b [i]) ;
481
}
482
fclose (f) ;
483
}
484
else
485
{
486
Atimesx (n, Ap, Ai, Ax, b, FALSE) ;
487
}
488
}
489
490
/* ---------------------------------------------------------------------- */
491
/* free the triplet form */
492
/* ---------------------------------------------------------------------- */
493
494
free (Ti) ;
495
free (Tj) ;
496
free (Tx) ;
497
498
/* ---------------------------------------------------------------------- */
499
/* symbolic factorization */
500
/* ---------------------------------------------------------------------- */
501
502
status = umfpack_di_symbolic (nrow, ncol, Ap, Ai, Ax, &Symbolic,
503
Control, Info) ;
504
505
umfpack_di_report_info (Control, Info) ;
506
if (status != UMFPACK_OK)
507
{
508
umfpack_di_report_status (Control, status) ;
509
printf ("umfpack_di_symbolic failed") ;
510
exit (1) ;
511
}
512
513
/* print the symbolic factorization */
514
(void) umfpack_di_report_symbolic (Symbolic, Control) ;
515
516
/* ---------------------------------------------------------------------- */
517
/* numeric factorization */
518
/* ---------------------------------------------------------------------- */
519
520
status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info);
521
if (status < UMFPACK_OK)
522
{
523
umfpack_di_report_info (Control, Info) ;
524
umfpack_di_report_status (Control, status) ;
525
fprintf (stderr, "umfpack_di_numeric failed: %d\n", status) ;
526
printf ("umfpack_di_numeric failed\n") ;
527
exit (1) ;
528
}
529
530
/* print the numeric factorization */
531
(void) umfpack_di_report_numeric (Numeric, Control) ;
532
533
/* ---------------------------------------------------------------------- */
534
/* solve Ax=b */
535
/* ---------------------------------------------------------------------- */
536
537
if (nrow == ncol && status == UMFPACK_OK)
538
{
539
status = umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric,
540
Control, Info) ;
541
542
umfpack_di_report_info (Control, Info) ;
543
umfpack_di_report_status (Control, status) ;
544
if (status < UMFPACK_OK)
545
{
546
printf ("umfpack_di_solve failed\n") ;
547
exit (1) ;
548
}
549
(void) umfpack_di_report_vector (n, x, Control) ;
550
printf ("relative maxnorm of residual, ||Ax-b||/||b||: %g\n",
551
resid (n, Ap, Ai, Ax, x, r, b, FALSE)) ;
552
if (!rhs)
553
{
554
printf ("relative maxnorm of error, ||x-xtrue||/||xtrue||: %g\n\n",
555
err (n, x)) ;
556
}
557
558
f = fopen ("tmp/x", "w") ;
559
if (f != (FILE *) NULL)
560
{
561
printf ("Writing tmp/x\n") ;
562
for (i = 0 ; i < n ; i++)
563
{
564
fprintf (f, "%30.20e\n", x [i]) ;
565
}
566
fclose (f) ;
567
}
568
else
569
{
570
printf ("Unable to write output x!\n") ;
571
exit (1) ;
572
}
573
574
f = fopen ("tmp/info.umf4", "w") ;
575
if (f != (FILE *) NULL)
576
{
577
printf ("Writing tmp/info.umf4\n") ;
578
for (i = 0 ; i < UMFPACK_INFO ; i++)
579
{
580
fprintf (f, "%30.20e\n", Info [i]) ;
581
}
582
fclose (f) ;
583
}
584
else
585
{
586
printf ("Unable to write output info!\n") ;
587
exit (1) ;
588
}
589
}
590
else
591
{
592
/* don't solve, just report the results */
593
umfpack_di_report_info (Control, Info) ;
594
umfpack_di_report_status (Control, status) ;
595
}
596
597
/* ---------------------------------------------------------------------- */
598
/* free the Symbolic and Numeric factorization */
599
/* ---------------------------------------------------------------------- */
600
601
umfpack_di_free_symbolic (&Symbolic) ;
602
umfpack_di_free_numeric (&Numeric) ;
603
604
printf ("umf4 done, strategy: %g\n", Control [UMFPACK_STRATEGY]) ;
605
606
/* ---------------------------------------------------------------------- */
607
/* test just AMD ordering (not part of UMFPACK, but a separate test) */
608
/* ---------------------------------------------------------------------- */
609
610
/* first make the matrix square */
611
if (ncol < n)
612
{
613
for (j = ncol+1 ; j <= n ; j++)
614
{
615
Ap [j] = Ap [ncol] ;
616
}
617
}
618
619
printf (
620
"\n\n===========================================================\n"
621
"=== AMD ===================================================\n"
622
"===========================================================\n") ;
623
printf ("\n\n------- Now trying the AMD ordering. This not part of\n"
624
"the UMFPACK analysis or factorization, above, but a separate\n"
625
"test of just the AMD ordering routine.\n") ;
626
Pamd = (int *) malloc (n * sizeof (int)) ;
627
if (!Pamd)
628
{
629
printf ("out of memory\n") ;
630
exit (1) ;
631
}
632
amd_defaults (amd_Control) ;
633
amd_control (amd_Control) ;
634
umfpack_tic (tamd) ;
635
status = amd_order (n, Ap, Ai, Pamd, amd_Control, amd_Info) ;
636
umfpack_toc (tamd) ;
637
printf ("AMD ordering time: cpu %10.2f wall %10.2f\n",
638
tamd [1], tamd [0]) ;
639
if (status != AMD_OK)
640
{
641
printf ("amd failed: %d\n", status) ;
642
exit (1) ;
643
}
644
amd_info (amd_Info) ;
645
free (Pamd) ;
646
printf ("AMD test done\n") ;
647
648
return (0) ;
649
}
650
651