⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmd.c

📁 Handles Hexahedral, Tetrahedral, Quadrilateral, and Triangle meshes. Lagrangian, Hierarchic, and Mon
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * mmd.c * * ************************************************************** * The following C function was developed from a FORTRAN subroutine * in SPARSPAK written by Eleanor Chu, Alan George, Joseph Liu * and Esmond Ng. *  * The FORTRAN-to-C transformation and modifications such as dynamic * memory allocation and deallocation were performed by Chunguang * Sun. * **************************************************************  * * Taken from SMMS, George 12/13/94 * * The meaning of invperm, and perm vectors is different from that * in genqmd_ of SparsPak * * $Id: mmd.c,v 1.5 2004/03/08 04:58:28 benkirk Exp $ */#include <metis.h>/**************************************************************************  genmmd  -- multiple minimum external degree*  purpose -- this routine implements the minimum degree*     algorithm. it makes use of the implicit representation*     of elimination graphs by quotient graphs, and the notion*     of indistinguishable nodes. It also implements the modifications*     by multiple elimination and minimum external degree.*     Caution -- the adjacency vector adjncy will be destroyed.*  Input parameters --*     neqns -- number of equations.*     (xadj, adjncy) -- the adjacency structure.*     delta  -- tolerance value for multiple elimination.*     maxint -- maximum machine representable (short) integer*               (any smaller estimate will do) for marking nodes.*  Output parameters --*     perm -- the minimum degree ordering.*     invp -- the inverse of perm.*     *ncsub -- an upper bound on the number of nonzero subscripts*               for the compressed storage scheme.*  Working parameters --*     head -- vector for head of degree lists.*     invp  -- used temporarily for degree forward link.*     perm  -- used temporarily for degree backward link.*     qsize -- vector for size of supernodes.*     list -- vector for temporary linked lists.*     marker -- a temporary marker vector.*  Subroutines used -- mmdelm, mmdint, mmdnum, mmdupd.**************************************************************************/void genmmd(int neqns, idxtype *xadj, idxtype *adjncy, idxtype *invp, idxtype *perm,     int delta, idxtype *head, idxtype *qsize, idxtype *list, idxtype *marker,     int maxint, int *ncsub){    int  ehead, i, mdeg, mdlmt, mdeg_node, nextmd, num, tag;    if (neqns <= 0)        return;    /* Adjust from C to Fortran */    xadj--; adjncy--; invp--; perm--; head--; qsize--; list--; marker--;    /* initialization for the minimum degree algorithm. */    *ncsub = 0;    mmdint(neqns, xadj, adjncy, head, invp, perm, qsize, list, marker);    /*  'num' counts the number of ordered nodes plus 1. */    num = 1;    /* eliminate all isolated nodes. */    nextmd = head[1];    while (nextmd > 0) {      mdeg_node = nextmd;      nextmd = invp[mdeg_node];      marker[mdeg_node] = maxint;      invp[mdeg_node] = -num;      num = num + 1;    }    /* search for node of the minimum degree. 'mdeg' is the current */    /* minimum degree; 'tag' is used to facilitate marking nodes.   */    if (num > neqns)       goto n1000;    tag = 1;    head[1] = 0;    mdeg = 2;    /* infinite loop here ! */    while (1) {      while (head[mdeg] <= 0)         mdeg++;      /* use value of 'delta' to set up 'mdlmt', which governs */      /* when a degree update is to be performed.              */      mdlmt = mdeg + delta;      ehead = 0;n500:      mdeg_node = head[mdeg];      while (mdeg_node <= 0) {        mdeg++;        if (mdeg > mdlmt)           goto n900;        mdeg_node = head[mdeg];      };      /*  remove 'mdeg_node' from the degree structure. */      nextmd = invp[mdeg_node];      head[mdeg] = nextmd;      if (nextmd > 0)          perm[nextmd] = -mdeg;      invp[mdeg_node] = -num;      *ncsub += mdeg + qsize[mdeg_node] - 2;      if ((num+qsize[mdeg_node]) > neqns)          goto n1000;      /*  eliminate 'mdeg_node' and perform quotient graph */      /*  transformation. reset 'tag' value if necessary.    */      tag++;      if (tag >= maxint) {        tag = 1;        for (i = 1; i <= neqns; i++)          if (marker[i] < maxint)              marker[i] = 0;      };      mmdelm(mdeg_node, xadj, adjncy, head, invp, perm, qsize, list, marker, maxint, tag);      num += qsize[mdeg_node];      list[mdeg_node] = ehead;      ehead = mdeg_node;      if (delta >= 0)         goto n500; n900:      /* update degrees of the nodes involved in the  */      /* minimum degree nodes elimination.            */      if (num > neqns)          goto n1000;      mmdupd( ehead, neqns, xadj, adjncy, delta, &mdeg, head, invp, perm, qsize, list, marker, maxint, &tag);    }; /* end of -- while ( 1 ) -- */n1000:    mmdnum( neqns, perm, invp, qsize );    /* Adjust from Fortran back to C*/    xadj++; adjncy++; invp++; perm++; head++; qsize++; list++; marker++;}/***************************************************************************           mmdelm ...... multiple minimum degree elimination* Purpose -- This routine eliminates the node mdeg_node of minimum degree*     from the adjacency structure, which is stored in the quotient*     graph format. It also transforms the quotient graph representation*     of the elimination graph.* Input parameters --*     mdeg_node -- node of minimum degree.*     maxint -- estimate of maximum representable (short) integer.*     tag    -- tag value.* Updated parameters --*     (xadj, adjncy) -- updated adjacency structure.*     (head, forward, backward) -- degree doubly linked structure.*     qsize -- size of supernode.*     marker -- marker vector.*     list -- temporary linked list of eliminated nabors.***************************************************************************/void mmdelm(int mdeg_node, idxtype *xadj, idxtype *adjncy, idxtype *head, idxtype *forward,     idxtype *backward, idxtype *qsize, idxtype *list, idxtype *marker, int maxint,int tag){    int   element, i,   istop, istart, j,          jstop, jstart, link,          nabor, node, npv, nqnbrs, nxnode,          pvnode, rlmt, rloc, rnode, xqnbr;    /* find the reachable set of 'mdeg_node' and */    /* place it in the data structure.           */    marker[mdeg_node] = tag;    istart = xadj[mdeg_node];    istop = xadj[mdeg_node+1] - 1;    /* 'element' points to the beginning of the list of  */    /* eliminated nabors of 'mdeg_node', and 'rloc' gives the */    /* storage location for the next reachable node.   */    element = 0;    rloc = istart;    rlmt = istop;    for ( i = istart; i <= istop; i++ ) {        nabor = adjncy[i];        if ( nabor == 0 ) break;        if ( marker[nabor] < tag ) {           marker[nabor] = tag;           if ( forward[nabor] < 0 )  {              list[nabor] = element;              element = nabor;           } else {              adjncy[rloc] = nabor;              rloc++;           };        }; /* end of -- if -- */    }; /* end of -- for -- */  /* merge with reachable nodes from generalized elements. */  while ( element > 0 ) {      adjncy[rlmt] = -element;      link = element;n400:      jstart = xadj[link];      jstop = xadj[link+1] - 1;      for ( j = jstart; j <= jstop; j++ ) {          node = adjncy[j];          link = -node;          if ( node < 0 )  goto n400;          if ( node == 0 ) break;          if ((marker[node]<tag)&&(forward[node]>=0)) {             marker[node] = tag;             /*use storage from eliminated nodes if necessary.*/             while ( rloc >= rlmt ) {                   link = -adjncy[rlmt];                   rloc = xadj[link];                   rlmt = xadj[link+1] - 1;             };             adjncy[rloc] = node;             rloc++;          };      }; /* end of -- for ( j = jstart; -- */      element = list[element];    };  /* end of -- while ( element > 0 ) -- */    if ( rloc <= rlmt ) adjncy[rloc] = 0;    /* for each node in the reachable set, do the following. */    link = mdeg_node;n1100:    istart = xadj[link];    istop = xadj[link+1] - 1;    for ( i = istart; i <= istop; i++ ) {        rnode = adjncy[i];        link = -rnode;        if ( rnode < 0 ) goto n1100;        if ( rnode == 0 ) return;        /* 'rnode' is in the degree list structure. */        pvnode = backward[rnode];        if (( pvnode != 0 ) && ( pvnode != (-maxint) )) {           /* then remove 'rnode' from the structure. */           nxnode = forward[rnode];           if ( nxnode > 0 ) backward[nxnode] = pvnode;           if ( pvnode > 0 ) forward[pvnode] = nxnode;           npv = -pvnode;           if ( pvnode < 0 ) head[npv] = nxnode;        };        /* purge inactive quotient nabors of 'rnode'. */        jstart = xadj[rnode];        jstop = xadj[rnode+1] - 1;        xqnbr = jstart;        for ( j = jstart; j <= jstop; j++ ) {            nabor = adjncy[j];            if ( nabor == 0 ) break;            if ( marker[nabor] < tag ) {                adjncy[xqnbr] = nabor;                xqnbr++;            };        };        /* no active nabor after the purging. */        nqnbrs = xqnbr - jstart;        if ( nqnbrs <= 0 ) {           /* merge 'rnode' with 'mdeg_node'. */           qsize[mdeg_node] += qsize[rnode];           qsize[rnode] = 0;           marker[rnode] = maxint;           forward[rnode] = -mdeg_node;           backward[rnode] = -maxint;        } else {           /* flag 'rnode' for degree update, and  */           /* add 'mdeg_node' as a nabor of 'rnode'.      */           forward[rnode] = nqnbrs + 1;           backward[rnode] = 0;           adjncy[xqnbr] = mdeg_node;           xqnbr++;           if ( xqnbr <= jstop )  adjncy[xqnbr] = 0;        };      }; /* end of -- for ( i = istart; -- */      return; }/****************************************************************************    mmdint ---- mult minimum degree initialization*    purpose -- this routine performs initialization for the*       multiple elimination version of the minimum degree algorithm.*    input parameters --*       neqns  -- number of equations.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -