2
* Copyright 1997, Regents of the University of Minnesota
6
* This file performs the symbolic factorization of a matrix
11
* $Id: smbfactor.c 10154 2011-06-09 21:27:35Z karypis $
18
/*************************************************************************/
19
/*! This function sets up data structures for fill-in computations */
20
/*************************************************************************/
21
void ComputeFillIn(graph_t *graph, idx_t *perm, idx_t *iperm,
22
size_t *r_maxlnz, size_t *r_opc)
24
idx_t i, j, k, nvtxs, maxlnz, maxsub;
26
idx_t *xlnz, *xnzsub, *nzsub;
30
printf("\nSymbolic factorization... --------------------------------------------\n");
35
adjncy = graph->adjncy;
37
maxsub = 8*(nvtxs+xadj[nvtxs]);
39
/* Relabel the vertices so that it starts from 1 */
40
for (i=0; i<xadj[nvtxs]; i++)
42
for (i=0; i<nvtxs+1; i++)
44
for (i=0; i<nvtxs; i++) {
49
/* Allocate the required memory */
50
xlnz = imalloc(nvtxs+2, "ComputeFillIn: xlnz");
51
xnzsub = imalloc(nvtxs+2, "ComputeFillIn: xnzsub");
52
nzsub = imalloc(maxsub+1, "ComputeFillIn: nzsub");
55
/* Call sparspak's routine. */
56
if (smbfct(nvtxs, xadj, adjncy, perm, iperm, xlnz, &maxlnz, xnzsub, nzsub, &maxsub)) {
57
printf("Realocating nzsub...\n");
58
gk_free((void **)&nzsub, LTERM);
61
nzsub = imalloc(maxsub+1, "ComputeFillIn: nzsub");
62
if (smbfct(nvtxs, xadj, adjncy, perm, iperm, xlnz, &maxlnz, xnzsub, nzsub, &maxsub))
63
errexit("MAXSUB is too small!");
66
for (i=0; i<nvtxs; i++)
68
for (opc=0, i=0; i<nvtxs; i++)
69
opc += (xlnz[i+1]-xlnz[i])*(xlnz[i+1]-xlnz[i]) - (xlnz[i+1]-xlnz[i]);
74
gk_free((void **)&xlnz, &xnzsub, &nzsub, LTERM);
76
/* Relabel the vertices so that it starts from 0 */
77
for (i=0; i<nvtxs; i++) {
81
for (i=0; i<nvtxs+1; i++)
83
for (i=0; i<xadj[nvtxs]; i++)
90
/*************************************************************************/
92
PURPOSE - THIS ROUTINE PERFORMS SYMBOLIC FACTORIZATION
93
ON A PERMUTED LINEAR SYSTEM AND IT ALSO SETS UP THE
94
COMPRESSED DATA STRUCTURE FOR THE SYSTEM.
97
NEQNS - NUMBER OF EQUATIONS.
98
(XADJ, ADJNCY) - THE ADJACENCY STRUCTURE.
99
(PERM, INVP) - THE PERMUTATION VECTOR AND ITS INVERSE.
102
MAXSUB - SIZE OF THE SUBSCRIPT ARRAY NZSUB. ON RETURN,
103
IT CONTAINS THE NUMBER OF SUBSCRIPTS USED
106
XLNZ - INDEX INTO THE NONZERO STORAGE VECTOR LNZ.
107
(XNZSUB, NZSUB) - THE COMPRESSED SUBSCRIPT VECTORS.
108
MAXLNZ - THE NUMBER OF NONZEROS FOUND.
110
/*************************************************************************/
111
idx_t smbfct(idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t *perm, idx_t *invp,
112
idx_t *xlnz, idx_t *maxlnz, idx_t *xnzsub, idx_t *nzsub,
115
/* Local variables */
116
idx_t node, rchm, mrgk, lmax, i, j, k, m, nabor, nzbeg, nzend;
117
idx_t kxsub, jstop, jstrt, mrkflg, inz, knz, flag;
118
idx_t *mrglnk, *marker, *rchlnk;
120
rchlnk = ismalloc(neqns+1, 0, "smbfct: rchlnk");
121
marker = ismalloc(neqns+1, 0, "smbfct: marker");
122
mrglnk = ismalloc(neqns+1, 0, "smbfct: mgrlnk");
124
/* Parameter adjustments */
142
/* FOR EACH COLUMN KNZ COUNTS THE NUMBER OF NONZEROS IN COLUMN K ACCUMULATED IN RCHLNK. */
143
for (k=1; k<=neqns; k++) {
151
assert(mrgk > 0 && mrgk <= neqns);
152
marker[k] = marker[mrgk];
155
if (xadj[node] >= xadj[node+1]) {
160
/* USE RCHLNK TO LINK THROUGH THE STRUCTURE OF A(*,K) BELOW DIAGONAL */
161
assert(k <= neqns && k > 0);
163
for (j=xadj[node]; j<xadj[node+1]; j++) {
164
nabor = invp[adjncy[j]];
171
assert(m > 0 && m <= neqns);
173
} while (rchm <= nabor);
176
assert(m > 0 && m <= neqns);
178
assert(nabor > 0 && nabor <= neqns);
179
rchlnk[nabor] = rchm;
180
assert(k > 0 && k <= neqns);
181
if (marker[nabor] != marker[k])
186
/* TEST FOR MASS SYMBOLIC ELIMINATION */
188
assert(mrgk >= 0 && mrgk <= neqns);
189
if (mrkflg != 0 || mrgk == 0 || mrglnk[mrgk] != 0)
191
xnzsub[k] = xnzsub[mrgk] + 1;
192
knz = xlnz[mrgk + 1] - (xlnz[mrgk] + 1);
197
/* LINK THROUGH EACH COLUMN I THAT AFFECTS L(*,K) */
199
assert(i > 0 && i <= neqns);
200
while ((i = mrglnk[i]) != 0) {
201
assert(i > 0 && i <= neqns);
202
inz = xlnz[i+1] - (xlnz[i]+1);
203
jstrt = xnzsub[i] + 1;
204
jstop = xnzsub[i] + inz;
211
/* MERGE STRUCTURE OF L(*,I) IN NZSUB INTO RCHLNK. */
213
for (j=jstrt; j<=jstop; j++) {
217
assert(m > 0 && m <= neqns);
219
} while (rchm < nabor);
223
assert(m > 0 && m <= neqns);
225
assert(nabor > 0 && nabor <= neqns);
226
rchlnk[nabor] = rchm;
233
/* CHECK IF SUBSCRIPTS DUPLICATE THOSE OF ANOTHER COLUMN */
237
/* OR IF TAIL OF K-1ST COLUMN MATCHES HEAD OF KTH */
241
assert(k > 0 && k <= neqns);
243
for (jstrt = nzbeg; jstrt <= nzend; ++jstrt) {
244
if (nzsub[jstrt] < i)
247
if (nzsub[jstrt] == i)
257
for (j = jstrt; j <= nzend; ++j) {
261
assert(i > 0 && i <= neqns);
269
/* COPY THE STRUCTURE OF L(*,K) FROM RCHLNK TO THE DATA STRUCTURE (XNZSUB, NZSUB) */
274
if (nzend >= *maxsub) {
275
flag = 1; /* Out of memory */
280
for (j=nzbeg; j<=nzend; j++) {
281
assert(i > 0 && i <= neqns);
284
assert(i > 0 && i <= neqns);
288
assert(k > 0 && k <= neqns);
292
* UPDATE THE VECTOR MRGLNK. NOTE COLUMN L(*,K) JUST FOUND
293
* IS REQUIRED TO DETERMINE COLUMN L(*,J), WHERE
294
* L(J,K) IS THE FIRST NONZERO IN L(*,K) BELOW DIAGONAL.
300
assert(i > 0 && i <= neqns);
301
assert(k > 0 && k <= neqns);
302
mrglnk[k] = mrglnk[i];
306
xlnz[k + 1] = xlnz[k] + knz;
310
*maxlnz = xlnz[neqns] - 1;
311
*maxsub = xnzsub[neqns];
312
xnzsub[neqns + 1] = xnzsub[neqns];
327
gk_free((void **)&rchlnk, &mrglnk, &marker, LTERM);