/* Sorts in increasing order with primary key val1 and secondary key val2. The arrays val1 and val2 are not rearranged; rather the index array sorted is rearranged based on values in val1 and val2. */ void Zoltan_quicksort_pointer_inc_int_int ( int *sorted, /* index array that is rearranged; should be initialized so that sorted[i] == i. */ int* val1, /* array of primary key values. */ int *val2, /* array of secondary key values. */ int start, /* first array position to be considered for sorting. */ int end /* last array position to be considered for sorting. */ ) { int equal, larger; if (start < end) { quickpart_pointer_inc_int_int (sorted,val1,val2,start,end,&equal,&larger); Zoltan_quicksort_pointer_inc_int_int (sorted, val1, val2, start, equal-1); Zoltan_quicksort_pointer_inc_int_int (sorted, val1, val2, larger, end); } }
int Zoltan_PHG_Vertex_Visit_Order( ZZ *zz, HGraph *hg, PHGPartParams *hgp, int *order) { int i, j, edge; int *ldegree=NULL, *gdegree=NULL; /* local/global degree */ int *lpins=NULL, *gpins=NULL; /* local/global sum of pins */ char *yo= "Zoltan_PHG_Vertex_Visit_Order"; /* Start with linear order. */ for (i=0; i<hg->nVtx; i++) order[i] = i; /* Permute order array according to chosen strategy. */ switch (hgp->visit_order){ case 0: /* random node visit order (recommended) */ /* Synchronize so each proc in column visits in same order */ Zoltan_Srand_Sync(Zoltan_Rand(NULL), &(hg->comm->RNGState_col), hg->comm->col_comm); Zoltan_Rand_Perm_Int (order, hg->nVtx, &(hg->comm->RNGState_col)); break; case 1: /* linear (natural) vertex visit order */ break; case 2: { /* increasing vertex weight */ float *tmpvwgt; if (hg->VtxWeightDim == 1) tmpvwgt = hg->vwgt; else { /* Sort based on first component of multidimensional weight */ tmpvwgt = (float *) ZOLTAN_MALLOC(hg->nVtx * sizeof(float)); for (i = 0; i < hg->nVtx; i++) tmpvwgt[i] = hg->vwgt[i*hg->VtxWeightDim]; } Zoltan_quicksort_pointer_inc_float (order, tmpvwgt, 0, hg->nVtx-1); if (tmpvwgt != hg->vwgt) ZOLTAN_FREE(&tmpvwgt); break; } case 3: /* increasing vertex degree */ /* intentionally fall through into next case */ case 4: /* increasing vertex degree, weighted by # pins */ /* allocate 4 arrays of size hg->nVtx with a single malloc */ if (!(ldegree = (int *) ZOLTAN_MALLOC (4*sizeof(int) * hg->nVtx))){ ZOLTAN_PRINT_WARN(zz->Proc, yo, "Out of memory"); ZOLTAN_FREE (&ldegree); return ZOLTAN_MEMERR; } /* first local data, then global data */ lpins = ldegree + hg->nVtx; gdegree = lpins + hg->nVtx; gpins = gdegree + hg->nVtx; /* loop over vertices */ for (i=0; i<hg->nVtx; i++){ ldegree[i] = hg->vindex[i+1] - hg->vindex[i]; /* local degree */ lpins[i] = 0; /* loop over edges, sum up #pins */ for (j= hg->vindex[i]; j < hg->vindex[i+1]; j++) { edge = hg->vedge[j]; lpins[i] += hg->hindex[edge+1] - hg->hindex[edge]; } } /* sum up local degrees in each column to get global degrees */ /* also sum up #pins in same communication */ MPI_Allreduce(ldegree, gdegree, 2*hg->nVtx, MPI_INT, MPI_SUM, hg->comm->col_comm); /* sort by global values. same on every processor. */ if (hgp->visit_order == 3) Zoltan_quicksort_pointer_inc_int_int (order, gdegree, gpins, 0, hg->nVtx-1); else /* hgp->visit_order == 4 */ Zoltan_quicksort_pointer_inc_int_int (order, gpins, gdegree, 0, hg->nVtx-1); ZOLTAN_FREE (&ldegree); break; /* add more cases here */ } return ZOLTAN_OK; }
void Zoltan_PHG_Plot( int proc, /* Processor calling the routine */ int nvtx, /* Number of vertices */ int nparts, /* Number of partitions; ignored if part == NULL */ int *vindex, /* Starting index in vedges of hyperedges for each vertex */ int *vedge, /* Hyperedges for each vertex */ int *part, /* Partition to which vertices are assigned; if NULL, partition information is not plotted. */ char *str /* String included as comment in output files. */ ) { /* Routine that produces gnuplot output of hypergraph in form of matrix. * One column for each vertex. * One row for each hyperedge. * Entries in matrix entry a[j,i] if vertex i is in hyperedge j. * If part == NULL, a single file is produced with all information. * (Currently, this capability is serial only.) * If part != NULL, a separate file is produced for each partition. * (Currently, this capability works in parallel for k >= p.) */ static int cnt = 0; char filename[32]; int i, j, v; FILE *fp = NULL; int prev_part = -1; int *idx = NULL; int *vtx = NULL; idx = (int *) ZOLTAN_MALLOC(2 * nvtx * sizeof(int)); vtx = idx + nvtx; for (i = 0; i < nvtx; i++) vtx[i] = idx[i] = i; if (part != NULL) { /* sort vertices by partition */ Zoltan_quicksort_pointer_inc_int_int(idx, part, vtx, 0, nvtx-1); } else { /* write all results to one file */ sprintf(filename, "hgplot%02d", cnt); fp = fopen(filename, "w"); fprintf(fp, "#%s\n", str); } for (i = 0; i < nvtx; i++) { v = idx[i]; if (part != NULL) { if (part[v] != prev_part) { /* open new file for this partition's data */ if (fp != NULL) fclose(fp); sprintf(filename, "hgplot%02d.%02d", cnt, part[v]); fp = fopen(filename, "w"); fprintf(fp, "#%s\n", str); prev_part = part[v]; } } for (j = vindex[v]; j < vindex[v+1]; j++) fprintf(fp, "%d %d\n", v, -vedge[j]); } fclose(fp); ZOLTAN_FREE(&idx); if (proc == 0) { sprintf(filename, "hgplot%02d.gnuload", cnt); fp = fopen(filename, "w"); fprintf(fp, "set data style points\n"); fprintf(fp, "set pointsize 5\n"); fprintf(fp, "set nokey\n"); fprintf(fp, "set title \"%s\"\n", str); fprintf(fp, "set xlabel \"vertices\"\n"); fprintf(fp, "set ylabel \"-hyperedges\"\n"); fprintf(fp, "plot "); if (part != NULL) { for (i = 0; i < nparts; i++) { fprintf(fp, "\"hgplot%02d.%02d\"", cnt, i); if (i != nparts-1) fprintf(fp, ", "); else fprintf(fp, "\n"); } } else { fprintf(fp, "\"hgplot%02d\"\n", cnt); } fclose(fp); } cnt++; }