/* ------------------------------------------------------------------ create and return a height metric DV object input : vmetricDV -- a metric defined on the vertices output : dmetricDV -- a depth metric defined on the vertices hmetric[v] = vmetric[v] + max{p(u) = v} hmetric[u] if fch[v] != -1 = vmetric[v] if fch[v] == -1 created -- 96jun23, cca ------------------------------------------------------------------ */ DV * Tree_setHeightDmetric ( Tree *tree, DV *vmetricDV ) { int u, v, val ; double *hmetric, *vmetric ; DV *hmetricDV ; /* --------------- check the input --------------- */ if ( tree == NULL || tree->n < 1 || vmetricDV == NULL || tree->n != DV_size(vmetricDV) || (vmetric = DV_entries(vmetricDV)) == NULL ) { fprintf(stderr, "\n fatal error in Tree_setHeightDmetric(%p,%p)" "\n bad input\n", tree, vmetricDV) ; exit(-1) ; } hmetricDV = DV_new() ; DV_init(hmetricDV, tree->n, NULL) ; hmetric = DV_entries(hmetricDV) ; for ( v = Tree_postOTfirst(tree) ; v != -1 ; v = Tree_postOTnext(tree, v) ) { for ( u = tree->fch[v], val = 0 ; u != -1 ; u = tree->sib[u] ) { if ( val < hmetric[u] ) { val = hmetric[u] ; } } hmetric[v] = val + vmetric[v] ; } return(hmetricDV) ; }
/* ------------------------------------------------------ create and return a subtree metric DV object input : vmetricDV -- a metric defined on the vertices return : tmetricDV -- a metric defined on the subtrees created -- 96jun23, cca ------------------------------------------------------ */ DV * Tree_setSubtreeDmetric ( Tree *tree, DV *vmetricDV ) { int u, v ; double *tmetric, *vmetric ; DV *tmetricDV ; /* --------------- check the input --------------- */ if ( tree == NULL || tree->n <= 0 || vmetricDV == NULL || tree->n != DV_size(vmetricDV) || (vmetric = DV_entries(vmetricDV)) == NULL ) { fprintf(stderr, "\n fatal error in Tree_setSubtreeImetric(%p,%p)" "\n bad input\n", tree, vmetricDV) ; exit(-1) ; } tmetricDV = DV_new() ; DV_init(tmetricDV, tree->n, NULL) ; tmetric = DV_entries(tmetricDV) ; for ( v = Tree_postOTfirst(tree) ; v != -1 ; v = Tree_postOTnext(tree, v) ) { tmetric[v] = vmetric[v] ; for ( u = tree->fch[v] ; u != -1 ; u = tree->sib[u] ) { tmetric[v] += tmetric[u] ; } } return(tmetricDV) ; }
/* --------------------------------------------------------------- purpose -- fill dvec[J] with the stack storage to solve for J in a forward solve created -- 97nov30, cca --------------------------------------------------------------- */ void ETree_forwSolveProfile ( ETree *etree, double dvec[] ) { int I, J, maxstack, nDJ, nfront, nUJ, stack ; int *bndwghts, *fch, *nodwghts, *sib ; Tree *tree ; /* --------------- check the input --------------- */ if ( etree == NULL || dvec == NULL ) { fprintf(stderr, "\n fatal error in ETree_forwSolveProfile(%p,%p)" "\n bad input\n", etree, dvec) ; exit(-1) ; } tree = ETree_tree(etree) ; nodwghts = ETree_nodwghts(etree) ; bndwghts = ETree_bndwghts(etree) ; nfront = ETree_nfront(etree) ; fch = ETree_fch(etree) ; sib = ETree_sib(etree) ; /* --------------------------------------------- loop over the nodes in a post-order traversal --------------------------------------------- */ maxstack = stack = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { nDJ = nodwghts[J] ; nUJ = bndwghts[J] ; stack += nDJ + nUJ ; dvec[J] = stack ; if ( maxstack < stack ) { maxstack = stack ; } #if MYDEBUG > 0 fprintf(stdout, "\n working on front %d, nD = %d, nU = %d, stack = %d", J, nDJ, nUJ, stack) ; #endif for ( I = fch[J] ; I != -1 ; I = sib[I] ) { stack -= bndwghts[I] ; } stack -= nDJ ; } #if MYDEBUG >= 0 fprintf(stdout, "\n forward solve : final stack = %d, max stack = %d", stack, maxstack) ; #endif return ; }
/* ------------------------------------------------------------------ create and return a height metric IV object input : vmetricIV -- a metric defined on the vertices output : dmetricIV -- a depth metric defined on the vertices hmetric[v] = vmetric[v] + max{p(u) = v} hmetric[u] if fch[v] != -1 = vmetric[v] if fch[v] == -1 created -- 96jun23, cca ------------------------------------------------------------------ */ IV * Tree_setHeightImetric ( Tree *tree, IV *vmetricIV ) { int u, v, val ; int *hmetric, *vmetric ; IV *hmetricIV ; /* --------------- check the input --------------- */ if ( tree == NULL || tree->n < 1 || vmetricIV == NULL || tree->n != IV_size(vmetricIV) || (vmetric = IV_entries(vmetricIV)) == NULL ) { fprintf(stderr, "\n fatal error in Tree_setHeightImetric(%p,%p)" "\n bad input\n", tree, vmetricIV) ; if ( tree != NULL ) { Tree_writeForHumanEye(tree, stderr) ; } if ( vmetricIV != NULL ) { IV_writeForHumanEye(vmetricIV, stderr) ; } exit(-1) ; } hmetricIV = IV_new() ; IV_init(hmetricIV, tree->n, NULL) ; hmetric = IV_entries(hmetricIV) ; for ( v = Tree_postOTfirst(tree) ; v != -1 ; v = Tree_postOTnext(tree, v) ) { for ( u = tree->fch[v], val = 0 ; u != -1 ; u = tree->sib[u] ) { if ( val < hmetric[u] ) { val = hmetric[u] ; } } hmetric[v] = val + vmetric[v] ; } return(hmetricIV) ; }
/* -------------------------------------------- create and return an IV object that contains the map from vertices to fundamental chains. return value -- # of fundamental chains created -- 96jun23, cca ------------------------------------------- */ IV * Tree_fundChainMap ( Tree *tree ) { int nfc, u, v ; int *map ; IV *mapIV ; /* --------------- check the input --------------- */ if ( tree == NULL || tree->n <= 0 ) { fprintf(stderr, "\n fatal error in Tree_fundChainMap(%p)" "\n bad input\n", tree) ; exit(-1) ; } mapIV = IV_new() ; IV_init(mapIV, tree->n, NULL) ; map = IV_entries(mapIV) ; for ( v = Tree_postOTfirst(tree), nfc = 0 ; v != -1 ; v = Tree_postOTnext(tree, v) ) { if ( (u = tree->fch[v]) == -1 || tree->sib[u] != -1 ) { /* -------------------- v starts a new chain -------------------- */ map[v] = nfc++ ; } else { /* ----------------------------------------------- v belongs in the same chain as its only child u ----------------------------------------------- */ map[v] = map[u] ; } } return(mapIV) ; }
/* ---------------------------------------------- purpose -- map the off diagonal blocks to processes in a domain decomposition fashion created -- 98mar28, cca ---------------------------------------------- */ void SolveMap_ddMap ( SolveMap *solvemap, int symmetryflag, IVL *upperBlockIVL, IVL *lowerBlockIVL, int nproc, IV *ownersIV, Tree *tree, int seed, int msglvl, FILE *msgFile ) { char *mark ; Drand drand ; int ii, I, J, K, loc, nadj, nblockLower, nblockUpper, nfront, proc ; int *adj, *colids, *fch, *map, *owners, *rowids, *sib ; /* --------------- check the input --------------- */ if ( solvemap == NULL || symmetryflag < 0 || upperBlockIVL == NULL || ownersIV == NULL ) { fprintf(stderr, "\n fatal error in SolveMap_ddMap(%p,%d,%p,%p,%p,%d)" "\n bad input\n", solvemap, symmetryflag, upperBlockIVL, lowerBlockIVL, ownersIV, seed) ; spoolesFatal(); } nfront = IV_size(ownersIV) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n SolveMap_ddMap(): nfront = %d, nproc = %d", nfront, nproc) ; fflush(msgFile) ; } /* ----------------------------------------------------------- count the number of upper blocks that do not include U(J,J) ----------------------------------------------------------- */ if ( msglvl > 2 ) { fprintf(msgFile, "\n upperBlockIVL = %p", upperBlockIVL) ; fflush(msgFile) ; } nblockUpper = 0 ; for ( J = 0 ; J < nfront ; J++ ) { IVL_listAndSize(upperBlockIVL, J, &nadj, &adj) ; for ( ii = 0 ; ii < nadj ; ii++ ) { if ( adj[ii] > J ) { nblockUpper++ ; } } } if ( msglvl > 2 ) { fprintf(msgFile, "\n nblockUpper = %d", nblockUpper) ; fflush(msgFile) ; } /* ----------------------------------------------------------- count the number of lower blocks that do not include L(J,J) ----------------------------------------------------------- */ if ( msglvl > 2 ) { fprintf(msgFile, "\n lowerBlockIVL = %p", lowerBlockIVL) ; fflush(msgFile) ; } nblockLower = 0 ; if ( lowerBlockIVL != NULL ) { for ( J = 0 ; J < nfront ; J++ ) { IVL_listAndSize(lowerBlockIVL, J, &nadj, &adj) ; for ( ii = 0 ; ii < nadj ; ii++ ) { if ( adj[ii] > J ) { nblockLower++ ; } } } } if ( msglvl > 2 ) { fprintf(msgFile, "\n nblockLower = %d", nblockLower) ; fflush(msgFile) ; } /* --------------------- initialize the object --------------------- */ SolveMap_init(solvemap, symmetryflag, nfront, nproc, nblockUpper, nblockLower) ; owners = SolveMap_owners(solvemap) ; /* ---------------------- fill the owners vector ---------------------- */ IVcopy(nfront, owners, IV_entries(ownersIV)) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n owners") ; IVfprintf(msgFile, nfront, owners) ; fflush(msgFile) ; } /* ----------------------------------------------------- mark a node J in the tree as 'D' if it is in a domain (owners[J] = owners[I] for all I a descendent of J) and 'S' (for the schur complement) otherwise ----------------------------------------------------- */ mark = CVinit(nfront, 'D') ; fch = tree->fch ; sib = tree->sib ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { for ( I = fch[J] ; I != -1 ; I = sib[I] ) { if ( mark[I] != 'D' || owners[I] != owners[J] ) { mark[J] = 'S' ; break ; } } } /* -------------------------------------- initialize the random number generator -------------------------------------- */ Drand_setDefaultFields(&drand) ; Drand_setUniform(&drand, 0, nproc) ; /* ------------------------------- if J is in a domain map(J,K) to owners[J] else map(J,K) to a random process ------------------------------- */ if ( msglvl > 2 ) { fprintf(msgFile, "\n\n mapping upper blocks") ; fflush(msgFile) ; } rowids = SolveMap_rowidsUpper(solvemap) ; colids = SolveMap_colidsUpper(solvemap) ; map = SolveMap_mapUpper(solvemap) ; for ( J = loc = 0 ; J < nfront ; J++ ) { IVL_listAndSize(upperBlockIVL, J, &nadj, &adj) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n J = %d", J) ; fflush(msgFile) ; } for ( ii = 0 ; ii < nadj ; ii++ ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n K = %d", adj[ii]) ; fflush(msgFile) ; } if ( (K = adj[ii]) > J ) { if ( mark[J] == 'D' ) { proc = owners[J] ; } else { proc = (int) Drand_value(&drand) ; } rowids[loc] = J ; colids[loc] = K ; map[loc] = proc ; if ( msglvl > 2 ) { fprintf(msgFile, ", map[%d] = %d", loc, map[loc]) ; fflush(msgFile) ; } loc++ ; } } } if ( symmetryflag == SPOOLES_NONSYMMETRIC ) { /* ------------------------------- if J is in a domain map(K,J) to owners[J] else map(K,J) to a random process ------------------------------- */ if ( msglvl > 2 ) { fprintf(msgFile, "\n\n mapping lower blocks") ; fflush(msgFile) ; } rowids = SolveMap_rowidsLower(solvemap) ; colids = SolveMap_colidsLower(solvemap) ; map = SolveMap_mapLower(solvemap) ; for ( J = loc = 0 ; J < nfront ; J++ ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n J = %d", J) ; fflush(msgFile) ; } IVL_listAndSize(lowerBlockIVL, J, &nadj, &adj) ; for ( ii = 0 ; ii < nadj ; ii++ ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n K = %d", adj[ii]) ; fflush(msgFile) ; } if ( (K = adj[ii]) > J ) { if ( mark[J] == 'D' ) { proc = owners[J] ; } else { proc = (int) Drand_value(&drand) ; } rowids[loc] = K ; colids[loc] = J ; map[loc] = proc ; if ( msglvl > 2 ) { fprintf(msgFile, ", map[%d] = %d", loc, map[loc]) ; fflush(msgFile) ; } loc++ ; } } } } /* ------------------------ free the working storage ------------------------ */ CVfree(mark) ; 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) ; }
/* --------------------------------------------------------------- purpose -- fill dvec[J] with the active storage to eliminate J using the right-looking general sparse method symflag -- symmetry flag, one of SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC created -- 98dec19, cca --------------------------------------------------------------- */ void ETree_FSstorageProfile ( ETree *etree, int symflag, IVL *symbfacIVL, double dvec[] ) { char *incore ; int ii, J, K, nDJ, nfront, nUJ, sizeJ, storage ; int *bndwghts, *indJ, *mark, *nodwghts, *stor, *vtxToFront ; Tree *tree ; /* --------------- check the input --------------- */ if ( etree == NULL || symbfacIVL == NULL || dvec == NULL ) { fprintf(stderr, "\n fatal error in ETree_FSstorageProfile(%p,%p,%p)" "\n bad input\n", etree, symbfacIVL, dvec) ; exit(-1) ; } tree = ETree_tree(etree) ; nodwghts = ETree_nodwghts(etree) ; bndwghts = ETree_bndwghts(etree) ; vtxToFront = ETree_vtxToFront(etree) ; nfront = ETree_nfront(etree) ; incore = CVinit(nfront, 'F') ; stor = IVinit(nfront, 0) ; mark = IVinit(nfront, -1) ; /* -------------------------------------------- compute the storage for each front's chevron -------------------------------------------- */ if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { for ( J = 0 ; J < nfront ; J++ ) { nDJ = nodwghts[J] ; nUJ = bndwghts[J] ; stor[J] = (nDJ*(nDJ+1))/2 + nDJ*nUJ ; } } else { for ( J = 0 ; J < nfront ; J++ ) { nDJ = nodwghts[J] ; nUJ = bndwghts[J] ; stor[J] = nDJ*nDJ + 2*nDJ*nUJ ; } } /* --------------------------------------------- loop over the nodes in a post-order traversal --------------------------------------------- */ storage = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { if ( incore[J] == 'F' ) { storage += stor[J] ; incore[J] = 'T' ; } IVL_listAndSize(symbfacIVL, J, &sizeJ, &indJ) ; mark[J] = J ; for ( ii = 0 ; ii < sizeJ ; ii++ ) { K = vtxToFront[indJ[ii]] ; if ( mark[K] != J ) { mark[K] = J ; if ( incore[K] == 'F' ) { storage += stor[K] ; incore[K] = 'T' ; } } } dvec[J] = storage ; storage -= stor[J] ; } IVfree(mark) ; IVfree(stor) ; CVfree(incore) ; return ; }
/* --------------------------------------------------------------- purpose -- fill dvec[J] with the active storage to eliminate J using the multifrontal method symflag -- symmetry flag, one of SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC created -- 97may21, cca --------------------------------------------------------------- */ void ETree_MFstackProfile ( ETree *etree, int symflag, double dvec[] ) { int I, J, nDJ, nUI, nUJ, stack ; int *bndwghts, *fch, *nodwghts, *sib ; Tree *tree ; /* --------------- check the input --------------- */ if ( etree == NULL || dvec == NULL ) { fprintf(stderr, "\n fatal error in ETree_MFstackProfile(%p,%p)" "\n bad input\n", etree, dvec) ; exit(-1) ; } tree = ETree_tree(etree) ; nodwghts = ETree_nodwghts(etree) ; bndwghts = ETree_bndwghts(etree) ; fch = ETree_fch(etree) ; sib = ETree_sib(etree) ; /* --------------------------------------------- loop over the nodes in a post-order traversal --------------------------------------------- */ stack = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { nDJ = nodwghts[J] ; nUJ = bndwghts[J] ; #if MYDEBUG > 0 fprintf(stdout, "\n working on front %d, nD = %d, nU = %d, stack = %d", J, nDJ, nUJ, stack) ; #endif if ( (I = fch[J]) != -1 ) { /* -------------------------------- remove last child from the stack -------------------------------- */ while ( sib[I] != -1 ) { I = sib[I] ; } nUI = bndwghts[I] ; if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { stack -= (nUI*(nUI+1))/2 ; } else if ( symflag == SPOOLES_NONSYMMETRIC ) { stack -= nUI*nUI ; } #if MYDEBUG > 0 fprintf(stdout, "\n removing last child %d, stack = %d", I, stack) ; #endif } /* --------------------------------- add frontal matrix for J to stack and store as the storage for J --------------------------------- */ dvec[J] = stack + (nDJ + nUJ)*(nDJ + nUJ) ; if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { dvec[J] = stack + ((nDJ + nUJ)*(nDJ + nUJ+1))/2 ; } else if ( symflag == SPOOLES_NONSYMMETRIC ) { dvec[J] = stack + (nDJ + nUJ)*(nDJ + nUJ) ; } #if MYDEBUG > 0 fprintf(stdout, "\n working storage = %.0f", dvec[J]) ; #endif if ( (I = fch[J]) != -1 ) { /* ------------------------------------ remove other children from the stack ------------------------------------ */ while ( sib[I] != -1 ) { nUI = bndwghts[I] ; if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { stack -= (nUI*(nUI+1))/2 ; } else if ( symflag == SPOOLES_NONSYMMETRIC ) { stack -= nUI*nUI ; } #if MYDEBUG > 0 fprintf(stdout, "\n removing child %d, stack = %d", I, stack) ; #endif I = sib[I] ; } } /* -------------------------------- add update matrix for J to stack -------------------------------- */ if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { stack += (nUJ*(nUJ+1))/2 ; } else if ( symflag == SPOOLES_NONSYMMETRIC ) { stack += nUJ*nUJ ; } #if MYDEBUG > 0 fprintf(stdout, "\n adding update matrix, stack = %d", stack) ; #endif } #if MYDEBUG >= 0 fprintf(stdout, "\n MF: final stack = %d", stack) ; #endif return ; }
/* --------------------------------------------------------------- purpose -- fill dvec[J] with the active storage to eliminate J using the left-looking general sparse method symflag -- symmetry flag, one of SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC created -- 97may21, cca --------------------------------------------------------------- */ void ETree_GSstorageProfile ( ETree *etree, int symflag, IVL *symbfacIVL, int *vwghts, double dvec[] ) { int count, ii, I, J, K, nDJ, nfront, nUJ, sizeI, sizeJ, storage, v ; int *bndwghts, *head, *indI, *indJ, *link, *nodwghts, *offsets, *vtxToFront ; Tree *tree ; /* --------------- check the input --------------- */ if ( etree == NULL || symbfacIVL == NULL || dvec == NULL ) { fprintf(stderr, "\n fatal error in ETree_GSstorageProfile(%p,%p,%p,%p)" "\n bad input\n", etree, symbfacIVL, vwghts, dvec) ; exit(-1) ; } tree = ETree_tree(etree) ; nodwghts = ETree_nodwghts(etree) ; bndwghts = ETree_bndwghts(etree) ; vtxToFront = ETree_vtxToFront(etree) ; nfront = ETree_nfront(etree) ; head = IVinit(nfront, -1) ; link = IVinit(nfront, -1) ; offsets = IVinit(nfront, 0) ; /* --------------------------------------------- loop over the nodes in a post-order traversal --------------------------------------------- */ storage = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { nDJ = nodwghts[J] ; nUJ = bndwghts[J] ; if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { storage += (nDJ*(nDJ + 1))/2 + nDJ*nUJ ; } else if ( symflag == SPOOLES_NONSYMMETRIC ) { storage += nDJ*nDJ + 2*nDJ*nUJ ; } dvec[J] = storage ; #if MYDEBUG > 0 fprintf(stdout, "\n working on front %d, nD = %d, nU = %d, storage = %d", J, nDJ, nUJ, storage) ; #endif /* ----------------------------- loop over the updating fronts ----------------------------- */ while ( (I = head[J]) != -1 ) { head[J] = link[I] ; IVL_listAndSize(symbfacIVL, I, &sizeI, &indI) ; #if MYDEBUG > 0 fprintf(stdout, "\n updating front %d, offset = %d, sizeI = %d", I, offsets[I], sizeI) ; IVfprintf(stdout, sizeI, indI) ; #endif for ( ii = offsets[I], count = 0, K = -1 ; ii < sizeI ; ii++ ) { v = indI[ii] ; #if MYDEBUG > 0 fprintf(stdout, "\n ii = %d, v = %d, K = %d", ii, v, vtxToFront[v]) ; fflush(stdout) ; #endif K = vtxToFront[v] ; if ( K < 0 || K >= nfront ) { fprintf(stderr, "\n\n fatal error" "\n ii = %d, v = %d, K = %d", ii, v, K) ; exit(-1) ; } if ( (K = vtxToFront[v]) != J ) { #if MYDEBUG > 0 fprintf(stdout, "\n linking to next ancestor %d", K) ; #endif link[I] = head[K] ; head[K] = I ; offsets[I] = ii ; break ; } count += (vwghts == NULL) ? 1 : vwghts[v] ; #if MYDEBUG > 0 fprintf(stdout, "\n count = %d", count) ; fflush(stdout) ; #endif } if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { storage -= count*nodwghts[I] ; } else if ( symflag == SPOOLES_NONSYMMETRIC ) { storage -= 2*count*nodwghts[I] ; } } if ( symflag == SPOOLES_SYMMETRIC || symflag == SPOOLES_HERMITIAN ) { storage -= (nDJ*(nDJ+1))/2 ; } else if ( symflag == SPOOLES_NONSYMMETRIC ) { storage -= nDJ*nDJ ; } if ( nUJ > 0 ) { IVL_listAndSize(symbfacIVL, J, &sizeJ, &indJ) ; for ( ii = 0 ; ii < sizeJ ; ii++ ) { v = indJ[ii] ; if ( (K = vtxToFront[v]) != J ) { break ; } } offsets[J] = ii ; #if MYDEBUG > 0 fprintf(stdout, "\n linking to next ancestor %d", K) ; #endif IVL_listAndSize(symbfacIVL, J, &sizeJ, &indJ) ; link[J] = head[K] ; head[K] = J ; } #if MYDEBUG > 0 fprintf(stdout, "\n at end of step %d, storage = %d", J, storage) ; #endif } #if MYDEBUG >= 0 fprintf(stdout, "\n GS: final storage = %d", storage) ; #endif IVfree(head) ; IVfree(link) ; IVfree(offsets) ; return ; }
/* ------------------------------------------------- expand an ETree object by splitting a large front into a chain of smaller fronts. created -- 96jun27, cca ------------------------------------------------- */ ETree * ETree_splitFronts ( ETree *etree, int vwghts[], int maxfrontsize, int seed ) { ETree *etree2 ; int count, front, ii, I, Inew, J, Jnew, nbnd, newsize, nint, nfront, nfront2, nsplit, nvtx, prev, size, sizeJ, v, vwght ; int *bndwghts, *fch, *head, *indices, *link, *newbndwghts, *newmap, *newnodwghts, *newpar, *nodwghts, *roots, *sib, *vtxToFront ; Tree *tree ; /* --------------- check the input --------------- */ if ( etree == NULL || (nfront = etree->nfront) <= 0 || (nvtx = etree->nvtx) <= 0 || maxfrontsize <= 0 ) { fprintf(stderr, "\n fatal error in ETree_splitFronts(%p,%p,%d,%d)" "\n bad input\n", etree, vwghts, maxfrontsize, seed) ; spoolesFatal(); } tree = etree->tree ; fch = tree->fch ; sib = tree->sib ; nodwghts = IV_entries(etree->nodwghtsIV) ; bndwghts = IV_entries(etree->bndwghtsIV) ; vtxToFront = IV_entries(etree->vtxToFrontIV) ; /* -------------------------- set up the working storage -------------------------- */ newpar = IVinit(nvtx, -1) ; roots = IVinit(nfront, -1) ; newmap = IVinit(nvtx, -1) ; newnodwghts = IVinit(nvtx, -1) ; newbndwghts = IVinit(nvtx, -1) ; head = IVinit(nfront, -1) ; link = IVinit(nvtx, -1) ; indices = IVinit(nvtx, -1) ; for ( v = 0 ; v < nvtx ; v++ ) { front = vtxToFront[v] ; link[v] = head[front] ; head[front] = v ; } /* ------------------------------------------------ execute a post-order traversal of the front tree ------------------------------------------------ */ nfront2 = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { sizeJ = 0 ; for ( v = head[J], count = 0 ; v != -1 ; v = link[v] ) { indices[count++] = v ; vwght = (vwghts != NULL) ? vwghts[v] : 1 ; sizeJ += vwght ; } if ( sizeJ != nodwghts[J] ) { fprintf(stderr, "\n fatal error in ETree_splitFronts(%p,%p,%d,%d)" "\n J = %d, sizeJ = %d, nodwght = %d\n", etree, vwghts, maxfrontsize, seed, J, sizeJ, nodwghts[J]) ; spoolesFatal(); } #if MYDEBUG > 0 fprintf(stdout, "\n\n checking out front %d, size %d", J, sizeJ) ; #endif if ( sizeJ <= maxfrontsize || fch[J] == -1 ) { /* ------------------------------------------- this front is small enough (or is a domain) ------------------------------------------- */ Jnew = nfront2++ ; for ( ii = 0 ; ii < count ; ii++ ) { v = indices[ii] ; newmap[v] = Jnew ; #if MYDEBUG > 1 fprintf(stdout, "\n mapping vertex %d into new front %d", v, Jnew) ; #endif } for ( I = fch[J] ; I != -1 ; I = sib[I] ) { Inew = roots[I] ; newpar[Inew] = Jnew ; } newnodwghts[Jnew] = nodwghts[J] ; newbndwghts[Jnew] = bndwghts[J] ; roots[J] = Jnew ; #if MYDEBUG > 0 fprintf(stdout, "\n front is small enough, Jnew = %d", Jnew) ; #endif } else { /* ------------------------------------------ this front is too large, split into pieces whose size differs by one vertex ------------------------------------------ */ nsplit = (sizeJ + maxfrontsize - 1)/maxfrontsize ; newsize = sizeJ / nsplit ; if ( sizeJ % nsplit != 0 ) { newsize++ ; } #if MYDEBUG > 0 fprintf(stdout, "\n front is too large, %d target fronts, target size = %d", nsplit, newsize) ; #endif prev = -1 ; nint = nodwghts[J] ; nbnd = nint + bndwghts[J] ; if ( seed > 0 ) { IVshuffle(count, indices, seed) ; } ii = 0 ; while ( ii < count ) { Jnew = nfront2++ ; size = 0 ; while ( ii < count ) { v = indices[ii] ; vwght = (vwghts != NULL) ? vwghts[v] : 1 ; #if MYDEBUG > 0 fprintf(stdout, "\n ii = %d, v = %d, vwght = %d, size = %d", ii, v, vwght, size) ; #endif /* ----------------------------------------------- 97aug28, cca bug fix. front is created even if it is too big ----------------------------------------------- */ if ( newsize >= size + vwght || size == 0 ) { newmap[v] = Jnew ; size += vwght ; #if MYDEBUG > 0 fprintf(stdout, "\n mapping vertex %d into new front %d, size = %d", v, Jnew, size) ; #endif ii++ ; } else { break ; } } if ( prev == -1 ) { for ( I = fch[J] ; I != -1 ; I = sib[I] ) { Inew = roots[I] ; newpar[Inew] = Jnew ; } } else { newpar[prev] = Jnew ; } prev = Jnew ; newnodwghts[Jnew] = size ; nbnd = nbnd - size ; newbndwghts[Jnew] = nbnd ; #if MYDEBUG > 0 fprintf(stdout, "\n new front %d, size %d, bnd %d", Jnew, newnodwghts[Jnew], newbndwghts[Jnew]) ; #endif } roots[J] = Jnew ; } } /* --------------------------- create the new ETree object --------------------------- */ etree2 = ETree_new() ; ETree_init1(etree2, nfront2, nvtx) ; IVcopy(nfront2, etree2->tree->par, newpar) ; Tree_setFchSibRoot(etree2->tree) ; IVcopy(nvtx, IV_entries(etree2->vtxToFrontIV), newmap) ; IVcopy(nfront2, IV_entries(etree2->nodwghtsIV), newnodwghts) ; IVcopy(nfront2, IV_entries(etree2->bndwghtsIV), newbndwghts) ; /* ------------------------ free the working storage ------------------------ */ IVfree(newpar) ; IVfree(roots) ; IVfree(newmap) ; IVfree(newnodwghts) ; IVfree(newbndwghts) ; IVfree(head) ; IVfree(link) ; IVfree(indices) ; return(etree2) ; }
/* -------------------------------------------------------------------- purpose -- merge the front tree allowing at most maxzeros zero entries inside a front return -- IV object that has the old front to new front map created -- 96jun23, cca modified -- 97dec18, cca bug fixed that incorrectly counted the number of zeros in a front -------------------------------------------------------------------- */ ETree * ETree_mergeFrontsAny ( ETree *etree, int maxzeros, IV *nzerosIV ) { ETree *etree2 ; int J, K, nfront, nvtx, nnew ; int *bndwghts, *cost, *fch, *map, *nodwghts, *nzeros, *par, *place, *rep, *sib, *temp ; IV *mapIV ; Tree *tree ; /* --------------- check the input --------------- */ if ( etree == NULL || (nfront = etree->nfront) <= 0 || (nvtx = etree->nvtx) <= 0 ) { fprintf(stderr, "\n fatal error in ETree_mergeFrontsAny(%p,%d)" "\n bad input\n", etree, maxzeros) ; spoolesFatal(); } if ( IV_size(nzerosIV) != nfront ) { fprintf(stderr, "\n fatal error in ETree_mergeFrontsAny(%p,%d,%p)" "\n size(nzerosIV) = %d, nfront = %d\n", etree, maxzeros, nzerosIV, IV_size(nzerosIV), nfront) ; spoolesFatal(); } nzeros = IV_entries(nzerosIV) ; tree = etree->tree ; nodwghts = IVinit(nfront, 0) ; bndwghts = IVinit(nfront, 0) ; par = IVinit(nfront, -1) ; fch = IVinit(nfront, -1) ; sib = IVinit(nfront, -1) ; IVcopy(nfront, par, tree->par) ; IVcopy(nfront, fch, tree->fch) ; IVcopy(nfront, sib, tree->sib) ; IVcopy(nfront, nodwghts, IV_entries(etree->nodwghtsIV)) ; IVcopy(nfront, bndwghts, IV_entries(etree->bndwghtsIV)) ; /* ---------------------- set up working storage ---------------------- */ rep = IVinit(nfront, -1) ; IVramp(nfront, rep, 0, 1) ; cost = IVinit(nfront, 0) ; /* ------------------------------------------ perform a post-order traversal of the tree ------------------------------------------ */ for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { #if MYDEBUG > 0 fprintf(stdout, "\n\n ##### visiting front %d", J) ; fflush(stdout) ; #endif visitAny(J, par, fch, sib, nodwghts, bndwghts, rep, cost, nzeros, maxzeros) ; } #if MYDEBUG > 0 fprintf(stdout, "\n\n whoa, finished") ; fflush(stdout) ; #endif /* ------------------------------------------------- take the map from fronts to representative fronts and make the map from old fronts to new fronts ------------------------------------------------- */ mapIV = IV_new() ; IV_init(mapIV, nfront, NULL) ; map = IV_entries(mapIV) ; place = IVinit(nfront, -1) ; for ( J = 0, nnew = 0 ; J < nfront ; J++ ) { #if MYDEBUG > 0 fprintf(stdout, "\n rep[%d] = %d", J, rep[J]) ; fflush(stdout) ; #endif if ( rep[J] != J ) { K = J ; while ( rep[K] != K ) { #if MYDEBUG > 0 fprintf(stdout, "\n rep[%d] = %d", K, rep[K]) ; fflush(stdout) ; #endif K = rep[K] ; } rep[J] = K ; #if MYDEBUG > 0 fprintf(stdout, "\n setting rep[%d] = %d", J, rep[J]) ; fflush(stdout) ; #endif } else { place[J] = nnew++ ; } } for ( J = 0 ; J < nfront ; J++ ) { K = rep[J] ; map[J] = place[K] ; } /* ------------------------------- get the compressed ETree object ------------------------------- */ etree2 = ETree_compress(etree, mapIV) ; /* ------------------------- remap the nzeros[] vector ------------------------- */ temp = IVinit(nfront, 0) ; IVcopy(nfront, temp, nzeros) ; IV_setSize(nzerosIV, nnew) ; nzeros = IV_entries(nzerosIV) ; for ( J = 0 ; J < nfront ; J++ ) { if ( rep[J] == J ) { nzeros[map[J]] = temp[J] ; } } IVfree(temp) ; /* ------------------------ free the working storage ------------------------ */ IVfree(par) ; IVfree(fch) ; IVfree(sib) ; IVfree(nodwghts) ; IVfree(bndwghts) ; IVfree(rep) ; IVfree(cost) ; IVfree(place) ; IV_free(mapIV) ; return(etree2) ; }
/* ------------------------------------------------------- purpose -- merge the front tree allowing a parent to absorb all children when that creates at most maxzeros zero entries inside a front return -- IV object that has the old front to new front map created -- 98jan29, cca ------------------------------------------------------- */ ETree * ETree_mergeFrontsAll ( ETree *etree, int maxzeros, IV *nzerosIV ) { ETree *etree2 ; int cost, J, Jall, K, KandBnd, nfront, nvtx, nnew ; int *bndwghts, *fch, *map, *nodwghts, *nzeros, *rep, *sib, *temp ; IV *mapIV ; Tree *tree ; /* --------------- check the input --------------- */ if ( etree == NULL || nzerosIV == NULL || (nfront = etree->nfront) <= 0 || (nvtx = etree->nvtx) <= 0 ) { fprintf(stderr, "\n fatal error in ETree_mergeFrontsAll(%p,%d,%p)" "\n bad input\n", etree, maxzeros, nzerosIV) ; if ( etree != NULL ) { fprintf(stderr, "\n nfront = %d, nvtx = %d", etree->nfront, etree->nvtx) ; } spoolesFatal(); } if ( IV_size(nzerosIV) != nfront ) { fprintf(stderr, "\n fatal error in ETree_mergeFrontsAll(%p,%d,%p)" "\n size(nzerosIV) = %d, nfront = %d\n", etree, maxzeros, nzerosIV, IV_size(nzerosIV), nfront) ; spoolesFatal(); } nzeros = IV_entries(nzerosIV) ; /* ---------------------- set up working storage ---------------------- */ tree = etree->tree ; fch = ETree_fch(etree) ; sib = ETree_sib(etree) ; nodwghts = IVinit(nfront, 0) ; IVcopy(nfront, nodwghts, ETree_nodwghts(etree)) ; bndwghts = ETree_bndwghts(etree) ; rep = IVinit(nfront, -1) ; IVramp(nfront, rep, 0, 1) ; /* ------------------------------------------ perform a post-order traversal of the tree ------------------------------------------ */ for ( K = Tree_postOTfirst(tree) ; K != -1 ; K = Tree_postOTnext(tree, K) ) { #if MYDEBUG > 0 fprintf(stdout, "\n\n ##### visiting front %d", K) ; fflush(stdout) ; #endif if ( (J = fch[K]) != -1 ) { KandBnd = nodwghts[K] + bndwghts[K] ; Jall = 0 ; cost = 2*nzeros[K] ; for ( J = fch[K] ; J != -1 ; J = sib[J] ) { Jall += nodwghts[J] ; cost -= nodwghts[J]*nodwghts[J] ; cost += 2*nodwghts[J]*(KandBnd - bndwghts[J]) ; cost += 2*nzeros[J] ; } cost += Jall*Jall ; cost = cost/2 ; #if MYDEBUG > 0 fprintf(stdout, "\n cost = %d", cost) ; fflush(stdout) ; #endif if ( cost <= maxzeros ) { for ( J = fch[K] ; J != -1 ; J = sib[J] ) { #if MYDEBUG > 0 fprintf(stdout, "\n merging %d into %d", J, K) ; fflush(stdout) ; #endif rep[J] = K ; nodwghts[K] += nodwghts[J] ; } nzeros[K] = cost ; } } } #if MYDEBUG > 0 fprintf(stdout, "\n\n whoa, finished") ; fflush(stdout) ; #endif /* ------------------------------------------------- take the map from fronts to representative fronts and make the map from old fronts to new fronts ------------------------------------------------- */ mapIV = IV_new() ; IV_init(mapIV, nfront, NULL) ; map = IV_entries(mapIV) ; for ( J = 0, nnew = 0 ; J < nfront ; J++ ) { if ( rep[J] == J ) { map[J] = nnew++ ; } else { K = J ; while ( rep[K] != K ) { K = rep[K] ; } rep[J] = K ; } } for ( J = 0 ; J < nfront ; J++ ) { if ( (K = rep[J]) != J ) { map[J] = map[K] ; } } /* ------------------------------- get the compressed ETree object ------------------------------- */ etree2 = ETree_compress(etree, mapIV) ; /* ------------------------- remap the nzeros[] vector ------------------------- */ temp = IVinit(nfront, 0) ; IVcopy(nfront, temp, nzeros) ; IV_setSize(nzerosIV, nnew) ; nzeros = IV_entries(nzerosIV) ; for ( J = 0 ; J < nfront ; J++ ) { if ( rep[J] == J ) { nzeros[map[J]] = temp[J] ; } } IVfree(temp) ; /* ------------------------ free the working storage ------------------------ */ IVfree(nodwghts) ; IVfree(rep) ; IV_free(mapIV) ; return(etree2) ; }
/* ------------------------------------------------ purpose -- to get simple x[] and y[] coordinates for the tree vertices return values -- 1 -- normal return -1 -- tree is NULL -2 -- heightflag is invalid -3 -- coordflag is invalid -4 -- xDV is NULL -5 -- yDV is NULL created -- 99jan07, cca ------------------------------------------------ */ int Tree_getSimpleCoords ( Tree *tree, char heightflag, char coordflag, DV *xDV, DV *yDV ) { double *x, *y ; int count, I, J, n, nleaves ; int *fch, *par, *sib ; /* --------------- check the input --------------- */ if ( tree == NULL ) { fprintf(stderr, "\n error in Tree_getSimpleCoords()" "\n tree is NULL\n") ; return(-1) ; } if ( heightflag != 'D' && heightflag != 'H' ) { fprintf(stderr, "\n error in Tree_getSimpleCoords()" "\n invalid heightflag = %c\n", heightflag) ; return(-2) ; } if ( coordflag != 'C' && coordflag != 'P' ) { fprintf(stderr, "\n error in Tree_getSimpleCoords()" "\n invalid coordflag = %c\n", coordflag) ; return(-3) ; } if ( xDV == NULL ) { fprintf(stderr, "\n error in Tree_getSimpleCoords()" "\n xDV is NULL\n") ; return(-4) ; } if ( yDV == NULL ) { fprintf(stderr, "\n error in Tree_getSimpleCoords()" "\n yDV is NULL\n") ; return(-5) ; } n = tree->n ; par = tree->par ; fch = tree->fch ; sib = tree->sib ; DV_setSize(xDV, n) ; DV_setSize(yDV, n) ; x = DV_entries(xDV) ; y = DV_entries(yDV) ; switch ( heightflag ) { case 'D' : { int J, K, maxdepth ; for ( J = Tree_preOTfirst(tree), maxdepth = 0 ; J != -1 ; J = Tree_preOTnext(tree, J) ) { if ( (K = par[J]) == -1 ) { y[J] = 0.0 ; } else { y[J] = y[K] + 1.0 ; } if ( maxdepth < y[J] ) { maxdepth = y[J] ; } } if ( coordflag == 'C' ) { for ( J = 0 ; J < n ; J++ ) { y[J] = maxdepth - y[J] ; } } } break ; case 'H' : { int height, I, J, maxheight ; for ( J = Tree_postOTfirst(tree), maxheight = 0 ; J != -1 ; J = Tree_postOTnext(tree, J) ) { if ( (I = fch[J]) == -1 ) { y[J] = 0.0 ; } else { height = y[I] ; for ( I = sib[I] ; I != -1 ; I = sib[I] ) { if ( height < y[I] ) { height = y[I] ; } } y[J] = height + 1.0 ; } if ( maxheight < y[J] ) { maxheight = y[J] ; } } if ( coordflag == 'P' ) { for ( J = 0 ; J < n ; J++ ) { y[J] = maxheight - y[J] ; } } } break ; default : break ; } #if MYDEBUG > 0 fprintf(stdout, "\n\n y") ; DV_writeForHumanEye(yDV, stdout) ; #endif DV_zero(xDV) ; nleaves = 0 ; for ( J = Tree_postOTfirst(tree) ; J != -1 ; J = Tree_postOTnext(tree, J) ) { if ( fch[J] == -1 ) { x[J] = nleaves++ ; } else { for ( I = fch[J], count = 0 ; I != -1 ; I = sib[I] ) { x[J] += x[I] ; count++ ; } x[J] /= count ; } } if ( coordflag == 'C' ) { for ( J = 0 ; J < n ; J++ ) { x[J] = x[J] / nleaves ; } } else { double r, theta ; for ( J = 0 ; J < n ; J++ ) { theta = 6.283185 * x[J] / nleaves ; r = y[J] ; x[J] = r * cos(theta) ; y[J] = r * sin(theta) ; } } #if MYDEBUG > 0 fprintf(stdout, "\n\n x") ; DV_writeForHumanEye(xDV, stdout) ; #endif return(1) ; }
/*--------------------------------------------------------------------*/ 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) ; }