Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/umfpack/src/umfpack/umf_kernel_wrapup.c
3203 views
1
/* ========================================================================== */
2
/* === UMF_kernel_wrapup ==================================================== */
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
/* The matrix is factorized. Finish the LU data structure. */
12
13
#include "umf_internal.h"
14
15
GLOBAL void UMF_kernel_wrapup
16
(
17
NumericType *Numeric,
18
SymbolicType *Symbolic,
19
WorkType *Work
20
)
21
{
22
23
/* ---------------------------------------------------------------------- */
24
/* local variables */
25
/* ---------------------------------------------------------------------- */
26
27
Entry pivot_value ;
28
double d ;
29
Entry *D ;
30
Int i, k, col, row, llen, ulen, *ip, *Rperm, *Cperm, *Lilen, npiv, lp,
31
*Uilen, *Lip, *Uip, *Cperm_init, up, pivrow, pivcol, *Lpos, *Upos, *Wr,
32
*Wc, *Wp, *Frpos, *Fcpos, *Row_degree, *Col_degree, *Rperm_init,
33
n_row, n_col, n_inner, zero_pivot, nan_pivot, n1 ;
34
35
#ifndef NDEBUG
36
UMF_dump_matrix (Numeric, Work, FALSE) ;
37
#endif
38
39
DEBUG0 (("Kernel complete, Starting Kernel wrapup\n")) ;
40
n_row = Symbolic->n_row ;
41
n_col = Symbolic->n_col ;
42
n_inner = MIN (n_row, n_col) ;
43
Rperm = Numeric->Rperm ;
44
Cperm = Numeric->Cperm ;
45
Lilen = Numeric->Lilen ;
46
Uilen = Numeric->Uilen ;
47
Upos = Numeric->Upos ;
48
Lpos = Numeric->Lpos ;
49
Lip = Numeric->Lip ;
50
Uip = Numeric->Uip ;
51
D = Numeric->D ;
52
53
npiv = Work->npiv ;
54
Numeric->npiv = npiv ;
55
Numeric->ulen = Work->ulen ;
56
57
ASSERT (n_row == Numeric->n_row) ;
58
ASSERT (n_col == Symbolic->n_col) ;
59
DEBUG0 (("Wrap-up: npiv "ID" ulen "ID"\n", npiv, Numeric->ulen)) ;
60
ASSERT (npiv <= n_inner) ;
61
62
/* this will be nonzero only if matrix is singular or rectangular */
63
ASSERT (IMPLIES (npiv == n_col, Work->ulen == 0)) ;
64
65
/* ---------------------------------------------------------------------- */
66
/* find the smallest and largest entries in D */
67
/* ---------------------------------------------------------------------- */
68
69
for (k = 0 ; k < npiv ; k++)
70
{
71
pivot_value = D [k] ;
72
ABS (d, pivot_value) ;
73
zero_pivot = SCALAR_IS_ZERO (d) ;
74
nan_pivot = SCALAR_IS_NAN (d) ;
75
76
if (!zero_pivot)
77
{
78
/* the pivot is nonzero, but might be Inf or NaN */
79
Numeric->nnzpiv++ ;
80
}
81
82
if (k == 0)
83
{
84
Numeric->min_udiag = d ;
85
Numeric->max_udiag = d ;
86
}
87
else
88
{
89
/* min (abs (diag (U))) behaves as follows: If any entry is zero,
90
then the result is zero (regardless of the presence of NaN's).
91
Otherwise, if any entry is NaN, then the result is NaN.
92
Otherwise, the result is the smallest absolute value on the
93
diagonal of U.
94
*/
95
96
if (SCALAR_IS_NONZERO (Numeric->min_udiag))
97
{
98
if (zero_pivot || nan_pivot)
99
{
100
Numeric->min_udiag = d ;
101
}
102
else if (!SCALAR_IS_NAN (Numeric->min_udiag))
103
{
104
/* d and min_udiag are both non-NaN */
105
Numeric->min_udiag = MIN (Numeric->min_udiag, d) ;
106
}
107
}
108
109
/*
110
max (abs (diag (U))) behaves as follows: If any entry is NaN
111
then the result is NaN. Otherise, the result is the largest
112
absolute value on the diagonal of U.
113
*/
114
115
if (nan_pivot)
116
{
117
Numeric->max_udiag = d ;
118
}
119
else if (!SCALAR_IS_NAN (Numeric->max_udiag))
120
{
121
/* d and max_udiag are both non-NaN */
122
Numeric->max_udiag = MAX (Numeric->max_udiag, d) ;
123
}
124
}
125
}
126
127
/* ---------------------------------------------------------------------- */
128
/* check if matrix is singular or rectangular */
129
/* ---------------------------------------------------------------------- */
130
131
Col_degree = Cperm ; /* for NON_PIVOTAL_COL macro */
132
Row_degree = Rperm ; /* for NON_PIVOTAL_ROW macro */
133
134
if (npiv < n_row)
135
{
136
/* finalize the row permutation */
137
k = npiv ;
138
DEBUGm3 (("Singular pivot rows "ID" to "ID"\n", k, n_row-1)) ;
139
for (row = 0 ; row < n_row ; row++)
140
{
141
if (NON_PIVOTAL_ROW (row))
142
{
143
Rperm [row] = ONES_COMPLEMENT (k) ;
144
DEBUGm3 (("Singular row "ID" is k: "ID" pivot row\n", row, k)) ;
145
ASSERT (!NON_PIVOTAL_ROW (row)) ;
146
Lpos [row] = EMPTY ;
147
Uip [row] = EMPTY ;
148
Uilen [row] = 0 ;
149
k++ ;
150
}
151
}
152
ASSERT (k == n_row) ;
153
}
154
155
if (npiv < n_col)
156
{
157
/* finalize the col permutation */
158
k = npiv ;
159
DEBUGm3 (("Singular pivot cols "ID" to "ID"\n", k, n_col-1)) ;
160
for (col = 0 ; col < n_col ; col++)
161
{
162
if (NON_PIVOTAL_COL (col))
163
{
164
Cperm [col] = ONES_COMPLEMENT (k) ;
165
DEBUGm3 (("Singular col "ID" is k: "ID" pivot row\n", col, k)) ;
166
ASSERT (!NON_PIVOTAL_COL (col)) ;
167
Upos [col] = EMPTY ;
168
Lip [col] = EMPTY ;
169
Lilen [col] = 0 ;
170
k++ ;
171
}
172
}
173
ASSERT (k == n_col) ;
174
}
175
176
if (npiv < n_inner)
177
{
178
/* finalize the diagonal of U */
179
DEBUGm3 (("Diag of U is zero, "ID" to "ID"\n", npiv, n_inner-1)) ;
180
for (k = npiv ; k < n_inner ; k++)
181
{
182
CLEAR (D [k]) ;
183
}
184
}
185
186
/* save the pattern of the last row of U */
187
if (Numeric->ulen > 0)
188
{
189
DEBUGm3 (("Last row of U is not empty\n")) ;
190
Numeric->Upattern = Work->Upattern ;
191
Work->Upattern = (Int *) NULL ;
192
}
193
194
DEBUG2 (("Nnzpiv: "ID" npiv "ID"\n", Numeric->nnzpiv, npiv)) ;
195
ASSERT (Numeric->nnzpiv <= npiv) ;
196
if (Numeric->nnzpiv < n_inner && !SCALAR_IS_NAN (Numeric->min_udiag))
197
{
198
/* the rest of the diagonal is zero, so min_udiag becomes 0,
199
* unless it is already NaN. */
200
Numeric->min_udiag = 0.0 ;
201
}
202
203
/* ---------------------------------------------------------------------- */
204
/* size n_row, n_col workspaces that can be used here: */
205
/* ---------------------------------------------------------------------- */
206
207
Frpos = Work->Frpos ; /* of size n_row+1 */
208
Fcpos = Work->Fcpos ; /* of size n_col+1 */
209
Wp = Work->Wp ; /* of size MAX(n_row,n_col)+1 */
210
/* Work->Upattern ; cannot be used (in Numeric) */
211
Wr = Work->Lpattern ; /* of size n_row+1 */
212
Wc = Work->Wrp ; /* of size n_col+1 or bigger */
213
214
/* ---------------------------------------------------------------------- */
215
/* construct Rperm from inverse permutations */
216
/* ---------------------------------------------------------------------- */
217
218
/* use Frpos for temporary copy of inverse row permutation [ */
219
220
for (pivrow = 0 ; pivrow < n_row ; pivrow++)
221
{
222
k = Rperm [pivrow] ;
223
ASSERT (k < 0) ;
224
k = ONES_COMPLEMENT (k) ;
225
ASSERT (k >= 0 && k < n_row) ;
226
Wp [k] = pivrow ;
227
Frpos [pivrow] = k ;
228
}
229
for (k = 0 ; k < n_row ; k++)
230
{
231
Rperm [k] = Wp [k] ;
232
}
233
234
/* ---------------------------------------------------------------------- */
235
/* construct Cperm from inverse permutation */
236
/* ---------------------------------------------------------------------- */
237
238
/* use Fcpos for temporary copy of inverse column permutation [ */
239
240
for (pivcol = 0 ; pivcol < n_col ; pivcol++)
241
{
242
k = Cperm [pivcol] ;
243
ASSERT (k < 0) ;
244
k = ONES_COMPLEMENT (k) ;
245
ASSERT (k >= 0 && k < n_col) ;
246
Wp [k] = pivcol ;
247
/* save a copy of the inverse column permutation in Fcpos */
248
Fcpos [pivcol] = k ;
249
}
250
for (k = 0 ; k < n_col ; k++)
251
{
252
Cperm [k] = Wp [k] ;
253
}
254
255
#ifndef NDEBUG
256
for (k = 0 ; k < n_col ; k++)
257
{
258
col = Cperm [k] ;
259
ASSERT (col >= 0 && col < n_col) ;
260
ASSERT (Fcpos [col] == k) ; /* col is the kth pivot */
261
}
262
for (k = 0 ; k < n_row ; k++)
263
{
264
row = Rperm [k] ;
265
ASSERT (row >= 0 && row < n_row) ;
266
ASSERT (Frpos [row] == k) ; /* row is the kth pivot */
267
}
268
#endif
269
270
#ifndef NDEBUG
271
UMF_dump_lu (Numeric) ;
272
#endif
273
274
/* ---------------------------------------------------------------------- */
275
/* permute Lpos, Upos, Lilen, Lip, Uilen, and Uip */
276
/* ---------------------------------------------------------------------- */
277
278
for (k = 0 ; k < npiv ; k++)
279
{
280
pivrow = Rperm [k] ;
281
Wr [k] = Uilen [pivrow] ;
282
Wp [k] = Uip [pivrow] ;
283
}
284
285
for (k = 0 ; k < npiv ; k++)
286
{
287
Uilen [k] = Wr [k] ;
288
Uip [k] = Wp [k] ;
289
}
290
291
for (k = 0 ; k < npiv ; k++)
292
{
293
pivrow = Rperm [k] ;
294
Wp [k] = Lpos [pivrow] ;
295
}
296
297
for (k = 0 ; k < npiv ; k++)
298
{
299
Lpos [k] = Wp [k] ;
300
}
301
302
for (k = 0 ; k < npiv ; k++)
303
{
304
pivcol = Cperm [k] ;
305
Wc [k] = Lilen [pivcol] ;
306
Wp [k] = Lip [pivcol] ;
307
}
308
309
for (k = 0 ; k < npiv ; k++)
310
{
311
Lilen [k] = Wc [k] ;
312
Lip [k] = Wp [k] ;
313
}
314
315
for (k = 0 ; k < npiv ; k++)
316
{
317
pivcol = Cperm [k] ;
318
Wp [k] = Upos [pivcol] ;
319
}
320
321
for (k = 0 ; k < npiv ; k++)
322
{
323
Upos [k] = Wp [k] ;
324
}
325
326
/* ---------------------------------------------------------------------- */
327
/* terminate the last Uchain and last Lchain */
328
/* ---------------------------------------------------------------------- */
329
330
Upos [npiv] = EMPTY ;
331
Lpos [npiv] = EMPTY ;
332
Uip [npiv] = EMPTY ;
333
Lip [npiv] = EMPTY ;
334
Uilen [npiv] = 0 ;
335
Lilen [npiv] = 0 ;
336
337
/* ---------------------------------------------------------------------- */
338
/* convert U to the new pivot order */
339
/* ---------------------------------------------------------------------- */
340
341
n1 = Symbolic->n1 ;
342
343
for (k = 0 ; k < n1 ; k++)
344
{
345
/* this is a singleton row of U */
346
ulen = Uilen [k] ;
347
DEBUG4 (("K "ID" New U. ulen "ID" Singleton 1\n", k, ulen)) ;
348
if (ulen > 0)
349
{
350
up = Uip [k] ;
351
ip = (Int *) (Numeric->Memory + up) ;
352
for (i = 0 ; i < ulen ; i++)
353
{
354
col = *ip ;
355
DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col]));
356
ASSERT (col >= 0 && col < n_col) ;
357
*ip++ = Fcpos [col] ;
358
}
359
}
360
}
361
362
for (k = n1 ; k < npiv ; k++)
363
{
364
up = Uip [k] ;
365
if (up < 0)
366
{
367
/* this is the start of a new Uchain (with a pattern) */
368
ulen = Uilen [k] ;
369
DEBUG4 (("K "ID" New U. ulen "ID" End_Uchain 1\n", k, ulen)) ;
370
if (ulen > 0)
371
{
372
up = -up ;
373
ip = (Int *) (Numeric->Memory + up) ;
374
for (i = 0 ; i < ulen ; i++)
375
{
376
col = *ip ;
377
DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col]));
378
ASSERT (col >= 0 && col < n_col) ;
379
*ip++ = Fcpos [col] ;
380
}
381
}
382
}
383
}
384
385
ulen = Numeric->ulen ;
386
if (ulen > 0)
387
{
388
/* convert last pivot row of U to the new pivot order */
389
DEBUG4 (("K "ID" (last)\n", k)) ;
390
for (i = 0 ; i < ulen ; i++)
391
{
392
col = Numeric->Upattern [i] ;
393
DEBUG4 ((" old col "ID" new col "ID"\n", col, Fcpos [col])) ;
394
Numeric->Upattern [i] = Fcpos [col] ;
395
}
396
}
397
398
/* Fcpos no longer needed ] */
399
400
/* ---------------------------------------------------------------------- */
401
/* convert L to the new pivot order */
402
/* ---------------------------------------------------------------------- */
403
404
for (k = 0 ; k < n1 ; k++)
405
{
406
llen = Lilen [k] ;
407
DEBUG4 (("K "ID" New L. llen "ID" Singleton col\n", k, llen)) ;
408
if (llen > 0)
409
{
410
lp = Lip [k] ;
411
ip = (Int *) (Numeric->Memory + lp) ;
412
for (i = 0 ; i < llen ; i++)
413
{
414
row = *ip ;
415
DEBUG4 ((" old row "ID" new row "ID"\n", row, Frpos [row])) ;
416
ASSERT (row >= 0 && row < n_row) ;
417
*ip++ = Frpos [row] ;
418
}
419
}
420
}
421
422
for (k = n1 ; k < npiv ; k++)
423
{
424
llen = Lilen [k] ;
425
DEBUG4 (("K "ID" New L. llen "ID" \n", k, llen)) ;
426
if (llen > 0)
427
{
428
lp = Lip [k] ;
429
if (lp < 0)
430
{
431
/* this starts a new Lchain */
432
lp = -lp ;
433
}
434
ip = (Int *) (Numeric->Memory + lp) ;
435
for (i = 0 ; i < llen ; i++)
436
{
437
row = *ip ;
438
DEBUG4 ((" old row "ID" new row "ID"\n", row, Frpos [row])) ;
439
ASSERT (row >= 0 && row < n_row) ;
440
*ip++ = Frpos [row] ;
441
}
442
}
443
}
444
445
/* Frpos no longer needed ] */
446
447
/* ---------------------------------------------------------------------- */
448
/* combine symbolic and numeric permutations */
449
/* ---------------------------------------------------------------------- */
450
451
Cperm_init = Symbolic->Cperm_init ;
452
Rperm_init = Symbolic->Rperm_init ;
453
454
for (k = 0 ; k < n_row ; k++)
455
{
456
Rperm [k] = Rperm_init [Rperm [k]] ;
457
}
458
459
for (k = 0 ; k < n_col ; k++)
460
{
461
Cperm [k] = Cperm_init [Cperm [k]] ;
462
}
463
464
/* Work object will be freed immediately upon return (to UMF_kernel */
465
/* and then to UMFPACK_numeric). */
466
}
467
468