Path: blob/devel/elmergrid/src/metis-5.1.0/programs/smbfactor.c
3206 views
/*1* Copyright 1997, Regents of the University of Minnesota2*3* smbfactor.c4*5* This file performs the symbolic factorization of a matrix6*7* Started 8/1/978* George9*10* $Id: smbfactor.c 10154 2011-06-09 21:27:35Z karypis $11*12*/1314#include "metisbin.h"151617/*************************************************************************/18/*! This function sets up data structures for fill-in computations */19/*************************************************************************/20void ComputeFillIn(graph_t *graph, idx_t *perm, idx_t *iperm,21size_t *r_maxlnz, size_t *r_opc)22{23idx_t i, j, k, nvtxs, maxlnz, maxsub;24idx_t *xadj, *adjncy;25idx_t *xlnz, *xnzsub, *nzsub;26size_t opc;2728/*29printf("\nSymbolic factorization... --------------------------------------------\n");30*/3132nvtxs = graph->nvtxs;33xadj = graph->xadj;34adjncy = graph->adjncy;3536maxsub = 8*(nvtxs+xadj[nvtxs]);3738/* Relabel the vertices so that it starts from 1 */39for (i=0; i<xadj[nvtxs]; i++)40adjncy[i]++;41for (i=0; i<nvtxs+1; i++)42xadj[i]++;43for (i=0; i<nvtxs; i++) {44iperm[i]++;45perm[i]++;46}4748/* Allocate the required memory */49xlnz = imalloc(nvtxs+2, "ComputeFillIn: xlnz");50xnzsub = imalloc(nvtxs+2, "ComputeFillIn: xnzsub");51nzsub = imalloc(maxsub+1, "ComputeFillIn: nzsub");525354/* Call sparspak's routine. */55if (smbfct(nvtxs, xadj, adjncy, perm, iperm, xlnz, &maxlnz, xnzsub, nzsub, &maxsub)) {56printf("Realocating nzsub...\n");57gk_free((void **)&nzsub, LTERM);5859maxsub *= 2;60nzsub = imalloc(maxsub+1, "ComputeFillIn: nzsub");61if (smbfct(nvtxs, xadj, adjncy, perm, iperm, xlnz, &maxlnz, xnzsub, nzsub, &maxsub))62errexit("MAXSUB is too small!");63}6465for (i=0; i<nvtxs; i++)66xlnz[i]--;67for (opc=0, i=0; i<nvtxs; i++)68opc += (xlnz[i+1]-xlnz[i])*(xlnz[i+1]-xlnz[i]) - (xlnz[i+1]-xlnz[i]);6970*r_maxlnz = maxlnz;71*r_opc = opc;7273gk_free((void **)&xlnz, &xnzsub, &nzsub, LTERM);7475/* Relabel the vertices so that it starts from 0 */76for (i=0; i<nvtxs; i++) {77iperm[i]--;78perm[i]--;79}80for (i=0; i<nvtxs+1; i++)81xadj[i]--;82for (i=0; i<xadj[nvtxs]; i++)83adjncy[i]--;8485}86878889/*************************************************************************/90/*!91PURPOSE - THIS ROUTINE PERFORMS SYMBOLIC FACTORIZATION92ON A PERMUTED LINEAR SYSTEM AND IT ALSO SETS UP THE93COMPRESSED DATA STRUCTURE FOR THE SYSTEM.9495INPUT PARAMETERS -96NEQNS - NUMBER OF EQUATIONS.97(XADJ, ADJNCY) - THE ADJACENCY STRUCTURE.98(PERM, INVP) - THE PERMUTATION VECTOR AND ITS INVERSE.99100UPDATED PARAMETERS -101MAXSUB - SIZE OF THE SUBSCRIPT ARRAY NZSUB. ON RETURN,102IT CONTAINS THE NUMBER OF SUBSCRIPTS USED103104OUTPUT PARAMETERS -105XLNZ - INDEX INTO THE NONZERO STORAGE VECTOR LNZ.106(XNZSUB, NZSUB) - THE COMPRESSED SUBSCRIPT VECTORS.107MAXLNZ - THE NUMBER OF NONZEROS FOUND.108*/109/*************************************************************************/110idx_t smbfct(idx_t neqns, idx_t *xadj, idx_t *adjncy, idx_t *perm, idx_t *invp,111idx_t *xlnz, idx_t *maxlnz, idx_t *xnzsub, idx_t *nzsub,112idx_t *maxsub)113{114/* Local variables */115idx_t node, rchm, mrgk, lmax, i, j, k, m, nabor, nzbeg, nzend;116idx_t kxsub, jstop, jstrt, mrkflg, inz, knz, flag;117idx_t *mrglnk, *marker, *rchlnk;118119rchlnk = ismalloc(neqns+1, 0, "smbfct: rchlnk");120marker = ismalloc(neqns+1, 0, "smbfct: marker");121mrglnk = ismalloc(neqns+1, 0, "smbfct: mgrlnk");122123/* Parameter adjustments */124--marker;125--mrglnk;126--rchlnk;127--nzsub;128--xnzsub;129--xlnz;130--invp;131--perm;132--adjncy;133--xadj;134135/* Function Body */136flag = 0;137nzbeg = 1;138nzend = 0;139xlnz[1] = 1;140141/* FOR EACH COLUMN KNZ COUNTS THE NUMBER OF NONZEROS IN COLUMN K ACCUMULATED IN RCHLNK. */142for (k=1; k<=neqns; k++) {143xnzsub[k] = nzend;144node = perm[k];145knz = 0;146mrgk = mrglnk[k];147mrkflg = 0;148marker[k] = k;149if (mrgk != 0) {150assert(mrgk > 0 && mrgk <= neqns);151marker[k] = marker[mrgk];152}153154if (xadj[node] >= xadj[node+1]) {155xlnz[k+1] = xlnz[k];156continue;157}158159/* USE RCHLNK TO LINK THROUGH THE STRUCTURE OF A(*,K) BELOW DIAGONAL */160assert(k <= neqns && k > 0);161rchlnk[k] = neqns+1;162for (j=xadj[node]; j<xadj[node+1]; j++) {163nabor = invp[adjncy[j]];164if (nabor <= k)165continue;166rchm = k;167168do {169m = rchm;170assert(m > 0 && m <= neqns);171rchm = rchlnk[m];172} while (rchm <= nabor);173174knz++;175assert(m > 0 && m <= neqns);176rchlnk[m] = nabor;177assert(nabor > 0 && nabor <= neqns);178rchlnk[nabor] = rchm;179assert(k > 0 && k <= neqns);180if (marker[nabor] != marker[k])181mrkflg = 1;182}183184185/* TEST FOR MASS SYMBOLIC ELIMINATION */186lmax = 0;187assert(mrgk >= 0 && mrgk <= neqns);188if (mrkflg != 0 || mrgk == 0 || mrglnk[mrgk] != 0)189goto L350;190xnzsub[k] = xnzsub[mrgk] + 1;191knz = xlnz[mrgk + 1] - (xlnz[mrgk] + 1);192goto L1400;193194195L350:196/* LINK THROUGH EACH COLUMN I THAT AFFECTS L(*,K) */197i = k;198assert(i > 0 && i <= neqns);199while ((i = mrglnk[i]) != 0) {200assert(i > 0 && i <= neqns);201inz = xlnz[i+1] - (xlnz[i]+1);202jstrt = xnzsub[i] + 1;203jstop = xnzsub[i] + inz;204205if (inz > lmax) {206lmax = inz;207xnzsub[k] = jstrt;208}209210/* MERGE STRUCTURE OF L(*,I) IN NZSUB INTO RCHLNK. */211rchm = k;212for (j=jstrt; j<=jstop; j++) {213nabor = nzsub[j];214do {215m = rchm;216assert(m > 0 && m <= neqns);217rchm = rchlnk[m];218} while (rchm < nabor);219220if (rchm != nabor) {221knz++;222assert(m > 0 && m <= neqns);223rchlnk[m] = nabor;224assert(nabor > 0 && nabor <= neqns);225rchlnk[nabor] = rchm;226rchm = nabor;227}228}229}230231232/* CHECK IF SUBSCRIPTS DUPLICATE THOSE OF ANOTHER COLUMN */233if (knz == lmax)234goto L1400;235236/* OR IF TAIL OF K-1ST COLUMN MATCHES HEAD OF KTH */237if (nzbeg > nzend)238goto L1200;239240assert(k > 0 && k <= neqns);241i = rchlnk[k];242for (jstrt = nzbeg; jstrt <= nzend; ++jstrt) {243if (nzsub[jstrt] < i)244continue;245246if (nzsub[jstrt] == i)247goto L1000;248else249goto L1200;250}251goto L1200;252253254L1000:255xnzsub[k] = jstrt;256for (j = jstrt; j <= nzend; ++j) {257if (nzsub[j] != i)258goto L1200;259260assert(i > 0 && i <= neqns);261i = rchlnk[i];262if (i > neqns)263goto L1400;264}265nzend = jstrt - 1;266267268/* COPY THE STRUCTURE OF L(*,K) FROM RCHLNK TO THE DATA STRUCTURE (XNZSUB, NZSUB) */269L1200:270nzbeg = nzend + 1;271nzend += knz;272273if (nzend >= *maxsub) {274flag = 1; /* Out of memory */275break;276}277278i = k;279for (j=nzbeg; j<=nzend; j++) {280assert(i > 0 && i <= neqns);281i = rchlnk[i];282nzsub[j] = i;283assert(i > 0 && i <= neqns);284marker[i] = k;285}286xnzsub[k] = nzbeg;287assert(k > 0 && k <= neqns);288marker[k] = k;289290/*291* UPDATE THE VECTOR MRGLNK. NOTE COLUMN L(*,K) JUST FOUND292* IS REQUIRED TO DETERMINE COLUMN L(*,J), WHERE293* L(J,K) IS THE FIRST NONZERO IN L(*,K) BELOW DIAGONAL.294*/295L1400:296if (knz > 1) {297kxsub = xnzsub[k];298i = nzsub[kxsub];299assert(i > 0 && i <= neqns);300assert(k > 0 && k <= neqns);301mrglnk[k] = mrglnk[i];302mrglnk[i] = k;303}304305xlnz[k + 1] = xlnz[k] + knz;306}307308if (flag == 0) {309*maxlnz = xlnz[neqns] - 1;310*maxsub = xnzsub[neqns];311xnzsub[neqns + 1] = xnzsub[neqns];312}313314315marker++;316mrglnk++;317rchlnk++;318nzsub++;319xnzsub++;320xlnz++;321invp++;322perm++;323adjncy++;324xadj++;325326gk_free((void **)&rchlnk, &mrglnk, &marker, LTERM);327328return flag;329330}331332333334