/***********************************************************************************
* This function is the entry point of the parallel multilevel undirected diffusion
* algorithm. It uses parallel undirected diffusion followed by adaptive k-way
* refinement. This function utilizes local coarsening.
************************************************************************************/
void PARUAMETIS(idxtype *vtxdist, idxtype *xadj, idxtype *vwgt, idxtype *adjncy, idxtype *adjwgt,
               idxtype *part, int *options, MPI_Comm comm)
{
  int wgtflag, numflag, edgecut, newoptions[5];

  newoptions[0] = 1;
  newoptions[OPTION_IPART] = options[2];
  newoptions[OPTION_FOLDF] = options[1];
  newoptions[OPTION_DBGLVL] = options[4];

  numflag = options[3];
  wgtflag = (vwgt == NULL ? 0 : 2) + (adjwgt == NULL ? 0 : 1);

  ParMETIS_RepartLDiffusion(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag,
     newoptions, &edgecut, part, &comm);

  options[0] = edgecut;

}
Beispiel #2
0
void CreateFusedElementGraph(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int *numflag)
{
  int i, j, k, l;
  int *nparts, ipart, mypart, newpart;
  int wgtflag, edgecut, npes, mype, nvtxs, nedges, counter;
  int gnfvtxs, nfvtxs, firstfvtx;
  int foptions[10];
  idxtype *fptr, *find;
  idxtype *part, *fpart, *spart, *rpart;
  idxtype *vtxdist, *xadj, *adjncy;
  idxtype *fvtxdist, *fxadj, *fadjncy;
  idxtype *map;
  realtype *fadjwgt;
  MPI_Comm *comm;

  npes = ctrl->npes;
  mype = ctrl->mype;
  nparts = &(ctrl->nparts);
  comm = &(ctrl->comm);

  vtxdist = graph->vtxdist;
  xadj = graph->xadj;
  adjncy = graph->adjncy;

  nvtxs = vtxdist[mype+1]-vtxdist[mype];
  nedges = xadj[nvtxs];

  SetUp(ctrl, graph, wspace);

  /* Communicate number of parts found */
  fvtxdist = idxmalloc(npes+1, "FusedElementGraph: fvtxdist");
  MPI_Allgather((void *)nparts, 1, MPI_INT, (void *)fvtxdist, 1, MPI_INT, *comm);

  MAKECSR(i, npes, fvtxdist);
  firstfvtx = fvtxdist[mype];
  nfvtxs = fvtxdist[mype+1]-fvtxdist[mype];
  gnfvtxs = fvtxdist[npes];

  ASSERT(ctrl, nfvtxs == *nparts);

  part = idxmalloc(nvtxs+graph->nrecv, "FusedElementGraph: part");
  idxcopy(nvtxs, graph->where, part);
  spart = wspace->indices;
  rpart = part + nvtxs;

  CommInterfaceData(ctrl, graph, part, spart, rpart);

  /* Create a part-to-vertex mapping */
/*  map = idxsmalloc(gnfvtxs, -1, "FusedElementGraph: map"); */ /* TOO GENEROUS !! */
/*  fptr = idxsmalloc(*nparts+1, 0, "FusedElementGraph: fptr"); */
/*  find = idxmalloc(nvtxs, "FusedElementGraph: find"); */
  if (gnfvtxs + nvtxs + (*nparts+1) <= wspace->maxcore) {
    map = wspace->core;
    idxset(gnfvtxs, -1, map);
    fptr = map + gnfvtxs;
  }
  else {
    map = idxsmalloc(gnfvtxs, -1, "FusedElementGraph: map");
    fptr = wspace->core;
  }
  idxset((*nparts+1), 0, fptr);
  find = fptr + (*nparts+1);

  for (i=0; i<nvtxs; i++)
     fptr[part[i]-firstfvtx]++;
  MAKECSR(i, *nparts, fptr);
  for (i=0; i<nvtxs; i++) {
     ipart = part[i] - firstfvtx;
     find[fptr[ipart]] = i;
     fptr[ipart]++;
  }

  for (ipart=*nparts; ipart>0; ipart--)
     fptr[ipart] = fptr[ipart-1];
  fptr[0] = 0;

  /* Create the fused graph for the local edges */
  fxadj = idxsmalloc(nfvtxs+1, 0, "FusedElementGraph: fxadj");
  fadjncy = idxmalloc(nedges, "FusedElementGraph: fadjncy");
  fadjwgt = realsmalloc(nedges, 0, "FusedElementGraph: fadjwgt");

  fxadj[0] = 0;
  for (ipart=0; ipart<*nparts; ipart++) {
     counter = 0;
     mypart = ipart + firstfvtx;

     for (l=fptr[ipart]; l<fptr[ipart+1]; l++) {
        i = find[l];
        for (j=xadj[i]; j<xadj[i+1]; j++) {
           k=adjncy[j];
           newpart=part[k];
           if (newpart != mypart && map[newpart] == -1) {  /* edge is not created yet */
             map[newpart] = fxadj[ipart]+counter;
             fadjncy[fxadj[ipart]+counter] = newpart;
             fadjwgt[map[newpart]] = 1;         /* alternatively = adjwgt[k] */
             counter++;
           }
           else if (newpart != mypart && map[newpart] != -1)  /* edge is already there */
             fadjwgt[map[newpart]]++;
        }
     }
     fxadj[ipart+1] = fxadj[ipart] + counter;
     for (i=fxadj[ipart]; i<fxadj[ipart+1]; i++)
        map[fadjncy[i]] = -1;
  }

  /* Now change the weights of the interface edges */
  ChangeWeights(nfvtxs, fvtxdist, fxadj, fadjncy, fadjwgt, *comm);

  /* Repartition the graph using fused elements */
  foptions[0] = 1;
  foptions[3] = 0;

/* fpart = idxmalloc(nfvtxs, "TestParMetis: fpart"); */
  fpart = map;   /* it is OK since nfvtxs < gnfvtxs */

  wgtflag = 1;
  ParMETIS_RepartLDiffusion(fvtxdist, fxadj, fadjncy, NULL, fadjwgt,
                 &wgtflag, numflag, foptions, &edgecut, fpart, comm);

  /* Project the partitioning back to the original graph */
  for (ipart=0; ipart<nfvtxs; ipart++)  {
     ASSERTP(ctrl, fpart[ipart] >= 0 && fpart[ipart] < npes, (ctrl, "%d %d %d\n", ipart , fpart[ipart], npes) );
     for (i=fptr[ipart]; i<fptr[ipart+1]; i++)
        graph->where[find[i]]=fpart[ipart];
  }

  if (gnfvtxs + nvtxs + (*nparts+1) > wspace->maxcore)
    IMfree((void**)&map, LTERM);
  IMfree((void**)&fvtxdist, &fxadj, &fadjncy, &fadjwgt, &part, LTERM);
}