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

📄 node_refine.c

📁 Handles Hexahedral, Tetrahedral, Quadrilateral, and Triangle meshes. Lagrangian, Hierarchic, and Mon
💻 C
字号:
/* * Copyright 1997, Regents of the University of Minnesota * * node_refine.c * * This file contains code that performs the k-way refinement * * Started 3/1/96 * George * * $Id: node_refine.c,v 1.2 2004/03/08 04:58:31 benkirk Exp $ */#include <parmetislib.h>#define PackWeightWhereInfo(a, b) (((a)<<10) + (b))#define SelectWhere(a) ((a)%1024)#define SelectWeight(a) (((a)>>10))/************************************************************************** This function computes the initial id/ed **************************************************************************/void ComputeNodePartitionParams(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace){  int i, j, nparts, nvtxs, nsep, firstvtx, lastvtx;  idxtype *xadj, *ladjncy, *adjwgt, *vtxdist, *vwgt, *lpwgts, *gpwgts, *sepind;  idxtype *where, *swhere, *rwhere;  NRInfoType *rinfo, *myrinfo;  int me, other, otherwgt;  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->KWayInitTmr));  nvtxs = graph->nvtxs;  nparts = ctrl->nparts;  vtxdist = graph->vtxdist;  xadj = graph->xadj;  ladjncy = graph->adjncy;  adjwgt = graph->adjwgt;  vwgt = graph->vwgt;  where = graph->where;  rinfo = graph->nrinfo = (NRInfoType *)GKmalloc(sizeof(NRInfoType)*nvtxs, "ComputeNodePartitionParams: rinfo");  lpwgts = graph->lpwgts = idxsmalloc(2*nparts, 0, "ComputePartitionParams: lpwgts");  gpwgts = graph->gpwgts = idxmalloc(2*nparts, "ComputePartitionParams: gpwgts");  sepind = graph->sepind = idxmalloc(nvtxs, "ComputePartitionParams: sepind");  firstvtx = vtxdist[ctrl->mype];  lastvtx = vtxdist[ctrl->mype+1];  /*------------------------------------------------------------  / Send/Receive the where information of interface vertices.  / Also use this to also encode the vwgt information of this  / vertex. This is a hack, but it should work for now!  /------------------------------------------------------------*/  swhere = wspace->indices;  rwhere = where + nvtxs;  for (i=0; i<nvtxs; i++) {    ASSERTP(ctrl, where[i] >= 0 && where[i] < 2*nparts, (ctrl, "%d\n", where[i]) );    where[i] = PackWeightWhereInfo(vwgt[i], where[i]);  }  CommInterfaceData(ctrl, graph, where, swhere, rwhere);   /*------------------------------------------------------------  / Compute now the degrees  /------------------------------------------------------------*/  for (nsep=i=0; i<nvtxs; i++) {    me = SelectWhere(where[i]);    ASSERT(ctrl, me >= 0 && me < 2*nparts);    lpwgts[me] += vwgt[i];    if (me >= nparts) {  /* If it is a separator vertex */      sepind[nsep++] = i;      lpwgts[2*nparts-1] += vwgt[i];      myrinfo = rinfo+i;      myrinfo->edegrees[0] = myrinfo->edegrees[1] = 0;      for (j=xadj[i]; j<xadj[i+1]; j++) {        other = SelectWhere(where[ladjncy[j]]);        otherwgt = SelectWeight(where[ladjncy[j]]);        if (me != other)          myrinfo->edegrees[other%2] += otherwgt;      }    }  }  graph->nsep = nsep;  /* Finally, sum-up the partition weights */  MPI_Allreduce((void *)lpwgts, (void *)gpwgts, 2*nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);  graph->mincut = gpwgts[2*nparts-1];#ifdef XX  /* Print Weight information */  if (ctrl->mype == 0) {    for (i=0; i<nparts; i+=2)       printf("[%5d %5d %5d] ", gpwgts[i], gpwgts[i+1], gpwgts[nparts+i]);     printf("\n");  }#endif  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->KWayInitTmr));}/************************************************************************** This function performs k-way refinement**************************************************************************/void KWayNodeRefine(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int npasses, float ubfraction){  int i, ii, j, k, pass, nvtxs, firstvtx, lastvtx, otherlastvtx, c, nmoves,       nlupd, nsupd, nnbrs, nchanged, nsep;  int npes = ctrl->npes, mype = ctrl->mype, nparts = ctrl->nparts;  idxtype *xadj, *ladjncy, *adjwgt, *vtxdist, *vwgt;  idxtype *where, *lpwgts, *gpwgts, *sepind;  idxtype *peind, *recvptr, *sendptr;  idxtype *update, *supdate, *rupdate, *pe_updates, *htable, *changed;  idxtype *badminpwgt, *badmaxpwgt;  KeyValueType *swchanges, *rwchanges;  int *nupds_pe;  NRInfoType *rinfo, *myrinfo;  int from, me, other, otherwgt, oldcut;  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->KWayTmr));  nvtxs = graph->nvtxs;  vtxdist = graph->vtxdist;  xadj = graph->xadj;  ladjncy = graph->adjncy;  adjwgt = graph->adjwgt;  vwgt = graph->vwgt;  firstvtx = vtxdist[mype];  lastvtx = vtxdist[mype+1];  where = graph->where;  rinfo = graph->nrinfo;  lpwgts = graph->lpwgts;  gpwgts = graph->gpwgts;  nsep = graph->nsep;  sepind = graph->sepind;  nnbrs = graph->nnbrs;  peind = graph->peind;  recvptr = graph->recvptr;  sendptr = graph->sendptr;  changed = idxmalloc(nvtxs, "KWayRefine: changed");  rwchanges = wspace->pairs;  swchanges = rwchanges + recvptr[nnbrs];  update = idxmalloc(nvtxs, "KWayRefine: update");  supdate = wspace->indices;  rupdate = supdate + recvptr[nnbrs];  nupds_pe = imalloc(npes, "KWayRefine: nupds_pe");  htable = idxsmalloc(nvtxs+graph->nrecv, 0, "KWayRefine: lhtable");  badminpwgt = wspace->pv1;  badmaxpwgt = wspace->pv2;  for (i=0; i<nparts; i+=2) {    badminpwgt[i] = badminpwgt[i+1] = (1.0/ubfraction)*(gpwgts[i]+gpwgts[i+1])/2;    badmaxpwgt[i] = badmaxpwgt[i+1] = ubfraction*(gpwgts[i]+gpwgts[i+1])/2;  }  IFSET(ctrl->dbglvl, DBG_REFINEINFO, PrintNodeBalanceInfo(ctrl, nparts, gpwgts, badminpwgt, badmaxpwgt, 1));  for (pass=0; pass<npasses; pass++) {    oldcut = graph->mincut;    for (c=0; c<2; c++) {      for (i=0; i<nparts; i+=2) {        badminpwgt[i] = badminpwgt[i+1] = (1.0/ubfraction)*(gpwgts[i]+gpwgts[i+1])/2;        badmaxpwgt[i] = badmaxpwgt[i+1] = ubfraction*(gpwgts[i]+gpwgts[i+1])/2;      }      nlupd = nsupd = nmoves = nchanged = 0;      for (ii=0; ii<nsep; ii++) {        i = sepind[ii];        from = SelectWhere(where[i]);        ASSERT(ctrl, from >= nparts);        /* Go through the loop if gain is possible for the separator vertex */        if (rinfo[i].edegrees[(c+1)%2] <= vwgt[i]) {          other = from%nparts+c;  /* It is one-sided move so we know where it goes */          if (gpwgts[other]+vwgt[i] > badmaxpwgt[other]) {            /* printf("Skip because of weight! %d\n", vwgt[i]-rinfo[i].edegrees[(c+1)%2]); */            continue;   /* We cannot move it there because it gets too heavy */          }          /* Update where, weight, and ID/ED information of the vertex you moved */          where[i] = PackWeightWhereInfo(vwgt[i], other);          /* Remove this vertex from the sepind. Note the trick for looking at the sepind[ii] again */          sepind[ii--] = sepind[--nsep];           /* myprintf(ctrl, "Vertex %d [%d %d] is moving to %d from %d [%d]\n", i+firstvtx, vwgt[i], rinfo[i].edegrees[(c+1)%2], other, from, SelectWhere(where[i])); */          lpwgts[from] -= vwgt[i];          lpwgts[2*nparts-1] -= vwgt[i];          lpwgts[other] += vwgt[i];          gpwgts[other] += vwgt[i];          /*            * Put the vertices adjacent to i that belong to either the separator or           * the (c+1)%2 partition into the update array            */          for (j=xadj[i]; j<xadj[i+1]; j++) {            k = ladjncy[j];            if (htable[k] == 0 && SelectWhere(where[k]) != other) {              htable[k] = 1;              if (k<nvtxs)                update[nlupd++] = k;              else                supdate[nsupd++] = k;            }          }          nmoves++;          if (graph->pexadj[i+1]-graph->pexadj[i] > 0)            changed[nchanged++] = i;        }      }      /* myprintf(ctrl, "nmoves: %d, nlupd: %d, nsupd: %d\n", nmoves, nlupd, nsupd); */      /* Tell everybody interested what the new where[] info is for the interface vertices */      CommChangedInterfaceData(ctrl, graph, nchanged, changed, where, swchanges, rwchanges, wspace->pv4);       IFSET(ctrl->dbglvl, DBG_RMOVEINFO, rprintf(ctrl, "\t[%d %d], [%d %d %d]\n",                 pass, c, GlobalSESum(ctrl, nmoves), GlobalSESum(ctrl, nsupd), GlobalSESum(ctrl, nlupd)));      /*-------------------------------------------------------------      / Time to communicate with processors to send the vertices      / whose degrees need to be update.      /-------------------------------------------------------------*/      /* Issue the receives first */      for (i=0; i<nnbrs; i++) {        MPI_Irecv((void *)(rupdate+sendptr[i]), sendptr[i+1]-sendptr[i], IDX_DATATYPE,                  peind[i], 1, ctrl->comm, ctrl->rreq+i);      }      /* Issue the sends next. This needs some preporcessing */      for (i=0; i<nsupd; i++) {        htable[supdate[i]] = 0;        supdate[i] = graph->imap[supdate[i]];      }      iidxsort(nsupd, supdate);      for (j=i=0; i<nnbrs; i++) {        otherlastvtx = vtxdist[peind[i]+1];        for (k=j; k<nsupd && supdate[k] < otherlastvtx; k++);         MPI_Isend((void *)(supdate+j), k-j, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i);        j = k;      }      /* OK, now get into the loop waiting for the send/recv operations to finish */      MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses);      for (i=0; i<nnbrs; i++)         MPI_Get_count(ctrl->statuses+i, IDX_DATATYPE, nupds_pe+i);      MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses);      /*-------------------------------------------------------------      / Place the received to-be updated vertices into update[]       /-------------------------------------------------------------*/      for (i=0; i<nnbrs; i++) {        pe_updates = rupdate+sendptr[i];        for (j=0; j<nupds_pe[i]; j++) {          k = pe_updates[j];          if (htable[k-firstvtx] == 0) {            htable[k-firstvtx] = 1;            update[nlupd++] = k-firstvtx;          }        }      }      /*-------------------------------------------------------------      / Update the where information of the vertices that are pulled      / into the separator.      /-------------------------------------------------------------*/      nchanged = 0;      for (ii=0; ii<nlupd; ii++) {        i = update[ii];        me = SelectWhere(where[i]);        if (me < nparts && me%2 == (c+1)%2) { /* This vertex is pulled into the separator */          lpwgts[me] -= vwgt[i];          where[i] = PackWeightWhereInfo(vwgt[i], nparts+me-(me%2));           sepind[nsep++] = i;  /* Put the vertex into the sepind array */          if (graph->pexadj[i+1]-graph->pexadj[i] > 0)            changed[nchanged++] = i;          lpwgts[SelectWhere(where[i])] += vwgt[i];          lpwgts[2*nparts-1] += vwgt[i];          /* myprintf(ctrl, "Vertex %d moves into the separator from %d to %d\n", i+firstvtx, me, SelectWhere(where[i])); */        }      }      /* Tell everybody interested what the new where[] info is for the interface vertices */      CommChangedInterfaceData(ctrl, graph, nchanged, changed, where, swchanges, rwchanges, wspace->pv4);       /*-------------------------------------------------------------      / Update the rinfo of the vertices in the update[] array      /-------------------------------------------------------------*/      for (ii=0; ii<nlupd; ii++) {        i = update[ii];        ASSERT(ctrl, htable[i] == 1);        htable[i] = 0;        me = SelectWhere(where[i]);        if (me >= nparts) {  /* If it is a separator vertex */          /* myprintf(ctrl, "Updating %d %d\n", i+firstvtx, me); */          myrinfo = rinfo+i;          myrinfo->edegrees[0] = myrinfo->edegrees[1] = 0;          for (j=xadj[i]; j<xadj[i+1]; j++) {            other = SelectWhere(where[ladjncy[j]]);            otherwgt = SelectWeight(where[ladjncy[j]]);            if (me != other)              myrinfo->edegrees[other%2] += otherwgt;          }        }      }      /* Finally, sum-up the partition weights */      MPI_Allreduce((void *)lpwgts, (void *)gpwgts, 2*nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm);      graph->mincut = gpwgts[2*nparts-1];      IFSET(ctrl->dbglvl, DBG_REFINEINFO, PrintNodeBalanceInfo(ctrl, nparts, gpwgts, badminpwgt, badmaxpwgt, 0));    }    if (graph->mincut == oldcut)      break;  }  /* Go and clear-up the where array */  for (i=0; i<nvtxs+graph->nrecv; i++)    where[i] = SelectWhere(where[i]);  GKfree((void **)&update, (void **)&nupds_pe, (void **)&htable, (void **)&changed, LTERM);  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->KWayTmr));}/************************************************************************** This function prints balance information for the parallel k-section * refinement algorithm**************************************************************************/void PrintNodeBalanceInfo(CtrlType *ctrl, int nparts, idxtype *gpwgts, idxtype *badminpwgt, idxtype *badmaxpwgt, int title){  int i;  if (ctrl->mype == 0) {    if (title)      printf("K-way sep-refinement: TotalSep: %d, ", gpwgts[2*nparts-1]);    else      printf("\tTotalSep: %d, ", gpwgts[2*nparts-1]);    for (i=0; i<nparts; i+=2)       printf(" [%5d %5d %5d %5d %5d]", gpwgts[i], gpwgts[i+1], gpwgts[nparts+i], badminpwgt[i], badmaxpwgt[i]);     printf("\n");  }  MPI_Barrier(ctrl->comm);}

⌨️ 快捷键说明

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