Date: 2013-07-02T14:44:44+00:00

Actual source code: genqmd.c
petsc-3.4.2 2013-07-02

      2: /* genqmd.f -- translated by f2c (version 19931217).*/

      4: #include <petscsys.h>
      5: #include <../src/mat/order/order.h>

      7: /******************************************************************/
      8: /***********    GENQMD ..... QUOT MIN DEGREE ORDERING    **********/
      9: /******************************************************************/
     10: /*    PURPOSE - THIS ROUTINE IMPLEMENTS THE MINIMUM DEGREE        */
     11: /*       ALGORITHM.  IT MAKES USE OF THE IMPLICIT REPRESENT-      */
     12: /*       ATION OF THE ELIMINATION GRAPHS BY QUOTIENT GRAPHS,      */
     13: /*       AND THE NOTION OF INDISTINGUISHABLE NODES.               */
     14: /*       CAUTION - THE ADJACENCY VECTOR ADJNCY WILL BE            */
     15: /*       DESTROYED.                                               */
     16: /*                                                                */
     17: /*    INPUT PARAMETERS -                                          */
     18: /*       NEQNS - NUMBER OF EQUATIONS.                             */
     19: /*       (XADJ, ADJNCY) - THE ADJACENCY STRUCTURE.                */
     20: /*                                                                */
     21: /*    OUTPUT PARAMETERS -                                         */
     22: /*       PERM - THE MINIMUM DEGREE ORDERING.                      */
     23: /*       INVP - THE INVERSE OF PERM.                              */
     24: /*                                                                */
     25: /*    WORKING PARAMETERS -                                        */
     26: /*       DEG - THE DEGREE VECTOR. DEG(I) IS NEGATIVE MEANS        */
     27: /*              NODE I HAS BEEN NUMBERED.                         */
     28: /*       MARKER - A MARKER VECTOR, WHERE MARKER(I) IS             */
     29: /*              NEGATIVE MEANS NODE I HAS BEEN MERGED WITH        */
     30: /*              ANOTHER NODE AND THUS CAN BE IGNORED.             */
     31: /*       RCHSET - VECTOR USED FOR THE REACHABLE SET.              */
     32: /*       NBRHD - VECTOR USED FOR THE NEIGHBORHOOD SET.            */
     33: /*       QSIZE - VECTOR USED TO STORE THE SIZE OF                 */
     34: /*              INDISTINGUISHABLE SUPERNODES.                     */
     35: /*       QLINK - VECTOR TO STORE INDISTINGUISHABLE NODES,         */
     36: /*              I, QLINK(I), QLINK(QLINK(I)) ... ARE THE          */
     37: /*              MEMBERS OF THE SUPERNODE REPRESENTED BY I.        */
     38: /*                                                                */
     39: /*    PROGRAM SUBROUTINES -                                       */
     40: /*       QMDRCH, QMDQT, QMDUPD.                                   */
     41: /*                                                                */
     42: /******************************************************************/
     43: /*                                                                */
     44: /*                                                                */
     47: PetscErrorCode SPARSEPACKgenqmd(const PetscInt *neqns,const PetscInt *xadj,const PetscInt *adjncy,
     48:                                 PetscInt *perm, PetscInt *invp, PetscInt *deg, PetscInt *marker,
     49:                                 PetscInt *rchset, PetscInt *nbrhd, PetscInt *qsize, PetscInt *qlink, PetscInt *nofsub)
     50: {
     51:   /* System generated locals */
     52:   PetscInt i__1;

     54:   /* Local variables */
     55:   PetscInt ndeg, irch, node, nump1, j, inode;
     56:   PetscInt ip, np, mindeg, search;
     57:   PetscInt nhdsze, nxnode, rchsze, thresh, num;

     59: /*       INITIALIZE DEGREE VECTOR AND OTHER WORKING VARIABLES.   */

     62:   /* Parameter adjustments */
     63:   --qlink;
     64:   --qsize;
     65:   --nbrhd;
     66:   --rchset;
     67:   --marker;
     68:   --deg;
     69:   --invp;
     70:   --perm;
     71:   --adjncy;
     72:   --xadj;

     74:   mindeg  = *neqns;
     75:   *nofsub = 0;
     76:   i__1    = *neqns;
     77:   for (node = 1; node <= i__1; ++node) {
     78:     perm[node]   = node;
     79:     invp[node]   = node;
     80:     marker[node] = 0;
     81:     qsize[node]  = 1;
     82:     qlink[node]  = 0;
     83:     ndeg         = xadj[node + 1] - xadj[node];
     84:     deg[node]    = ndeg;
     85:     if (ndeg < mindeg) mindeg = ndeg;
     86:   }
     87:   num = 0;
     88: /*       PERFORM THRESHOLD SEARCH TO GET A NODE OF MIN DEGREE.   */
     89: /*       VARIABLE SEARCH POINTS TO WHERE SEARCH SHOULD START.    */
     90: L200:
     91:   search = 1;
     92:   thresh = mindeg;
     93:   mindeg = *neqns;
     94: L300:
     95:   nump1 = num + 1;
     96:   if (nump1 > search) search = nump1;
     97:   i__1 = *neqns;
     98:   for (j = search; j <= i__1; ++j) {
     99:     node = perm[j];
    100:     if (marker[node] < 0) goto L400;
    101:     ndeg = deg[node];
    102:     if (ndeg <= thresh) goto L500;
    103:     if (ndeg < mindeg) mindeg = ndeg;
    104: L400:
    105:     ;
    106:   }
    107:   goto L200;
    108: /*          NODE HAS MINIMUM DEGREE. FIND ITS REACHABLE SETS BY    */
    109: /*          CALLING QMDRCH.                                        */
    110: L500:
    111:   search       = j;
    112:   *nofsub     += deg[node];
    113:   marker[node] = 1;
    114:   SPARSEPACKqmdrch(&node, &xadj[1], &adjncy[1], &deg[1], &marker[1], &rchsze, &
    115:                    rchset[1], &nhdsze, &nbrhd[1]);
    116: /*          ELIMINATE ALL NODES INDISTINGUISHABLE FROM NODE.       */
    117: /*          THEY ARE GIVEN BY NODE, QLINK(NODE), ....              */
    118:   nxnode = node;
    119: L600:
    120:   ++num;
    121:   np           = invp[nxnode];
    122:   ip           = perm[num];
    123:   perm[np]     = ip;
    124:   invp[ip]     = np;
    125:   perm[num]    = nxnode;
    126:   invp[nxnode] = num;
    127:   deg[nxnode]  = -1;
    128:   nxnode       = qlink[nxnode];
    129:   if (nxnode > 0) goto L600;
    130:   if (rchsze <= 0) goto L800;

    132: /*             UPDATE THE DEGREES OF THE NODES IN THE REACHABLE     */
    133: /*             SET AND IDENTIFY INDISTINGUISHABLE NODES.            */
    134:   SPARSEPACKqmdupd(&xadj[1], &adjncy[1], &rchsze, &rchset[1], &deg[1], &qsize[1], &
    135:                    qlink[1], &marker[1], &rchset[rchsze + 1], &nbrhd[nhdsze + 1]);

    137: /*             RESET MARKER VALUE OF NODES IN REACH SET.            */
    138: /*             UPDATE THRESHOLD VALUE FOR CYCLIC SEARCH.            */
    139: /*             ALSO CALL QMDQT TO FORM NEW QUOTIENT GRAPH.          */
    140:   marker[node] = 0;
    141:   i__1         = rchsze;
    142:   for (irch = 1; irch <= i__1; ++irch) {
    143:     inode = rchset[irch];
    144:     if (marker[inode] < 0) goto L700;

    146:     marker[inode] = 0;
    147:     ndeg          = deg[inode];
    148:     if (ndeg < mindeg) mindeg = ndeg;
    149:     if (ndeg > thresh) goto L700;
    150:     mindeg = thresh;
    151:     thresh = ndeg;
    152:     search = invp[inode];
    153: L700:
    154:     ;
    155:   }
    156:   if (nhdsze > 0) {
    157:     SPARSEPACKqmdqt(&node, &xadj[1], &adjncy[1], &marker[1], &rchsze, &rchset[1], &
    158:                     nbrhd[1]);
    159:   }
    160: L800:
    161:   if (num < *neqns) goto L300;
    162:   return(0);
    163: }