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
);