/* * Copyright 1997, Regents of the University of Minnesota * * mcoarsen.c * * This file contains code that performs graph coarsening * * Started 2/22/96 * George * * $Id: coarsen.c,v 1.2 2003/07/21 17:18:48 karypis Exp $ * */ #include /************************************************************************* * This function creates the coarser graph **************************************************************************/ void Moc_Global_CreateCoarseGraph(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int cnvtxs) { int h, i, j, k, l, ii, jj, ll, nnbrs, nvtxs, nedges, ncon; int firstvtx, lastvtx, cfirstvtx, clastvtx, otherlastvtx; int npes=ctrl->npes, mype=ctrl->mype; int cnedges, nsend, nrecv, nkeepsize, nrecvsize, nsendsize, v, u; idxtype *xadj, *ladjncy, *adjwgt, *vwgt, *vsize, *vtxdist, *home; idxtype *match, *cmap, *rcmap, *scmap; idxtype *cxadj, *cadjncy, *cadjwgt, *cvwgt, *cvsize = NULL, *chome = NULL, *cvtxdist; idxtype *rsizes, *ssizes, *rlens, *slens, *rgraph, *sgraph, *perm; idxtype *peind, *recvptr, *recvind; float *nvwgt, *cnvwgt; GraphType *cgraph; KeyValueType *scand, *rcand; int mask=(1<<13)-1, htable[8192], htableidx[8192]; nvtxs = graph->nvtxs; ncon = graph->ncon; vtxdist = graph->vtxdist; xadj = graph->xadj; vwgt = graph->vwgt; vsize = graph->vsize; nvwgt = graph->nvwgt; home = graph->home; ladjncy = graph->adjncy; adjwgt = graph->adjwgt; match = graph->match; firstvtx = vtxdist[mype]; lastvtx = vtxdist[mype+1]; cmap = graph->cmap = idxmalloc(nvtxs+graph->nrecv, "CreateCoarseGraph: cmap"); nnbrs = graph->nnbrs; peind = graph->peind; recvind = graph->recvind; recvptr = graph->recvptr; /* Use wspace->indices as the tmp space for map of the boundary * vertices that are sent and received */ scmap = wspace->indices; rcmap = cmap + nvtxs; /* Initialize the coarser graph */ cgraph = CreateGraph(); cgraph->nvtxs = cnvtxs; cgraph->ncon = ncon; cgraph->level = graph->level+1; cgraph->finer = graph; graph->coarser = cgraph; /************************************************************* * Obtain the vtxdist of the coarser graph **************************************************************/ cvtxdist = cgraph->vtxdist = idxmalloc(npes+1, "CreateCoarseGraph: cvtxdist"); cvtxdist[npes] = cnvtxs; /* Use last position in the cvtxdist as a temp buffer */ MPI_Allgather((void *)(cvtxdist+npes), 1, IDX_DATATYPE, (void *)cvtxdist, 1, IDX_DATATYPE, ctrl->comm); MAKECSR(i, npes, cvtxdist); cgraph->gnvtxs = cvtxdist[npes]; #ifdef DEBUG_CONTRACT PrintVector(ctrl, npes+1, 0, cvtxdist, "cvtxdist"); #endif /************************************************************* * Construct the cmap vector **************************************************************/ cfirstvtx = cvtxdist[mype]; clastvtx = cvtxdist[mype+1]; /* Create the cmap of what you know so far locally */ cnvtxs = 0; for (i=0; i= KEEP_BIT) { k = match[i] - KEEP_BIT; if (k>=firstvtx && k=firstvtx && knrecv, recvind, match[i])]; } } CommInterfaceData(ctrl, graph, cmap, scmap, rcmap); #ifdef DEBUG_CONTRACT PrintVector(ctrl, nvtxs, firstvtx, cmap, "Cmap"); #endif /************************************************************* * Determine how many adjcency lists you need to send/receive. **************************************************************/ /* Use wspace->pairs as the tmp space for the boundary vertices that are sent and received */ scand = wspace->pairs; rcand = graph->rcand = (KeyValueType *)GKmalloc(recvptr[nnbrs]*sizeof(KeyValueType), "CreateCoarseGraph: rcand"); nkeepsize = nsend = nrecv = 0; for (i=0; i=lastvtx) { /* This is comming from afar */ rcand[nrecv].key = k; rcand[nrecv].val = cmap[i] - cfirstvtx; /* Set it for use during the partition projection */ ASSERT(ctrl, rcand[nrecv].val>=0 && rcand[nrecv].valpv1; ssizes = wspace->pv2; idxset(nnbrs, 0, ssizes); idxset(nnbrs, 0, rsizes); rlens = graph->rlens = idxmalloc(nnbrs+1, "CreateCoarseGraph: graph->rlens"); slens = graph->slens = idxmalloc(nnbrs+1, "CreateCoarseGraph: graph->slens"); /* Take care the sending data first */ ikeyvalsort(nsend, scand); slens[0] = 0; for (k=i=0; i 0) /* Issue a receive only if you are getting something */ MPI_Irecv((void *)(rsizes+i), 1, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->rreq+i); } /* Take care the sending data next */ for (i=0; i 0) /* Issue a send only if you are sending something */ MPI_Isend((void *)(ssizes+i), 1, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i); } /* OK, now get into the loop waiting for the operations to finish */ for (i=0; i 0) MPI_Wait(ctrl->rreq+i, &ctrl->status); } for (i=0; i 0) MPI_Wait(ctrl->sreq+i, &ctrl->status); } #ifdef DEBUG_CONTRACT PrintVector(ctrl, nnbrs, 0, rsizes, "rsizes"); PrintVector(ctrl, nnbrs, 0, ssizes, "ssizes"); #endif /************************************************************* * Allocate memory for received/sent graphs and start sending * and receiving data. * rgraph and sgraph is a different data structure than CSR * to facilitate single message exchange. **************************************************************/ nrecvsize = idxsum(nnbrs, rsizes); nsendsize = idxsum(nnbrs, ssizes); if ((4+ncon)*(nrecv+nsend) + 2*(nrecvsize+nsendsize) <= wspace->nlarge) { rgraph = (idxtype *)wspace->degrees; sgraph = rgraph + (4+ncon)*nrecv+2*nrecvsize; } else { rgraph = idxmalloc((4+ncon)*nrecv+2*nrecvsize, "CreateCoarseGraph: rgraph"); sgraph = idxmalloc((4+ncon)*nsend+2*nsendsize, "CreateCoarseGraph: sgraph"); } /* Deal with the received portion first */ for (l=i=0; i 0) { MPI_Irecv((void *)(rgraph+l), (4+ncon)*(rlens[i+1]-rlens[i])+2*rsizes[i], IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->rreq+i); l += (4+ncon)*(rlens[i+1]-rlens[i])+2*rsizes[i]; } } /* Deal with the sent portion now */ for (ll=l=i=0; i 0) { /* Issue a send only if you are sending something */ for (k=slens[i]; kpartType == STATIC_PARTITION) ? -1 : vsize[ii]; sgraph[ll++] = (ctrl->partType == STATIC_PARTITION) ? -1 : home[ii]; for (jj=xadj[ii]; jjcomm, ctrl->sreq+i); l = ll; } } /* OK, now get into the loop waiting for the operations to finish */ for (i=0; i 0) MPI_Wait(ctrl->rreq+i, &ctrl->status); } for (i=0; i 0) MPI_Wait(ctrl->sreq+i, &ctrl->status); } #ifdef DEBUG_CONTRACT rprintf(ctrl, "Graphs were sent!\n"); PrintTransferedGraphs(ctrl, nnbrs, peind, slens, rlens, sgraph, rgraph); #endif /************************************************************* * Setup the mapping from indices returned by BSearch to * those that are actually stored **************************************************************/ perm = idxsmalloc(recvptr[nnbrs], -1, "CreateCoarseGraph: perm"); for (j=i=0; inrecv, recvind, rgraph[j]), j+ncon); */ perm[BSearch(graph->nrecv, recvind, rgraph[j])] = j+1; j += (4+ncon)+2*rgraph[j+1]; } /************************************************************* * Finally, create the coarser graph **************************************************************/ /* Allocate memory for the coarser graph, and fire up coarsening */ cxadj = cgraph->xadj = idxmalloc(cnvtxs+1, "CreateCoarserGraph: cxadj"); cvwgt = cgraph->vwgt = idxmalloc(cnvtxs*ncon, "CreateCoarserGraph: cvwgt"); if (ctrl->partType == ADAPTIVE_PARTITION || ctrl->partType == REFINE_PARTITION) { cvsize = cgraph->vsize = idxmalloc(cnvtxs, "CreateCoarserGraph: cvsize"); chome = cgraph->home = idxmalloc(cnvtxs, "CreateCoarserGraph: chome"); } cnvwgt = cgraph->nvwgt = fmalloc(cnvtxs*ncon, "CreateCoarserGraph: cnvwgt"); cadjncy = idxmalloc(2*(nkeepsize+nrecvsize), "CreateCoarserGraph: cadjncy"); cadjwgt = cadjncy + nkeepsize+nrecvsize; iset(8192, -1, htable); cxadj[0] = cnvtxs = cnedges = 0; for (i=0; i= KEEP_BIT) { v = firstvtx+i; u = match[i]-KEEP_BIT; if (u>=firstvtx && u u) continue; /* I have already collapsed it as (u,v) */ /* Collapse the v vertex first, which you know is local */ for (h=0; hpartType == ADAPTIVE_PARTITION || ctrl->partType == REFINE_PARTITION) { cvsize[cnvtxs] = vsize[i]; chome[cnvtxs] = home[i]; } nedges = 0; for (j=xadj[i]; j=firstvtx && upartType == ADAPTIVE_PARTITION || ctrl->partType == REFINE_PARTITION) { cvsize[cnvtxs] += vsize[u]; /* chome[cnvtxs] = home[u]; */ } for (j=xadj[u]; jnrecv, recvind, u)]; for (h=0; hpartType == ADAPTIVE_PARTITION || ctrl->partType == REFINE_PARTITION) { cvsize[cnvtxs] += rgraph[u+1+ncon]; chome[cnvtxs] = rgraph[u+2+ncon]; } for (j=0; jnedges = cnedges; /* ADD: In order to keep from having to change this too much */ /* ADD: I kept vwgt array and recomputed nvwgt for each coarser graph */ for (j=0; jnvwgt[j*ncon+h] = (float)(cvwgt[j*ncon+h])/(float)(ctrl->tvwgts[h]); cgraph->adjncy = idxmalloc(cnedges, "CreateCoarserGraph: cadjncy"); cgraph->adjwgt = idxmalloc(cnedges, "CreateCoarserGraph: cadjwgt"); idxcopy(cnedges, cadjncy, cgraph->adjncy); idxcopy(cnedges, cadjwgt, cgraph->adjwgt); free(cadjncy); free(perm); if (rgraph != (idxtype *)wspace->degrees) GKfree((void **)&rgraph, (void **)&sgraph, LTERM); }