/* ------------------------------------- return an IV object filled with the weights of the component's boundaries created -- 96oct21, cca ------------------------------------- */ IV * GPart_bndWeightsIV ( GPart *gpart ) { Graph *graph ; int icomp, ii, ncomp, nvtx, v, vsize, vwght, w ; int *bnd, *compids, *cweights, *mark, *vadj, *vwghts ; IV *bndIV ; /* --------------- check the input --------------- */ if ( gpart == NULL || (graph = gpart->g) == NULL ) { fprintf(stderr, "\n fatal error in GPart_bndWeightsIV(%p)" "\n bad input\n", gpart) ; exit(-1) ; } nvtx = gpart->nvtx ; ncomp = gpart->ncomp ; compids = IV_entries(&gpart->compidsIV) ; cweights = IV_entries(&gpart->cweightsIV) ; vwghts = graph->vwghts ; bndIV = IV_new() ; IV_init(bndIV, 1 + ncomp, NULL) ; IV_fill(bndIV, 0) ; bnd = IV_entries(bndIV) ; mark = IVinit(ncomp+1, -1) ; for ( v = 0 ; v < nvtx ; v++ ) { if ( compids[v] == 0 ) { vwght = (vwghts == NULL) ? 1 : vwghts[v] ; Graph_adjAndSize(graph, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( (icomp = compids[w]) != 0 && mark[icomp] != v ) { mark[icomp] = v ; bnd[icomp] += vwght ; } } } } IVfree(mark) ; return(bndIV) ; }
/* ------------------------------------------------------ return 1 if the partition has a valid vertex separator 0 otherwise created -- 95oct18, cca ------------------------------------------------------ */ int GPart_validVtxSep ( GPart *gpart ) { Graph *g ; int icomp, ii, nvtx, v, vsize, w ; int *compids, *vadj ; /* --------------- check the input --------------- */ if ( gpart == NULL ) { fprintf(stderr, "\n fatal error in GPart_validVtxSep(%p)" "\n bad input\n", gpart) ; exit(-1) ; } nvtx = gpart->nvtx ; g = gpart->g ; compids = IV_entries(&gpart->compidsIV) ; /* --------------------------------------------------- loop over the vertices check that each non-separator vertex is adjacent to vertices only in its component or in the separator --------------------------------------------------- */ for ( v = 0 ; v < nvtx ; v++ ) { if ( (icomp = compids[v]) != 0 ) { Graph_adjAndSize(g, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { if ( (w = vadj[ii]) < nvtx ) { if ( compids[w] != 0 && compids[w] != icomp ) { fprintf(stderr, "\n vertex %d, component %d, is adjacent to vertex %d, component %d", v, icomp, w, compids[w]) ; return(0) ; } } } } } return(1) ; }
/* ---------------------------------------------------- return 1 if vertex is adjacent to only one domain and fill *pdomid with the domain's id return 0 otherwise created -- 95oct19, cca ------------------------------------------------- */ int GPart_vtxIsAdjToOneDomain ( GPart *gpart, int v, int *pdomid ) { Graph *g ; int domid, ii, nvtx, u, Vi, vsize ; int *compids, *vadj ; /* --------------- check the input --------------- */ if ( gpart == NULL || v < 0 || (nvtx = gpart->nvtx) <= v || (g = gpart->g) == NULL || pdomid == NULL ) { fprintf(stderr, "\n fatal error in GPart_vtxIsAdjToOneDomain(%p,%d,%p)" "\n bad input\n", gpart, v, pdomid) ; exit(-1) ; } compids = IV_entries(&gpart->compidsIV) ; /* ------------------------------------------ fill domids[] with ids of adjacent domains ------------------------------------------ */ Graph_adjAndSize(g, v, &vsize, &vadj) ; domid = *pdomid = -1 ; for ( ii = 0 ; ii < vsize ; ii++ ) { if ( (u = vadj[ii]) < nvtx && (Vi = compids[u]) > 0 ) { if ( domid == -1 ) { *pdomid = domid = Vi ; } else if ( Vi != domid ) { return(0) ; } } } if ( domid == -1 ) { return(0) ; } else { return(1) ; } }
/* ---------------------------------------------------- set the component weights from the compids[] vector created -- 95oct05, cca modified -- 95nov29, cca ---------------------------------------------------- */ void GPart_setCweights ( GPart *gpart ) { Graph *g ; int ierr, ii, last, ncomp, now, nvtx, u, usize, v, w ; int *compids, *cweights, *list, *uadj, *vwghts ; /* -------------- check the data -------------- */ if ( gpart == NULL ) { fprintf(stderr, "\n fatal error in GPart_setCweights(%p)" "\n bad input\n", gpart) ; exit(-1) ; } if ( (nvtx = gpart->nvtx) <= 0 || (g = gpart->g) == NULL ) { fprintf(stderr, "\n fatal error in GPart_setCweights(%p)" "\n bad Gpart object\n", gpart) ; exit(-1) ; } /* ---------------------------------------------------------- set the component id of all non-multisector vertices to -1 ---------------------------------------------------------- */ compids = IV_entries(&gpart->compidsIV) ; for ( v = 0 ; v < nvtx ; v++ ) { if ( compids[v] != 0 ) { compids[v] = -1 ; } } /* ---------------------------------------------------------- compute the number of components and set the component ids ---------------------------------------------------------- */ list = IVinit(nvtx, -1) ; ncomp = 0 ; for ( v = 0 ; v < nvtx ; v++ ) { if ( compids[v] == -1 ) { compids[v] = ++ncomp ; now = last = 0 ; list[now] = v ; while ( now <= last ) { u = list[now++] ; Graph_adjAndSize(g, u, &usize, &uadj) ; for ( ii = 0 ; ii < usize ; ii++ ) { if ( (w = uadj[ii]) < nvtx && compids[w] == -1 ) { compids[w] = ncomp ; list[++last] = w ; } } } } } /* ---------------------------- set the number of components ---------------------------- */ gpart->ncomp = ncomp ; /* ------------------------- set the component weights ------------------------- */ IV_setSize(&gpart->cweightsIV, 1 + ncomp) ; cweights = IV_entries(&gpart->cweightsIV) ; IVzero(1 + ncomp, cweights) ; if ( (vwghts = gpart->g->vwghts) != NULL ) { for ( v = 0 ; v < nvtx ; v++ ) { cweights[compids[v]] += vwghts[v] ; } } else { for ( v = 0 ; v < nvtx ; v++ ) { cweights[compids[v]]++ ; } } /* ------------------------ free the working storage ------------------------ */ IVfree(list) ; return ; }
/*--------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) /* ------------------------------------------------------ (1) read in an ETree object. (2) read in an Graph object. (3) find the optimal domain/schur complement partition for a semi-implicit factorization created -- 96oct03, cca ------------------------------------------------------ */ { char *inETreeFileName, *inGraphFileName, *outIVfileName ; double alpha, nA21, nfent1, nfops1, nL11, nL22, nPhi, nV, t1, t2 ; Graph *graph ; int ii, inside, J, K, msglvl, nfind1, nfront, nJ, nleaves1, nnode1, nvtx, rc, sizeJ, totalgain, vsize, v, w ; int *adjJ, *compids, *nodwghts, *vadj, *vtxToFront, *vwghts ; IV *compidsIV ; IVL *symbfacIVL ; ETree *etree ; FILE *msgFile ; Tree *tree ; if ( argc != 7 ) { fprintf(stdout, "\n\n usage : %s msglvl msgFile inETreeFile inGraphFile alpha" "\n outIVfile " "\n msglvl -- message level" "\n msgFile -- message file" "\n inETreeFile -- input file, must be *.etreef or *.etreeb" "\n inGraphFile -- input file, must be *.graphf or *.graphb" "\n alpha -- weight parameter" "\n alpha = 0 --> minimize storage" "\n alpha = 1 --> minimize solve ops" "\n outIVfile -- output file for oldToNew vector," "\n must be *.ivf or *.ivb" "\n", argv[0]) ; return(0) ; } msglvl = atoi(argv[1]) ; if ( strcmp(argv[2], "stdout") == 0 ) { msgFile = stdout ; } else if ( (msgFile = fopen(argv[2], "a")) == NULL ) { fprintf(stderr, "\n fatal error in %s" "\n unable to open file %s\n", argv[0], argv[2]) ; return(-1) ; } inETreeFileName = argv[3] ; inGraphFileName = argv[4] ; alpha = atof(argv[5]) ; outIVfileName = argv[6] ; fprintf(msgFile, "\n %s " "\n msglvl -- %d" "\n msgFile -- %s" "\n inETreeFile -- %s" "\n inGraphFile -- %s" "\n alpha -- %f" "\n outIVfile -- %s" "\n", argv[0], msglvl, argv[2], inETreeFileName, inGraphFileName, alpha, outIVfileName) ; fflush(msgFile) ; /* ------------------------ read in the ETree object ------------------------ */ if ( strcmp(inETreeFileName, "none") == 0 ) { fprintf(msgFile, "\n no file to read from") ; spoolesFatal(); } etree = ETree_new() ; MARKTIME(t1) ; rc = ETree_readFromFile(etree, inETreeFileName) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s", t2 - t1, inETreeFileName) ; if ( rc != 1 ) { fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)", rc, etree, inETreeFileName) ; spoolesFatal(); } ETree_leftJustify(etree) ; fprintf(msgFile, "\n\n after reading ETree object from file %s", inETreeFileName) ; if ( msglvl > 2 ) { ETree_writeForHumanEye(etree, msgFile) ; } else { ETree_writeStats(etree, msgFile) ; } fflush(msgFile) ; nfront = ETree_nfront(etree) ; tree = ETree_tree(etree) ; nodwghts = ETree_nodwghts(etree) ; vtxToFront = ETree_vtxToFront(etree) ; /* ------------------------ read in the Graph object ------------------------ */ if ( strcmp(inGraphFileName, "none") == 0 ) { fprintf(msgFile, "\n no file to read from") ; spoolesFatal(); } graph = Graph_new() ; MARKTIME(t1) ; rc = Graph_readFromFile(graph, inGraphFileName) ; nvtx = graph->nvtx ; vwghts = graph->vwghts ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s", t2 - t1, inGraphFileName) ; if ( rc != 1 ) { fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)", rc, graph, inGraphFileName) ; spoolesFatal(); } fprintf(msgFile, "\n\n after reading Graph object from file %s", inGraphFileName) ; if ( msglvl > 2 ) { Graph_writeForHumanEye(graph, msgFile) ; } else { Graph_writeStats(graph, msgFile) ; } fflush(msgFile) ; /* ---------------------- compute the statistics ---------------------- */ nnode1 = etree->tree->n ; nfind1 = ETree_nFactorIndices(etree) ; nfent1 = ETree_nFactorEntries(etree, SPOOLES_SYMMETRIC) ; nfops1 = ETree_nFactorOps(etree, SPOOLES_REAL, SPOOLES_SYMMETRIC) ; nleaves1 = Tree_nleaves(etree->tree) ; fprintf(stdout, "\n root front %d has %d vertices", etree->tree->root, etree->nodwghtsIV->vec[etree->tree->root]) ; /* --------------------------------- create the symbolic factorization --------------------------------- */ symbfacIVL = SymbFac_initFromGraph(etree, graph) ; if ( msglvl > 2 ) { IVL_writeForHumanEye(symbfacIVL, msgFile) ; } else { IVL_writeStats(symbfacIVL, msgFile) ; } fflush(msgFile) ; /* -------------------------- find the optimal partition -------------------------- */ compidsIV = ETree_optPart(etree, graph, symbfacIVL, alpha, &totalgain, msglvl, msgFile) ; if ( msglvl > 2 ) { IV_writeForHumanEye(compidsIV, msgFile) ; } else { IV_writeStats(compidsIV, msgFile) ; } fflush(msgFile) ; compids = IV_entries(compidsIV) ; /* ------------------------------------------------------ compute the number of vertices in the schur complement ------------------------------------------------------ */ for ( J = 0, nPhi = nV = 0. ; J < nfront ; J++ ) { if ( compids[J] == 0 ) { nPhi += nodwghts[J] ; } nV += nodwghts[J] ; } /* -------------------------------------------- compute the number of entries in L11 and L22 -------------------------------------------- */ nL11 = nL22 = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { nJ = nodwghts[J] ; if ( msglvl > 3 ) { fprintf(msgFile, "\n\n front %d, nJ = %d", J, nJ) ; } IVL_listAndSize(symbfacIVL, J, &sizeJ, &adjJ) ; for ( ii = 0, inside = 0 ; ii < sizeJ ; ii++ ) { w = adjJ[ii] ; K = vtxToFront[w] ; if ( msglvl > 3 ) { fprintf(msgFile, "\n w = %d, K = %d", w, K) ; } if ( K > J && compids[K] == compids[J] ) { inside += (vwghts == NULL) ? 1 : vwghts[w] ; if ( msglvl > 3 ) { fprintf(msgFile, ", inside") ; } } } if ( compids[J] != 0 ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n inside = %d, adding %d to L11", inside, nJ*nJ + 2*nJ*inside) ; } nL11 += (nJ*(nJ+1))/2 + nJ*inside ; } else { if ( msglvl > 3 ) { fprintf(msgFile, "\n inside = %d, adding %d to L22", inside, (nJ*(nJ+1))/2 + nJ*inside) ; } nL22 += (nJ*(nJ+1))/2 + nJ*inside ; } } if ( msglvl > 0 ) { fprintf(msgFile, "\n |L| = %.0f, |L11| = %.0f, |L22| = %.0f", nfent1, nL11, nL22) ; } /* ------------------------------------ compute the number of entries in A21 ------------------------------------ */ nA21 = 0 ; if ( vwghts != NULL ) { for ( v = 0 ; v < nvtx ; v++ ) { J = vtxToFront[v] ; if ( compids[J] != 0 ) { Graph_adjAndSize(graph, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; K = vtxToFront[w] ; if ( compids[K] == 0 ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n A21 : v = %d, w = %d", v, w) ; } nA21 += vwghts[v] * vwghts[w] ; } } } } } else { for ( v = 0 ; v < nvtx ; v++ ) { J = vtxToFront[v] ; if ( compids[J] != 0 ) { Graph_adjAndSize(graph, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; K = vtxToFront[w] ; if ( compids[K] == 0 ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n A21 : v = %d, w = %d", v, w) ; } nA21++ ; } } } } } if ( msglvl > 0 ) { fprintf(msgFile, "\n |L| = %.0f, |L11| = %.0f, |L22| = %.0f, |A21| = %.0f", nfent1, nL11, nL22, nA21) ; fprintf(msgFile, "\n storage: explicit = %.0f, semi-implicit = %.0f, ratio = %.3f" "\n opcount: explicit = %.0f, semi-implicit = %.0f, ratio = %.3f", nfent1, nL11 + nA21 + nL22, nfent1/(nL11 + nA21 + nL22), 2*nfent1, 4*nL11 + 2*nA21 + 2*nL22, 2*nfent1/(4*nL11 + 2*nA21 + 2*nL22)) ; fprintf(msgFile, "\n ratios %8.3f %8.3f %8.3f", nPhi/nV, nfent1/(nL11 + nA21 + nL22), 2*nfent1/(4*nL11 + 2*nA21 + 2*nL22)) ; } /* ---------------- free the objects ---------------- */ ETree_free(etree) ; Graph_free(graph) ; IVL_free(symbfacIVL) ; fprintf(msgFile, "\n") ; fclose(msgFile) ; return(1) ; }
/* --------------------------------- write out a graph to a METIS file created -- 95oct18, cca --------------------------------- */ int Graph_writeToMetisFile ( Graph *g, FILE *fp ) { int ii, nedge, nvtx, v, vsize, w ; int *vewghts, *vadj ; /* --------------- check the input --------------- */ if ( g == NULL || fp == NULL ) { fprintf(stderr, "\n fatal error in Graph_writeToMetisFile(%p,%p)" "\n bad input\n", g, fp) ; spoolesFatal(); } nvtx = g->nvtx ; nedge = (g->nedges - nvtx)/2 ; switch ( g->type ) { case 0 : fprintf(fp, " %d %d ", nvtx, nedge) ; for ( v = 0 ; v < nvtx ; v++ ) { fprintf(fp, "\n ") ; Graph_adjAndSize(g, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w != v && w < nvtx ) { fprintf(fp, " %d", w + 1) ; } } } break ; case 1 : fprintf(fp, " %d %d 10", nvtx, nedge) ; for ( v = 0 ; v < nvtx ; v++ ) { fprintf(fp, "\n %d", g->vwghts[v]) ; Graph_adjAndSize(g, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w != v && w < nvtx ) { fprintf(fp, " %d", w + 1) ; } } } break ; case 2 : fprintf(fp, " %d %d 1", nvtx, nedge) ; for ( v = 0 ; v < nvtx ; v++ ) { fprintf(fp, "\n") ; Graph_adjAndEweights(g, v, &vsize, &vadj, &vewghts) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w != v && w < nvtx ) { fprintf(fp, " %d %d", w + 1, vewghts[ii]) ; } } } break ; case 3 : fprintf(fp, " %d %d 11", nvtx, nedge) ; for ( v = 0 ; v < nvtx ; v++ ) { fprintf(fp, "\n %d", g->vwghts[v]) ; Graph_adjAndEweights(g, v, &vsize, &vadj, &vewghts) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w != v && w < nvtx ) { fprintf(fp, " %d %d", w + 1, vewghts[ii]) ; } } } break ; } return(1) ; }
/* -------------------------------------------------------------- identify the wide separator return -- IV object that holds the nodes in the wide separator created -- 96oct21, cca -------------------------------------------------------------- */ IV * GPart_identifyWideSep ( GPart *gpart, int nlevel1, int nlevel2 ) { FILE *msgFile ; Graph *g ; int count, first, ierr, ii, ilevel, last, msglvl, nfirst, now, nsecond, nsep, nvtx, v, vsize, w ; int *compids, *list, *mark, *vadj ; IV *sepIV ; /* --------------- check the input --------------- */ if ( gpart == NULL || (g = gpart->g) == NULL || nlevel1 < 0 || nlevel2 < 0 ) { fprintf(stderr, "\n fatal error in GPart_identifyWideSep(%p,%d,%d)" "\n bad input\n", gpart, nlevel1, nlevel2) ; exit(-1) ; } g = gpart->g ; compids = IV_entries(&gpart->compidsIV) ; nvtx = g->nvtx ; mark = IVinit(nvtx, -1) ; list = IVinit(nvtx, -1) ; msglvl = gpart->msglvl ; msgFile = gpart->msgFile ; /* -------------------------------------- load the separator nodes into the list -------------------------------------- */ nsep = 0 ; for ( v = 0 ; v < nvtx ; v++ ) { if ( compids[v] == 0 ) { list[nsep++] = v ; mark[v] = 0 ; } } count = nsep ; if ( msglvl > 1 ) { fprintf(msgFile, "\n GPart_identifyWideSep : %d separator nodes loaded", count) ; fflush(msgFile) ; } if ( msglvl > 2 ) { IVfp80(msgFile, nsep, list, 80, &ierr) ; fflush(msgFile) ; } /* ---------------------------------------------- loop over the number of levels out that form the wide separator towards the first component ---------------------------------------------- */ if ( nlevel1 >= 1 ) { first = count ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n level = %d, first = %d", 1, first) ; fflush(msgFile) ; } for ( now = 0 ; now < nsep ; now++ ) { v = list[now] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n %d : ", v) ; IVfp80(msgFile, vsize, vadj, 80, &ierr) ; fflush(msgFile) ; } for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < nvtx && mark[w] == -1 && compids[w] == 1 ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n adding %d to list", w) ; fflush(msgFile) ; } list[count++] = w ; mark[w] = 1 ; } } } now = first ; for ( ilevel = 2 ; ilevel <= nlevel1 ; ilevel++ ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n\n level = %d, first = %d", ilevel, first); fflush(msgFile) ; } last = count - 1 ; while ( now <= last ) { v = list[now++] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n %d : ", v) ; IVfp80(msgFile, vsize, vadj, 80, &ierr) ; fflush(msgFile) ; } for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < nvtx && mark[w] == -1 && compids[w] == 1 ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n adding %d to list", w) ; fflush(msgFile) ; } mark[w] = 1 ; list[count++] = w ; } } } } } nfirst = count - nsep ; if ( msglvl > 2 ) { fprintf(msgFile, "\n %d nodes added from the first component", nfirst) ; fflush(msgFile) ; } if ( msglvl > 3 ) { IVfp80(msgFile, nfirst, &list[nsep], 80, &ierr) ; fflush(msgFile) ; } /* ---------------------------------------------- loop over the number of levels out that form the wide separator towards the second component ---------------------------------------------- */ if ( nlevel2 >= 1 ) { first = count ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n level = %d, first = %d", 1, first) ; fflush(msgFile) ; } for ( now = 0 ; now < nsep ; now++ ) { v = list[now] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n %d : ", v) ; IVfp80(msgFile, vsize, vadj, 80, &ierr) ; fflush(msgFile) ; } for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < nvtx && mark[w] == -1 && compids[w] == 2 ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n adding %d to list", w) ; fflush(msgFile) ; } list[count++] = w ; mark[w] = 2 ; } } } now = first ; for ( ilevel = 2 ; ilevel <= nlevel2 ; ilevel++ ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n\n level = %d, first = %d", ilevel, first); fflush(msgFile) ; } last = count - 1 ; while ( now <= last ) { v = list[now++] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n %d : ", v) ; IVfp80(msgFile, vsize, vadj, 80, &ierr) ; fflush(msgFile) ; } for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < nvtx && mark[w] == -1 && compids[w] == 2 ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n adding %d to list", w) ; fflush(msgFile) ; } mark[w] = 2 ; list[count++] = w ; } } } } } nsecond = count - nsep - nfirst ; if ( msglvl > 2 ) { fprintf(msgFile, "\n %d nodes added from the second component", nsecond) ; fflush(msgFile) ; } if ( msglvl > 3 ) { IVfp80(msgFile, nsecond, &list[nsep + nfirst], 80, &ierr) ; fflush(msgFile) ; } IVqsortUp(count, list) ; /* -------------------- create the IV object -------------------- */ sepIV = IV_new() ; IV_init(sepIV, count, NULL) ; IVcopy(count, IV_entries(sepIV), list) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n separator has %d nodes", IV_size(sepIV)) ; fflush(msgFile) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n sepIV") ; IV_writeForHumanEye(sepIV, msgFile) ; fflush(msgFile) ; } /* ------------------------ free the working storage ------------------------ */ IVfree(mark) ; IVfree(list) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n return from GPart_identifyWideSep") ; fflush(msgFile) ; } return(sepIV) ; }
/* --------------------------------------------------------- evaluate the (deltaS, deltaB and deltaW) of a domain flip created -- 950ct11, cca --------------------------------------------------------- */ void BKL_evalgain ( BKL *bkl, int dom, int *pdeltaS, int *pdeltaB, int *pdeltaW ) { int ii, newc, oldc, seg, size ; int *adj, *colors, *regwghts ; int stats[3] ; /* --------------- check the input --------------- */ if ( bkl == NULL || dom < 0 || dom >= bkl->ndom || pdeltaS == NULL || pdeltaB == NULL || pdeltaW == NULL ) { fprintf(stderr, "\n fatal error in BKL_evalGain(%p,%d,%p,%p,%p)" "\n bad input\n", bkl, dom, pdeltaS, pdeltaB, pdeltaW) ; exit(-1) ; } colors = bkl->colors ; regwghts = bkl->regwghts ; stats[0] = stats[1] = stats[2] = 0 ; /* --------------- flip the domain --------------- */ if ( colors[dom] == 1 ) { #if MYDEBUG > 0 fprintf(stdout, "\n domain %d, old color = 1, new color = 2", dom) ; fflush(stdout) ; #endif stats[1] -= regwghts[dom] ; stats[2] += regwghts[dom] ; colors[dom] = 2 ; } else { #if MYDEBUG > 0 fprintf(stdout, "\n domain %d, old color = 2, new color = 1", dom) ; fflush(stdout) ; #endif stats[2] -= regwghts[dom] ; stats[1] += regwghts[dom] ; colors[dom] = 1 ; } /* ------------------------------- loop over the adjacent segments ------------------------------- */ Graph_adjAndSize(bkl->bpg->graph, dom, &size, &adj) ; for ( ii = 0 ; ii < size ; ii++ ) { seg = adj[ii] ; oldc = colors[seg] ; newc = BKL_segColor(bkl, seg) ; #if MYDEBUG > 0 fprintf(stdout, "\n segment %d, weight = %d, old color = %d, new color = %d", seg, regwghts[seg], oldc, newc) ; fflush(stdout) ; #endif if ( oldc != newc ) { stats[oldc] -= regwghts[seg] ; stats[newc] += regwghts[seg] ; #if MYDEBUG > 0 fprintf(stdout, "\n stats = < %d %d %d >", stats[0], stats[1], stats[2]) ; fflush(stdout) ; #endif } } #if MYDEBUG > 0 fprintf(stdout, "\n stats = < %d %d %d > ", stats[0], stats[1], stats[2]) ; fflush(stdout) ; #endif /* ------------------------ set the output variables ------------------------ */ *pdeltaS = stats[0] ; *pdeltaB = stats[1] ; *pdeltaW = stats[2] ; /* -------------------- flip the domain back -------------------- */ if ( colors[dom] == 1 ) { colors[dom] = 2 ; } else { colors[dom] = 1 ; } /* --------------------------------- increment the number of gainevals --------------------------------- */ bkl->ngaineval++ ; return ; }
/* -------------------------------------------------------------------- fill *pndom with ndom, the number of domains. fill *pnseg with nseg, the number of segments. domains are numbered in [0, ndom), segments in [ndom,ndom+nseg). return -- an IV object that contains the map from vertices to segments created -- 99feb29, cca -------------------------------------------------------------------- */ IV * GPart_domSegMap ( GPart *gpart, int *pndom, int *pnseg ) { FILE *msgFile ; Graph *g ; int adjdom, count, d, first, ierr, ii, jj1, jj2, last, ndom, msglvl, nextphi, nPhi, nPsi, nV, phi, phi0, phi1, phi2, phi3, psi, sigma, size, size0, size1, size2, v, vsize, w ; int *adj, *adj0, *adj1, *adj2, *compids, *dmark, *dsmap, *head, *link, *list, *offsets, *PhiToPsi, *PhiToV, *PsiToSigma, *vadj, *VtoPhi ; IV *dsmapIV ; IVL *PhiByPhi, *PhiByPowD, *PsiByPowD ; /* -------------------- set the initial time -------------------- */ icputimes = 0 ; MARKTIME(cputimes[icputimes]) ; /* --------------- check the input --------------- */ if ( gpart == NULL || (g = gpart->g) == NULL || pndom == NULL || pnseg == NULL ) { fprintf(stderr, "\n fatal error in GPart_domSegMap(%p,%p,%p)" "\n bad input\n", gpart, pndom, pnseg) ; exit(-1) ; } compids = IV_entries(&gpart->compidsIV) ; msglvl = gpart->msglvl ; msgFile = gpart->msgFile ; /* ------------------------ create the map IV object ------------------------ */ nV = g->nvtx ; dsmapIV = IV_new() ; IV_init(dsmapIV, nV, NULL) ; dsmap = IV_entries(dsmapIV) ; /* ---------------------------------- check compids[] and get the number of domains and interface vertices ---------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; ndom = nPhi = 0 ; for ( v = 0 ; v < nV ; v++ ) { if ( (d = compids[v]) < 0 ) { fprintf(stderr, "\n fatal error in GPart_domSegMap(%p,%p,%p)" "\n compids[%d] = %d\n", gpart, pndom, pnseg, v, compids[v]) ; exit(-1) ; } else if ( d == 0 ) { nPhi++ ; } else if ( ndom < d ) { ndom = d ; } } *pndom = ndom ; if ( msglvl > 1 ) { fprintf(msgFile, "\n\n Inside GPart_domSegMap") ; fprintf(msgFile, "\n %d domains, %d Phi vertices", ndom, nPhi) ; } if ( ndom == 1 ) { IVfill(nV, dsmap, 0) ; *pndom = 1 ; *pnseg = 0 ; return(dsmapIV) ; } /* -------------------------------- get the maps PhiToV : [0,nPhi) |---> [0,nV) VtoPhi : [0,nV) |---> [0,nPhi) -------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PhiToV = IVinit(nPhi, -1) ; VtoPhi = IVinit(nV, -1) ; for ( v = 0, phi = 0 ; v < nV ; v++ ) { if ( (d = compids[v]) == 0 ) { PhiToV[phi] = v ; VtoPhi[v] = phi++ ; } } if ( phi != nPhi ) { fprintf(stderr, "\n fatal error in GPart_domSegMap(%p,%p,%p)" "\n phi = %d != %d = nPhi\n", gpart, pndom, pnseg, phi, nPhi) ; exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiToV(%d) :", nPhi) ; IVfp80(msgFile, nPhi, PhiToV, 15, &ierr) ; fflush(msgFile) ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n VtoPhi(%d) :", nV) ; IVfp80(msgFile, nV, VtoPhi, 15, &ierr) ; fflush(msgFile) ; } /* --------------------------------------------------- create an IVL object, PhiByPowD, to hold lists from the interface vertices to their adjacent domains --------------------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; dmark = IVinit(ndom+1, -1) ; if ( nPhi >= ndom ) { list = IVinit(nPhi, -1) ; } else { list = IVinit(ndom, -1) ; } PhiByPowD = IVL_new() ; IVL_init1(PhiByPowD, IVL_CHUNKED, nPhi) ; for ( phi = 0 ; phi < nPhi ; phi++ ) { v = PhiToV[phi] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; /* if ( phi == 0 ) { int ierr ; fprintf(msgFile, "\n adj(%d,%d) = ", v, phi) ; IVfp80(msgFile, vsize, vadj, 15, &ierr) ; fflush(msgFile) ; } */ count = 0 ; for ( ii = 0 ; ii < vsize ; ii++ ) { if ( (w = vadj[ii]) < nV && (d = compids[w]) > 0 && dmark[d] != phi ) { dmark[d] = phi ; list[count++] = d ; } } if ( count > 0 ) { IVqsortUp(count, list) ; IVL_setList(PhiByPowD, phi, count, list) ; } } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiByPowD : interface x adjacent domains") ; IVL_writeForHumanEye(PhiByPowD, msgFile) ; fflush(msgFile) ; } /* ------------------------------------------------------- create an IVL object, PhiByPhi to hold lists from the interface vertices to interface vertices. (s,t) are in the list if (s,t) is an edge in the graph and s and t do not share an adjacent domain ------------------------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PhiByPhi = IVL_new() ; IVL_init1(PhiByPhi, IVL_CHUNKED, nPhi) ; offsets = IVinit(nPhi, 0) ; head = IVinit(nPhi, -1) ; link = IVinit(nPhi, -1) ; for ( phi1 = 0 ; phi1 < nPhi ; phi1++ ) { count = 0 ; if ( msglvl > 2 ) { v = PhiToV[phi1] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; fprintf(msgFile, "\n checking out phi = %d, v = %d", phi1, v) ; fprintf(msgFile, "\n adj(%d) : ", v) ; IVfp80(msgFile, vsize, vadj, 10, &ierr) ; } /* ------------------------------------------------------------- get (phi1, phi0) edges that were previously put into the list ------------------------------------------------------------- */ if ( msglvl > 3 ) { if ( head[phi1] == -1 ) { fprintf(msgFile, "\n no previous edges") ; } else { fprintf(msgFile, "\n previous edges :") ; } } for ( phi0 = head[phi1] ; phi0 != -1 ; phi0 = nextphi ) { if ( msglvl > 3 ) { fprintf(msgFile, " %d", phi0) ; } nextphi = link[phi0] ; list[count++] = phi0 ; IVL_listAndSize(PhiByPhi, phi0, &size0, &adj0) ; if ( (ii = ++offsets[phi0]) < size0 ) { /* ---------------------------- link phi0 into the next list ---------------------------- */ phi2 = adj0[ii] ; link[phi0] = head[phi2] ; head[phi2] = phi0 ; } } /* -------------------------- get new edges (phi1, phi2) -------------------------- */ IVL_listAndSize(PhiByPowD, phi1, &size1, &adj1) ; v = PhiToV[phi1] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { if ( (w = vadj[ii]) < nV && compids[w] == 0 && (phi2 = VtoPhi[w]) > phi1 ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n checking out phi2 = %d", phi2) ; } /* -------------------------------------------------- see if phi1 and phi2 have a common adjacent domain -------------------------------------------------- */ IVL_listAndSize(PhiByPowD, phi2, &size2, &adj2) ; adjdom = 0 ; jj1 = jj2 = 0 ; while ( jj1 < size1 && jj2 < size2 ) { if ( adj1[jj1] < adj2[jj2] ) { jj1++ ; } else if ( adj1[jj1] > adj2[jj2] ) { jj2++ ; } else { if ( msglvl > 3 ) { fprintf(msgFile, ", common adj domain %d", adj1[jj1]) ; } adjdom = 1 ; break ; } } if ( adjdom == 0 ) { if ( msglvl > 3 ) { fprintf(msgFile, ", no adjacent domain") ; } list[count++] = phi2 ; } } } if ( count > 0 ) { /* --------------------- set the list for phi1 --------------------- */ IVqsortUp(count, list) ; IVL_setList(PhiByPhi, phi1, count, list) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n edge list for %d :", phi1) ; IVfp80(msgFile, count, list, 15, &ierr) ; } for ( ii = 0, phi2 = -1 ; ii < count ; ii++ ) { if ( list[ii] > phi1 ) { offsets[phi1] = ii ; phi2 = list[ii] ; break ; } } if ( phi2 != -1 ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n linking %d into list for %d", phi1, phi2) ; } link[phi1] = head[phi2] ; head[phi2] = phi1 ; } /* phi2 = list[0] ; link[phi1] = head[phi2] ; head[phi2] = phi1 ; */ } } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiByPhi : interface x interface") ; IVL_writeForHumanEye(PhiByPhi, msgFile) ; fflush(msgFile) ; } /* -------------------- get the PhiToPsi map -------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PhiToPsi = IVinit(nPhi, -1) ; nPsi = 0 ; for ( phi = 0 ; phi < nPhi ; phi++ ) { if ( PhiToPsi[phi] == -1 ) { /* --------------------------- phi not yet mapped to a psi --------------------------- */ first = last = 0 ; list[0] = phi ; PhiToPsi[phi] = nPsi ; while ( first <= last ) { phi2 = list[first++] ; IVL_listAndSize(PhiByPhi, phi2, &size, &adj) ; for ( ii = 0 ; ii < size ; ii++ ) { phi3 = adj[ii] ; if ( PhiToPsi[phi3] == -1 ) { PhiToPsi[phi3] = nPsi ; list[++last] = phi3 ; } } } nPsi++ ; } } if ( msglvl > 1 ) { fprintf(msgFile, "\n nPsi = %d", nPsi) ; fflush(msgFile) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiToPsi(%d) :", nPhi) ; IVfp80(msgFile, nPhi, PhiToPsi, 15, &ierr) ; fflush(msgFile) ; } /* --------------------------------- create an IVL object, Psi --> 2^D --------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; IVfill(nPsi, head, -1) ; IVfill(nPhi, link, -1) ; for ( phi = 0 ; phi < nPhi ; phi++ ) { psi = PhiToPsi[phi] ; link[phi] = head[psi] ; head[psi] = phi ; } PsiByPowD = IVL_new() ; IVL_init1(PsiByPowD, IVL_CHUNKED, nPsi) ; IVfill(ndom+1, dmark, -1) ; for ( psi = 0 ; psi < nPsi ; psi++ ) { count = 0 ; for ( phi = head[psi] ; phi != -1 ; phi = link[phi] ) { v = PhiToV[phi] ; Graph_adjAndSize(g, v, &size, &adj) ; for ( ii = 0 ; ii < size ; ii++ ) { if ( (w = adj[ii]) < nV && (d = compids[w]) > 0 && dmark[d] != psi ) { dmark[d] = psi ; list[count++] = d ; } } } if ( count > 0 ) { IVqsortUp(count, list) ; IVL_setList(PsiByPowD, psi, count, list) ; } } if ( msglvl > 2 ) { fprintf(msgFile, "\n PsiByPowD(%d) :", nPhi) ; IVL_writeForHumanEye(PsiByPowD, msgFile) ; fflush(msgFile) ; } icputimes++ ; MARKTIME(cputimes[icputimes]) ; /* ------------------------------------- now get the map Psi |---> Sigma that is the equivalence map over PhiByPowD ------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PsiToSigma = IVL_equivMap1(PsiByPowD) ; *pnseg = 1 + IVmax(nPsi, PsiToSigma, &ii) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n nSigma = %d", *pnseg) ; fprintf(msgFile, "\n PsiToSigma(%d) :", nPhi) ; IVfp80(msgFile, nPsi, PsiToSigma, 15, &ierr) ; fflush(msgFile) ; } /* -------------------------------------------------------------- now fill the map from the vertices to the domains and segments -------------------------------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; for ( v = 0 ; v < nV ; v++ ) { if ( (d = compids[v]) > 0 ) { dsmap[v] = d - 1 ; } else { phi = VtoPhi[v] ; psi = PhiToPsi[phi] ; sigma = PsiToSigma[psi] ; dsmap[v] = ndom + sigma ; } } /* ------------------------ free the working storage ------------------------ */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; IVL_free(PhiByPhi) ; IVL_free(PhiByPowD) ; IVL_free(PsiByPowD) ; IVfree(PhiToV) ; IVfree(VtoPhi) ; IVfree(dmark) ; IVfree(list) ; IVfree(PhiToPsi) ; IVfree(head) ; IVfree(link) ; IVfree(offsets) ; IVfree(PsiToSigma) ; icputimes++ ; MARKTIME(cputimes[icputimes]) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n domain/segment map timings split") ; fprintf(msgFile, "\n %9.5f : create the DSmap object" "\n %9.5f : get numbers of domain and interface vertices" "\n %9.5f : generate PhiToV and VtoPhi" "\n %9.5f : generate PhiByPowD" "\n %9.5f : generate PhiByPhi" "\n %9.5f : generate PhiToPsi" "\n %9.5f : generate PsiByPowD" "\n %9.5f : generate PsiToSigma" "\n %9.5f : generate dsmap" "\n %9.5f : free working storage" "\n %9.5f : total time", cputimes[1] - cputimes[0], cputimes[2] - cputimes[1], cputimes[3] - cputimes[2], cputimes[4] - cputimes[3], cputimes[5] - cputimes[4], cputimes[6] - cputimes[5], cputimes[7] - cputimes[6], cputimes[8] - cputimes[7], cputimes[9] - cputimes[8], cputimes[10] - cputimes[9], cputimes[11] - cputimes[0]) ; } return(dsmapIV) ; }
/* ----------------------------------------------------------- purpose -- return the Y by Y graph where (y1,y2) is an edge if there exists a x in X such that (x,y1) and (x,y2) are edges in the bipartite graph. created -- 95dec07, cca ----------------------------------------------------------- */ Graph * BPG_makeGraphYbyY ( BPG *bpg ) { Graph *graph, *gYbyY ; int count, ii, jj, nX, nY, x, xsize, y, ysize, z ; int *list, *mark, *xadj, *yadj ; /* --------------- check the input --------------- */ if ( bpg == NULL ) { fprintf(stdout, "\n fatal error in BPG_makeGraphXbyX(%p)" "\n bad input\n", bpg) ; spoolesFatal(); } /* ---------------------- check for quick return ---------------------- */ if ( (graph = bpg->graph) == NULL || (nY = bpg->nY) <= 0 ) { return(NULL) ; } nX = bpg->nX ; /* -------------------- initialize the graph -------------------- */ gYbyY = Graph_new() ; Graph_init1(gYbyY, graph->type, nY, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ; /* -------------- fill the graph -------------- */ mark = IVinit(nY, -1) ; list = IVinit(nY, -1) ; for ( y = 0 ; y < nY ; y++ ) { Graph_adjAndSize(graph, nX + y, &ysize, &yadj) ; mark[y] = y ; for ( ii = 0, count = 0 ; ii < ysize ; ii++ ) { x = yadj[ii] ; Graph_adjAndSize(graph, x, &xsize, &xadj) ; for ( jj = 0 ; jj < xsize ; jj++ ) { z = xadj[jj] ; if ( mark[z] != y ) { mark[z] = y ; list[count++] = z ; } } } if ( count > 0 ) { IVqsortUp(count, list) ; IVL_setList(gYbyY->adjIVL, nX + y, count, list) ; } } IVfree(list) ; IVfree(mark) ; /* --------------------------------------- set vertex weight vector if appropriate --------------------------------------- */ if ( graph->type % 2 == 1 ) { IVcopy(nY, gYbyY->vwghts, graph->vwghts + nX) ; } return(gYbyY) ; }
/* ------------------------------------------------------- make the map from wide separator vertices Y to components {0, 1, 2, 3}. YCmap[y] == 0 --> y is not adjacent to either component YCmap[y] == 1 --> y is adjacent to only component 1 YCmap[y] == 2 --> y is adjacent to only component 2 YCmap[y] == 3 --> y is adjacent to components 1 and 2 created -- 96jun09, cca ------------------------------------------------------- */ IV * GPart_makeYCmap ( GPart *gpart, IV *YVmapIV ) { Graph *g ; int ii, nvtx, nY, v, vsize, w, y ; int *compids, *vadj, *VYmap, *YCmap, *YVmap ; IV *YCmapIV ; /* --------------- check the input --------------- */ if ( gpart == NULL || (g = gpart->g) == NULL || (nvtx = gpart->nvtx) <= 0 || YVmapIV == NULL || (nY = IV_size(YVmapIV)) <= 0 || (YVmap = IV_entries(YVmapIV)) == NULL ) { fprintf(stderr, "\n fatal error in GPart_makeYCmap(%p,%p)" "\n bad input\n", gpart, YVmapIV) ; if ( YVmapIV != NULL ) { fprintf(stderr, "\n YVmapIV") ; IV_writeForHumanEye(YVmapIV, stderr) ; } exit(-1) ; } compids = IV_entries(&gpart->compidsIV) ; /* -------------------------------- generate the inverse V --> Y map -------------------------------- */ VYmap = IVinit(nvtx, -1) ; for ( y = 0 ; y < nY ; y++ ) { v = YVmap[y] ; VYmap[v] = y ; } /* ------------------------------------ initialize the Y --> C map IV object ------------------------------------ */ YCmapIV = IV_new(); IV_init(YCmapIV, nY, NULL) ; YCmap = IV_entries(YCmapIV) ; /* --------------- fill the fields --------------- */ for ( y = 0 ; y < nY ; y++ ) { YCmap[y] = 0 ; v = YVmap[y] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < nvtx && VYmap[w] == -1 ) { /* -------------------------------- w is not in the wide separator Y -------------------------------- */ if ( compids[w] == 1 ) { /* --------------------------------------- v is adjacent to component 1 setminus Y --------------------------------------- */ if ( YCmap[y] == 2 ) { /* ------------------------------------ v is already adjacent to component 2 so it is adjacent to both components ------------------------------------ */ YCmap[y] = 3 ; break ; } else { /* ---------------------------------- set map value but keep on checking ---------------------------------- */ YCmap[y] = 1 ; } } else if ( compids[w] == 2 ) { /* --------------------------------------- v is adjacent to component 2 setminus Y --------------------------------------- */ if ( YCmap[y] == 1 ) { /* ------------------------------------ v is already adjacent to component 1 so it is adjacent to both components ------------------------------------ */ YCmap[y] = 3 ; break ; } else { /* ---------------------------------- set map value but keep on checking ---------------------------------- */ YCmap[y] = 2 ; } } } } } /* ------------------------ free the working storage ------------------------ */ IVfree(VYmap) ; return(YCmapIV) ; }
/*--------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) /* ---------------------------------------- get statistics for a semi-implicit solve created -- 97dec11, cca ---------------------------------------- */ { char *inGraphFileName, *inETreeFileName, *inMapFileName ; double nA21, nL, nL11, nL22, nPhi, nV, t1, t2 ; ETree *etree ; int ii, inside, J, K, msglvl, nfront, nJ, nvtx, rc, sizeJ, v, vsize, w ; int *adjJ, *frontmap, *map, *nodwghts, *vadj, *vtxToFront, *vwghts ; IV *mapIV ; IVL *symbfacIVL ; Graph *graph ; FILE *msgFile ; Tree *tree ; if ( argc != 6 ) { fprintf(stdout, "\n\n usage : %s msglvl msgFile GraphFile ETreeFile mapFile " "\n msglvl -- message level" "\n msgFile -- message file" "\n GraphFile -- input graph file, must be *.graphf or *.graphb" "\n ETreeFile -- input ETree file, must be *.etreef or *.etreeb" "\n mapFile -- input map IV file, must be *.ivf or *.ivb" "\n", argv[0]) ; return(0) ; } msglvl = atoi(argv[1]) ; if ( strcmp(argv[2], "stdout") == 0 ) { msgFile = stdout ; } else if ( (msgFile = fopen(argv[2], "a")) == NULL ) { fprintf(stderr, "\n fatal error in %s" "\n unable to open file %s\n", argv[0], argv[2]) ; return(-1) ; } inGraphFileName = argv[3] ; inETreeFileName = argv[4] ; inMapFileName = argv[5] ; fprintf(msgFile, "\n %s " "\n msglvl -- %d" "\n msgFile -- %s" "\n GraphFile -- %s" "\n ETreeFile -- %s" "\n mapFile -- %s" "\n", argv[0], msglvl, argv[2], inGraphFileName, inETreeFileName, inMapFileName) ; fflush(msgFile) ; /* ------------------------ read in the Graph object ------------------------ */ graph = Graph_new() ; if ( strcmp(inGraphFileName, "none") == 0 ) { fprintf(msgFile, "\n no file to read from") ; exit(0) ; } MARKTIME(t1) ; rc = Graph_readFromFile(graph, inGraphFileName) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %9.5f : read in graph from file %s", t2 - t1, inGraphFileName) ; nvtx = graph->nvtx ; vwghts = graph->vwghts ; if ( rc != 1 ) { fprintf(msgFile, "\n return value %d from Graph_readFromFile(%p,%s)", rc, graph, inGraphFileName) ; exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n after reading Graph object from file %s", inGraphFileName) ; Graph_writeForHumanEye(graph, msgFile) ; fflush(msgFile) ; } /* ------------------------ read in the ETree object ------------------------ */ etree = ETree_new() ; if ( strcmp(inETreeFileName, "none") == 0 ) { fprintf(msgFile, "\n no file to read from") ; exit(0) ; } MARKTIME(t1) ; rc = ETree_readFromFile(etree, inETreeFileName) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %9.5f : read in etree from file %s", t2 - t1, inETreeFileName) ; nfront = ETree_nfront(etree) ; tree = ETree_tree(etree) ; vtxToFront = ETree_vtxToFront(etree) ; nodwghts = ETree_nodwghts(etree) ; nL = ETree_nFactorEntries(etree, 2) ; if ( rc != 1 ) { fprintf(msgFile, "\n return value %d from ETree_readFromFile(%p,%s)", rc, etree, inETreeFileName) ; exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n after reading ETree object from file %s", inETreeFileName) ; ETree_writeForHumanEye(etree, msgFile) ; fflush(msgFile) ; } /* ------------------------- read in the map IV object ------------------------- */ mapIV = IV_new() ; if ( strcmp(inMapFileName, "none") == 0 ) { fprintf(msgFile, "\n no file to read from") ; exit(0) ; } MARKTIME(t1) ; rc = IV_readFromFile(mapIV, inMapFileName) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %9.5f : read in mapIV from file %s", t2 - t1, inMapFileName) ; map = IV_entries(mapIV) ; if ( rc != 1 ) { fprintf(msgFile, "\n return value %d from IV_readFromFile(%p,%s)", rc, mapIV, inMapFileName) ; exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n after reading IV object from file %s", inMapFileName) ; IV_writeForHumanEye(mapIV, msgFile) ; fflush(msgFile) ; } nV = nPhi = 0 ; if ( vwghts == NULL ) { for ( v = 0 ; v < nvtx ; v++ ) { nV++ ; if ( map[v] == 0 ) { nPhi++ ; } } } else { for ( v = 0 ; v < nvtx ; v++ ) { nV += vwghts[v] ; if ( map[v] == 0 ) { nPhi += vwghts[v] ; } } } fprintf(msgFile, "\n nPhi = %.0f, nV = %.0f", nPhi, nV) ; /* ------------------------- get the frontmap[] vector ------------------------- */ frontmap = IVinit(nfront, -1) ; for ( v = 0 ; v < nvtx ; v++ ) { J = vtxToFront[v] ; if ( frontmap[J] == -1 ) { frontmap[J] = map[v] ; } else if ( frontmap[J] != map[v] ) { fprintf(msgFile, "\n\n error, frontmap[%d] = %d, map[%d] = %d", J, frontmap[J], v, map[v]) ; } } /* ---------------------------------- compute the symbolic factorization ---------------------------------- */ symbfacIVL = SymbFac_initFromGraph(etree, graph) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n symbolic factorization") ; IVL_writeForHumanEye(symbfacIVL, msgFile) ; fflush(msgFile) ; } /* -------------------------------------------- compute the number of entries in L11 and L22 -------------------------------------------- */ nL11 = nL22 = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { nJ = nodwghts[J] ; if ( msglvl > 3 ) { fprintf(msgFile, "\n\n front %d, nJ = %d", J, nJ) ; } IVL_listAndSize(symbfacIVL, J, &sizeJ, &adjJ) ; for ( ii = 0, inside = 0 ; ii < sizeJ ; ii++ ) { w = adjJ[ii] ; K = vtxToFront[w] ; if ( msglvl > 3 ) { fprintf(msgFile, "\n w = %d, K = %d", w, K) ; } if ( K > J && frontmap[K] == frontmap[J] ) { inside += (vwghts == NULL) ? 1 : vwghts[w] ; if ( msglvl > 3 ) { fprintf(msgFile, ", inside") ; } } } if ( frontmap[J] != 0 ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n inside = %d, adding %d to L11", inside, nJ*nJ + 2*nJ*inside) ; } nL11 += nJ*nJ + 2*nJ*inside ; } else { if ( msglvl > 3 ) { fprintf(msgFile, "\n inside = %d, adding %d to L22", inside, nJ*nJ + 2*nJ*inside) ; } nL22 += nJ*nJ + 2*nJ*inside ; } } if ( msglvl > 0 ) { fprintf(msgFile, "\n |L| = %.0f, |L11| = %.0f, |L22| = %.0f", nL, nL11, nL22) ; } /* ------------------------------------ compute the number of entries in A21 ------------------------------------ */ nA21 = 0 ; if ( vwghts != NULL ) { for ( v = 0 ; v < nvtx ; v++ ) { if ( map[v] == 0 ) { Graph_adjAndSize(graph, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( map[v] != map[w] ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n A21 : v = %d, w = %d", v, w) ; } nA21 += vwghts[v] * vwghts[w] ; } } } } } else { for ( v = 0 ; v < nvtx ; v++ ) { if ( map[v] == 0 ) { Graph_adjAndSize(graph, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( map[v] != map[w] ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n A21 : v = %d, w = %d", v, w) ; } nA21++ ; } } } } } if ( msglvl > 0 ) { fprintf(msgFile, "\n |L| = %.0f, |L11| = %.0f, |L22| = %.0f, |A21| = %.0f", nL, nL11, nL22, nA21) ; fprintf(msgFile, "\n storage: explicit = %.0f, semi-implicit = %.0f, ratio = %.3f" "\n opcount: explicit = %.0f, semi-implicit = %.0f, ratio = %.3f", nL, nL11 + nA21 + nL22, nL/(nL11 + nA21 + nL22), 2*nL, 4*nL11 + 2*nA21 + 2*nL22, 2*nL/(4*nL11 + 2*nA21 + 2*nL22)) ; fprintf(msgFile, "\n ratios %8.3f %8.3f %8.3f", nPhi/nV, nL/(nL11 + nA21 + nL22), 2*nL/(4*nL11 + 2*nA21 + 2*nL22)) ; } /* ------------------------ free the working storage ------------------------ */ Graph_free(graph) ; ETree_free(etree) ; IV_free(mapIV) ; IVL_free(symbfacIVL) ; IVfree(frontmap) ; fprintf(msgFile, "\n") ; fclose(msgFile) ; return(1) ; }
/* ------------------------------------------------- draw a graph to an EPS file (1) read a Graph object (2) read a Coords object (3) read an IV object that contains a tag vector. if (v,w) is an edge in the graph and tags[v] == tags[w] then draw edge (v,w) (4) bbox[4] is the bounding box for the plot. bbox = { xsw, ysw, xne, yne } try bbox = { 0, 0, 500, 500 } because coordinates are measured in points, 72 points per inch. (5) rect[4] contains the frame for the plot. to put a 20 point margin around the plot, rect[0] = bbox[0] + 20 rect[1] = bbox[1] + 20 rect[2] = bbox[2] - 20 rect[3] = bbox[3] - 20 created -- 98apr11, cca ------------------------------------------------- */ void drawGraphEPS ( Graph *graph, Coords *coords, IV *tagsIV, double bbox[], double rect[], double linewidth1, double linewidth2, double radius, char *epsFileName, int msglvl, FILE *msgFile ) { double a, b, d, height, offset, width, xmax, xmin, xsize, xv, xw, x0, x1, ymax, ymin, ysize, yv, yw, y0, y1 ; FILE *epsFile ; int ii, nedge, nvtx, v, vsize, w ; int *tags, *vadj ; nvtx = graph->nvtx ; if ( tagsIV == NULL ) { tags = NULL ; } else { tags = IV_entries(tagsIV) ; } /* ----------------- open the EPS file ----------------- */ if ( strcmp(epsFileName, "stdout") == 0 ) { epsFile = stdout ; } else if ( (epsFile = fopen(epsFileName, "w")) == NULL ) { fprintf(stderr, "\n fatal error in drawGraphEPS" "\n unable to open file %s\n", epsFileName) ; return ; } /* ----------------------------------- write the preamble for the EPS file ----------------------------------- */ fprintf(epsFile, "%%!PS-Adobe-2.0 EPSF-1.2" "\n%%%%BoundingBox: %.1f %.1f %.1f %.1f", bbox[0], bbox[1], bbox[2], bbox[3]) ; fprintf(epsFile, "\n /radius %.3f def" "\n /Helvetica findfont %.3f scalefont setfont" "\n /M {moveto} def" "\n /L {lineto} def" "\n /ACF { %% stack : x y radius" "\n newpath 0 360 arc closepath fill " "\n } def" "\n /str 6 string def" "\n /drawLabel { %% x y label radius" "\n /radius exch def" "\n /label exch def" "\n /y exch def" "\n /x exch def" "\n gsave" "\n 1.0 setgray" "\n x radius add y moveto" "\n x y radius 0 360 arc" "\n fill" "\n 0.0 setgray" "\n x radius add y moveto" "\n x y radius 0 360 arc" "\n stroke" "\n x y moveto" "\n label stringwidth pop 2 div neg radius 2 div neg rmoveto" "\n label show" "\n grestore" "\n } def ", radius, 1.25*radius) ; /* --------------------------------------- determine the transformation parameters --------------------------------------- */ xmin = Coords_min(coords, 1) ; xmax = Coords_max(coords, 1) ; ymin = Coords_min(coords, 2) ; ymax = Coords_max(coords, 2) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n xmin = %.3g, xmax = %.3g, ymin = %.3g, ymax = %.3g", xmin, xmax, ymin, ymax) ; } xsize = xmax - xmin ; ysize = ymax - ymin ; width = rect[2] - rect[0] ; height = rect[3] - rect[1] ; if ( msglvl > 2 ) { fprintf(msgFile, "\n xsize = %.3g, ysize = %.3g, width = %.3g, height = %.3g", xsize, ysize, width, height) ; } if ( ysize * width <= xsize * height ) { a = width / xsize ; b = rect[0] ; offset = (rect[3] - rect[1] - a * ysize)/2 ; d = rect[1] + offset - a * ymin ; } else { a = height / ysize ; d = rect[1] ; offset = (rect[2] - rect[0] - a * xsize)/2 ; b = rect[0] + offset - a * xmin ; } if ( ysize * width <= xsize * height ) { a = width / xsize ; } else { a = height / ysize ; } b = 0.5*(rect[2] + rect[0] - a*(xmin + xmax)) ; d = 0.5*(rect[3] + rect[1] - a*(ymin + ymax)) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n width = %.3g, height = %.3g", width, height) ; fprintf(msgFile, "\n xsize = %.3g, ysize = %.3g", xsize, ysize) ; fprintf(msgFile, "\n xmin = %.3g, xmax = %.3g, ymin = %.3g, ymax = %.3g", xmin, xmax, ymin, ymax) ; fprintf(msgFile, "\n a = %.3g, b = %.3g, d = %.3g", a, b, d) ; } if ( tags == NULL ) { /* -------------------------------- no component ids, draw the edges -------------------------------- */ fprintf(epsFile, "\n gsave" "\n %.3f setlinewidth" "\n 0.0 setgray", linewidth1) ; nedge = 0 ; for ( v = 0 ; v < nvtx ; v++ ) { Graph_adjAndSize(graph, v, &vsize, &vadj) ; xv = Coords_value(coords, 1, v) ; yv = Coords_value(coords, 2, v) ; x0 = a * xv + b ; y0 = a * yv + d ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < v ) { xw = Coords_value(coords, 1, w) ; yw = Coords_value(coords, 2, w) ; x1 = a * xw + b ; y1 = a * yw + d ; if ( nedge % 100 == 0 ) { fprintf(epsFile, "\n newpath") ; } fprintf(epsFile, "\n %.3g %.3g M %.3g %.3g L", x0, y0, x1, y1) ; if ( ++nedge % 100 == 0 ) { fprintf(epsFile, "\n stroke") ; } } } } if ( nedge % 100 != 0 ) { fprintf(epsFile, "\n stroke") ; } fprintf(epsFile, "\n grestore") ; fprintf(epsFile, "\n gsave" "\n 0.1 setlinewidth" "\n 0.0 setgray") ; if ( radius > 0.0 ) { /* ----------------- draw the vertices ----------------- */ for ( v = 0 ; v < nvtx ; v++ ) { xv = Coords_value(coords, 1, v) ; yv = Coords_value(coords, 2, v) ; x0 = a * xv + b ; y0 = a * yv + d ; fprintf(epsFile, "\n %.3f %.3f () radius drawLabel", x0, y0) ; } } fprintf(epsFile, "\n grestore") ; } else { /* ----------------------------------------- component ids are present, draw the edges between vertices in the same component ----------------------------------------- */ fprintf(epsFile, "\n gsave" "\n %.3f setlinewidth" "\n 0.0 setgray", linewidth1) ; nedge = 0 ; for ( v = 0 ; v < nvtx ; v++ ) { if ( tags[v] >= 0 ) { Graph_adjAndSize(graph, v, &vsize, &vadj) ; xv = Coords_value(coords, 1, v) ; yv = Coords_value(coords, 2, v) ; x0 = a * xv + b ; y0 = a * yv + d ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < v && tags[w] == tags[v] ) { xw = Coords_value(coords, 1, w) ; yw = Coords_value(coords, 2, w) ; x1 = a * xw + b ; y1 = a * yw + d ; if ( nedge % 100 == 0 ) { fprintf(epsFile, "\n newpath") ; } fprintf(epsFile, "\n %.3g %.3g M %.3g %.3g L", x0, y0, x1, y1) ; if ( ++nedge % 100 == 0 ) { fprintf(epsFile, "\n stroke") ; } } } } } if ( nedge % 100 != 0 ) { fprintf(epsFile, "\n stroke") ; } fprintf(epsFile, "\n grestore") ; fprintf(epsFile, "\n gsave" "\n %.3f setlinewidth" "\n 0.0 setgray", linewidth2) ; nedge = 0 ; for ( v = 0 ; v < nvtx ; v++ ) { if ( tags[v] >= 0 ) { Graph_adjAndSize(graph, v, &vsize, &vadj) ; xv = Coords_value(coords, 1, v) ; yv = Coords_value(coords, 2, v) ; x0 = a * xv + b ; y0 = a * yv + d ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < v && tags[w] != tags[v] && tags[w] >= 0 ) { xw = Coords_value(coords, 1, w) ; yw = Coords_value(coords, 2, w) ; x1 = a * xw + b ; y1 = a * yw + d ; if ( nedge % 100 == 0 ) { fprintf(epsFile, "\n newpath") ; } fprintf(epsFile, "\n %.3g %.3g M %.3g %.3g L", x0, y0, x1, y1) ; if ( ++nedge % 100 == 0 ) { fprintf(epsFile, "\n stroke") ; } } } } } if ( nedge % 100 != 0 ) { fprintf(epsFile, "\n stroke") ; } fprintf(epsFile, "\n grestore") ; fprintf(epsFile, "\n gsave" "\n 0.1 setlinewidth" "\n 0.0 setgray") ; if ( radius > 0.0 ) { /* ----------------- draw the vertices ----------------- */ for ( v = 0 ; v < nvtx ; v++ ) { if ( tags[v] >= 0 ) { xv = Coords_value(coords, 1, v) ; yv = Coords_value(coords, 2, v) ; x0 = a * xv + b ; y0 = a * yv + d ; fprintf(epsFile, "\n %.3f %.3f (%d) radius drawLabel", x0, y0, tags[v]) ; } } } fprintf(epsFile, "\n grestore") ; } fprintf(epsFile, "\n showpage") ; /* ---------------------------- close the file if not stdout ---------------------------- */ if ( strcmp(epsFileName, "stdout") != 0 ) { fclose(epsFile) ; } return ; }