/* * Copyright 1997, Regents of the University of Minnesota * * smbfactor.c * * This file performs the symbolic factorization of a matrix * * Started 8/1/97 * George * * $Id: smbfactor.c,v 1.1 1998/11/27 17:59:40 karypis Exp $ * */ #include /************************************************************************* * This function sets up data structures for fill-in computations **************************************************************************/ void ComputeFillIn(GraphType *graph, idxtype *iperm) { long i, j, k, nvtxs, maxlnz, maxsub; idxtype *xadj, *adjncy; idxtype *perm, *xlnz, *xnzsub, *nzsub; double opc; /* printf("\nSymbolic factorization... --------------------------------------------\n"); */ nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; maxsub = 4*xadj[nvtxs]; /* Relabel the vertices so that it starts from 1 */ k = xadj[nvtxs]; for (i=0; invtxs; xadj = graph->xadj; adjncy = graph->adjncy; maxsub = 4*xadj[nvtxs]; /* Relabel the vertices so that it starts from 1 */ k = xadj[nvtxs]; for (i=0; i= xadj[node+1]) { xlnz[k+1] = xlnz[k]; continue; } /* USE RCHLNK TO LINK THROUGH THE STRUCTURE OF A(*,K) BELOW DIAGONAL */ rchlnk[k] = neqns+1; for (j=xadj[node]; j lmax) { lmax = inz; xnzsub[k] = jstrt; } /* MERGE STRUCTURE OF L(*,I) IN NZSUB INTO RCHLNK. */ rchm = k; for (j = jstrt; j <= jstop; ++j) { nabor = nzsub[j]; do { m = rchm; rchm = rchlnk[m]; } while (rchm < nabor); if (rchm != nabor) { knz++; rchlnk[m] = nabor; rchlnk[nabor] = rchm; rchm = nabor; } } } /* CHECK IF SUBSCRIPTS DUPLICATE THOSE OF ANOTHER COLUMN */ if (knz == lmax) goto L1400; /* OR IF TAIL OF K-1ST COLUMN MATCHES HEAD OF KTH */ if (nzbeg > nzend) goto L1200; i = rchlnk[k]; for (jstrt = nzbeg; jstrt <= nzend; ++jstrt) { if (nzsub[jstrt] < i) continue; if (nzsub[jstrt] == i) goto L1000; else goto L1200; } goto L1200; L1000: xnzsub[k] = jstrt; for (j = jstrt; j <= nzend; ++j) { if (nzsub[j] != i) goto L1200; i = rchlnk[i]; if (i > neqns) goto L1400; } nzend = jstrt - 1; /* COPY THE STRUCTURE OF L(*,K) FROM RCHLNK TO THE DATA STRUCTURE (XNZSUB, NZSUB) */ L1200: nzbeg = nzend + 1; nzend += knz; if (nzend > *maxsub) { flag = 1; /* Out of memory */ break; } i = k; for (j=nzbeg; j<=nzend; ++j) { i = rchlnk[i]; nzsub[j] = i; marker[i] = k; } xnzsub[k] = nzbeg; marker[k] = k; /* * UPDATE THE VECTOR MRGLNK. NOTE COLUMN L(*,K) JUST FOUND * IS REQUIRED TO DETERMINE COLUMN L(*,J), WHERE * L(J,K) IS THE FIRST NONZERO IN L(*,K) BELOW DIAGONAL. */ L1400: if (knz > 1) { kxsub = xnzsub[k]; i = nzsub[kxsub]; mrglnk[k] = mrglnk[i]; mrglnk[i] = k; } xlnz[k + 1] = xlnz[k] + knz; } if (flag == 0) { *maxlnz = xlnz[neqns] - 1; *maxsub = xnzsub[neqns]; xnzsub[neqns + 1] = xnzsub[neqns]; } parent = idxsmalloc(neqns, 0, "smbfct: parent"); parent--; /* Calculate the elimination tree */ for (i=1; i<=neqns; i++) { if (xlnz[i] < xlnz[i+1]) parent[i] = nzsub[xnzsub[i]]; else parent[i] = -1; /* Indicates no parent */ } supnd = idxsmalloc(neqns+1, 0, "smbfct: supnd"); supnd--; /* super-noeuds */ nbip1 = xlnz[2] -xlnz[1] ; xnzip1 = xnzsub[1]; i=1 ; snode = 1 ; supnd[snode] = 1 ; lgind = nbip1; marker[i]= snode; nbi = nbip1; xnzi = xnzip1; marker[i]= snode; i = i+ 1; /* C.Rose ligne suivante : correction de bug 13/03/02 neqns+1 remplace neqns dans l'instruction suivante Il y avait un pb pour ssll102a avec le dernier SN qui ne comprend qu'un noeud*/ while ( i < neqns+1) { nbip1 = xlnz[i+1] -xlnz[i] ; xnzip1 = xnzsub[i]; if ( nbip1 != (nbi-1)) { snode ++;supnd[snode] = i; lgind += nbip1; } else if ( xnzip1 != (xnzi+1)) { snode ++;supnd[snode] = i; lgind += nbip1; } nbi = nbip1; xnzi = xnzip1; marker[i]= snode; i = i+ 1; } supnd[snode+1] = neqns +1; lnode =neqns; marker[neqns] = snode ; /* C.Rose ajout de la ligne precedante : correction de bug 11/03/02 */ /* printf(" nbsn : %d \n",snode); for(i=1;i<=neqns;i++) printf(" smarker %8ld %8ld\n ",i,marker[i]); for(i=1;i<=snode+1;i++) printf(" snode %8ld %8ld\n ",i,supnd[i]); */ /* fin de cr*/ minsn = neqns; maxsn = 0; k1 = 0; k2 = 0; k3 = 0; taille1 = 50; taille2 = 20; taille3 = 05; for (i = 1; i<=snode; i++) { aux = supnd[i+1]-supnd[i]; if(aux < minsn) minsn = aux; if(aux > maxsn) maxsn = aux; if(aux < taille1) k1++; if(aux < taille2) k2++; if(aux < taille3) k3++; } printf("\n "); printf(" taille du plus petit super-noeud %8ld\n ",minsn); printf(" taille du plus grand super-noeud %8ld\n ",maxsn); printf(" taille moyenne d un super-noeud %8ld\n ",lnode/snode); printf(" nb de super-noeuds de taille < %4ld : %8ld\n ",taille1,k1); printf(" nb de super-noeuds de taille < %4ld : %8ld\n ",taille2,k2); printf(" nb de super-noeuds de taille < %4ld : %8ld\n ",taille3,k3); /* for (i=1; i<=snode+1; i++) {printf(" i pt. %4ld%4d\n ",i,supnd[i]);} */ /* parent des super-noeuds */ /* principe : on a stocke dans marker pour chaque noeud son super-noeud */ /* maintenant pour chaque super-noeud on prend son dernier noeud, */ /* on cherche le parent de ce noeud, puis le supernoeud auquel */ /* appartient ce parent et on l'affecte comme parent au supernoeud */ /* quand il n'y a pas de parent on met 0 (convention C. Rose) */ parsnode = idxsmalloc(snode+1, 0, "smbfct: parsnode"); parsnode--; tbnode = idxsmalloc(neqns, 0, "smbfct: tbnode"); tbnode--; /*sauvegarde de parent nodal */ for(i = 1; i<=neqns; i++) { tbnode[i] = parent[i]; /* printf(" i %4ld parent %8ld \n", i, tbnode[i]);*/ } for(i = 1; i<=snode; i++) { nd = supnd[i+1] - 1; if(tbnode[nd] != -1) { parsnode[i] = marker[tbnode[nd]]; } else { parsnode[i] = 0; } /* printf(" noeud %4ld parent %8ld \n ",i, parsnode[i]); */ } opc = 0; for (i=1; i<=neqns; i++) xlnz[i]--; for (i=1; i<=neqns; i++) { opc += (xlnz[i+1]-xlnz[i])*(xlnz[i+1]-xlnz[i]) - (xlnz[i+1]-xlnz[i]); } printf(" Nonzeros: %ld, \tOperation Count: %6.4le \n", *maxlnz, opc); /* ecriture sur le fichier 85 */ ecri11_(invp,perm,supnd,parsnode,&neqns,&snode,&opc,maxlnz,&lgind); marker++; mrglnk++; rchlnk++; nzsub++; xnzsub++; xlnz++; invp++; perm++; adjncy++; xadj++; GKfree(&rchlnk, &mrglnk, &marker, LTERM); return flag; }