/* --------------------------------------------------------------- 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 ; }
/*--------------------------------------------------------------------*/ 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 -- to broadcast a front tree object from one process to all the others created -- 98may21, cca --------------------------------------------- */ ETree * ETree_MPI_Bcast ( ETree *etree, int root, int msglvl, FILE *msgFile, MPI_Comm comm ) { int myid, nvtx, nfront, nint ; int *buffer ; /* ------------- find identity ------------- */ MPI_Comm_rank(comm, &myid) ; if ( myid == root ) { /* -------------------------------------------- this process owns the front tree, allocate a continuous buffer and load the data into it. -------------------------------------------- */ nfront = ETree_nfront(etree) ; nvtx = ETree_nvtx(etree) ; nint = 3 + 5*nfront + nvtx ; buffer = IVinit(nint, -1) ; buffer[0] = nfront ; buffer[1] = nvtx ; buffer[2] = ETree_root(etree) ; IVcopy(nfront, buffer + 3, ETree_par(etree)) ; IVcopy(nfront, buffer + 3 + nfront, ETree_fch(etree)) ; IVcopy(nfront, buffer + 3 + 2*nfront, ETree_sib(etree)) ; IVcopy(nfront, buffer + 3 + 3*nfront, ETree_nodwghts(etree)) ; IVcopy(nfront, buffer + 3 + 4*nfront, ETree_bndwghts(etree)) ; IVcopy(nvtx, buffer + 3 + 5*nfront, ETree_vtxToFront(etree)) ; /* ------------------------------------ send the size of the buffer and then the buffer to the other processors ------------------------------------ */ MPI_Bcast(&nint, 1, MPI_INT, root, comm) ; MPI_Bcast(buffer, nint, MPI_INT, root, comm) ; } else { /* -------------------------------------------- this process will receive the front tree. clear its data, receive the number of int's, then receive the buffer -------------------------------------------- */ if ( etree != NULL ) { ETree_free(etree) ; } MPI_Bcast(&nint, 1, MPI_INT, root, comm) ; buffer = IVinit(nint, -1) ; MPI_Bcast(buffer, nint, MPI_INT, root, comm) ; /* ---------------------------------------- create an ETree object and fill its data ---------------------------------------- */ etree = ETree_new() ; nfront = buffer[0] ; nvtx = buffer[1] ; ETree_init1(etree, nfront, nvtx) ; etree->tree->n = nfront ; etree->tree->root = buffer[2] ; IVcopy(nfront, ETree_par(etree), buffer + 3) ; IVcopy(nfront, ETree_fch(etree), buffer + 3 + nfront) ; IVcopy(nfront, ETree_sib(etree), buffer + 3 + 2*nfront) ; IVcopy(nfront, ETree_nodwghts(etree), buffer + 3 + 3*nfront) ; IVcopy(nfront, ETree_bndwghts(etree), buffer + 3 + 4*nfront) ; IVcopy(nvtx, ETree_vtxToFront(etree), buffer + 3 + 5*nfront) ; } /* --------------- free the buffer --------------- */ IVfree(buffer) ; return(etree) ; }
/* -------------------------------------------------------------- purpose -- generate and return some statistics about the factor and solve type -- type of entries SPOOLES_REAL or SPOOLES_COMPLEX symmetryflag -- symmetry type SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC on return --- *pnfront -- # of fronts *pnfactorind -- # of factor indices *pnfactorent -- # of factor entries *pnsolveops -- # of solve operations *pnfactorops -- # of factor operations return values -- 1 -- normal return -1 -- bridge is NULL -2 -- type is bad, must be SPOOLES_REAL or SPOOLES_COMPLEX -3 -- symmetryflag is bad, must be SPOOLES_SYMMETRIC, SPOOLES_HERMITIAN or SPOOLES_NONSYMMETRIC -4 -- type and symmetryflag mismatch -5 -- front tree is not present -6 -- pnfront is NULL -7 -- pnfactorind is NULL -8 -- pnfactorent is NULL -9 -- pnsolveops is NULL -10 -- pnfactorops is NULL created -- 98oct01, cca -------------------------------------------------------------- */ int Bridge_factorStats ( Bridge *bridge, int type, int symmetryflag, int *pnfront, int *pnfactorind, int *pnfactorent, int *pnsolveops, double *pnfactorops ) { ETree *etree ; int nentD, nentU ; /* --------------- check the input --------------- */ if ( bridge == NULL ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n bridge is NULL\n") ; return(-1) ; } switch ( type ) { case SPOOLES_REAL : case SPOOLES_COMPLEX : break ; default : fprintf(stderr, "\n error in Bridge_factorStats()" "\n bad type %d\n", type) ; return(-3) ; break ; } switch ( symmetryflag ) { case SPOOLES_SYMMETRIC : case SPOOLES_HERMITIAN : case SPOOLES_NONSYMMETRIC : break ; default : fprintf(stderr, "\n error in Bridge_factorStats()" "\n bad symmetryflag %d\n", symmetryflag) ; return(-3) ; break ; } if ( type == SPOOLES_REAL && symmetryflag == SPOOLES_HERMITIAN ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n type %d, symmetryflag %d, mismatch\n", type, symmetryflag) ; return(-4) ; } if ( (etree = bridge->frontETree) == NULL ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n front tree is not present\n") ; return(-5) ; } if ( pnfront == NULL ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n pnfront is NULL\n") ; return(-6) ; } if ( pnfactorind == NULL ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n pnfactorind is NULL\n") ; return(-7) ; } if ( pnfactorent == NULL ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n pnfactorent is NULL\n") ; return(-8) ; } if ( pnsolveops == NULL ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n pnsolveops is NULL\n") ; return(-9) ; } if ( pnfactorops == NULL ) { fprintf(stderr, "\n error in Bridge_factorStats()" "\n pnfactorops is NULL\n") ; return(-10) ; } *pnfront = ETree_nfront(etree) ; *pnfactorind = ETree_nFactorIndices(etree) ; *pnfactorent = ETree_nFactorEntries(etree, symmetryflag) ; *pnfactorops = ETree_nFactorOps(etree, type, symmetryflag) ; nentD = etree->nvtx ; nentU = *pnfactorent - nentD ; switch ( type ) { case SPOOLES_REAL : *pnsolveops = 4*nentU + nentD ; break ; case SPOOLES_COMPLEX : *pnsolveops = 16*nentU + 8*nentD ; break ; } return(1) ; }
/* --------------------------------------------------------------- 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 ; }
/* --------------------------------------------------------------- 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 -- to initialize subtree with the subtree of the front tree using nodes in nodeidsIV. vtxIV is filled with the vertices in the subtree return values --- 1 -- normal return -1 -- subtree is NULL -2 -- nodeidsIV is NULL -3 -- etree is NULL -4 -- nodeidsIV is invalid -5 -- vtxIV is NULL created -- 98oct15, cca ----------------------------------------------------------- */ int ETree_initFromSubtree ( ETree *subtree, IV *nodeidsIV, ETree *etree, IV *vtxIV ) { int J, Jsub, nfrontInETree, nfrontInSubtree, nvtxInETree, nvtxInSubtree, v, vSub ; int *bndwghts, *bndwghtsSub, *localmap, *nodwghts, *nodwghtsSub, *subtreeNodes, *vtxInSubtree, *vtxToFront, *vtxToFrontSub ; /* --------------- check the input --------------- */ if ( subtree == NULL ) { fprintf(stderr, "\n\n error in ETree_initFromSubtree()" "\n subtree is NULL\n") ; return(-1) ; } if ( nodeidsIV == NULL ) { fprintf(stderr, "\n\n error in ETree_initFromSubtree()" "\n nodeidsIV is NULL\n") ; return(-2) ; } if ( etree == NULL ) { fprintf(stderr, "\n\n error in ETree_initFromSubtree()" "\n etree is NULL\n") ; return(-3) ; } nfrontInETree = ETree_nfront(etree) ; IV_sizeAndEntries(nodeidsIV, &nfrontInSubtree, &subtreeNodes) ; if ( nfrontInSubtree < 0 || nfrontInSubtree >= nfrontInETree ) { fprintf(stderr, "\n\n error in ETree_initFromSubtree()" "\n nfrontInETree = %d, nfrontInSubtree = %d\n", nfrontInETree, nfrontInSubtree) ; return(-4) ; } for ( Jsub = 0 ; Jsub < nfrontInSubtree ; Jsub++ ) { J = subtreeNodes[Jsub] ; if ( J < 0 || J >= nfrontInETree ) { fprintf(stderr, "\n\n error in ETree_initFromSubtree()" "\n nfrontInETree = %d, subtreeNodes[%d] = %d\n", nfrontInETree, Jsub, subtreeNodes[Jsub]) ; return(-4) ; } } if ( vtxIV == NULL ) { fprintf(stderr, "\n\n error in ETree_initFromSubtree()" "\n vtxIV is NULL\n") ; return(-5) ; } nvtxInETree = ETree_nvtx(etree) ; vtxToFront = ETree_vtxToFront(etree) ; /* ---------------------------- create a global-to-local map ---------------------------- */ localmap = IVinit(nfrontInETree, -1) ; for ( Jsub = 0 ; Jsub < nfrontInSubtree ; Jsub++ ) { J = subtreeNodes[Jsub] ; localmap[J] = Jsub ; } /* --------------------------------------------- compute the number of vertices in the subtree --------------------------------------------- */ nvtxInSubtree = 0 ; for ( v = 0 ; v < nvtxInETree ; v++ ) { J = vtxToFront[v] ; if ( (Jsub = localmap[J]) != -1 ) { nvtxInSubtree++ ; } } /* ---------------------- initialize the subtree ---------------------- */ ETree_init1(subtree, nfrontInSubtree, nvtxInSubtree) ; /* ----------------------------- initialize the subtree's tree ----------------------------- */ Tree_initFromSubtree(subtree->tree, nodeidsIV, etree->tree) ; /* ----------------------------------- set the nodwght and bndwght vectors ----------------------------------- */ nodwghts = ETree_nodwghts(etree) ; bndwghts = ETree_bndwghts(etree) ; nodwghtsSub = ETree_nodwghts(subtree) ; bndwghtsSub = ETree_bndwghts(subtree) ; for ( Jsub = 0 ; Jsub < nfrontInSubtree ; Jsub++ ) { J = subtreeNodes[Jsub] ; nodwghtsSub[Jsub] = nodwghts[J] ; bndwghtsSub[Jsub] = bndwghts[J] ; } /* ------------------------------------- set the subtree's vtxToFront[] vector and fill vtxIV with the vertices ------------------------------------- */ IV_init(vtxIV, nvtxInSubtree, NULL) ; vtxInSubtree = IV_entries(vtxIV) ; vtxToFrontSub = ETree_vtxToFront(subtree) ; for ( v = vSub = 0 ; v < nvtxInETree ; v++ ) { J = vtxToFront[v] ; if ( (Jsub = localmap[J]) != -1 ) { vtxInSubtree[vSub] = v ; vtxToFrontSub[vSub] = Jsub ; vSub++ ; } } /* ------------------------ free the working storage ------------------------ */ IVfree(localmap) ; return(1) ; }
/*--------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) /* --------------------------------------------------------------- read in a ETree object, create an IV object with the same size, mark the vertices in the top level separator(s), write the IV object to a file created -- 96may02, cca --------------------------------------------------------------- */ { char *inETreeFileName, *outIVfileName ; double t1, t2 ; int msglvl, rc, J, K, ncomp, nfront, nvtx, v ; int *bndwghts, *compids, *fch, *map, *nodwghts, *par, *sib, *vtxToFront ; IV *compidsIV, *mapIV ; ETree *etree ; FILE *msgFile ; Tree *tree ; if ( argc != 5 ) { fprintf(stdout, "\n\n usage : %s msglvl msgFile inETreeFile outIVfile" "\n msglvl -- message level" "\n msgFile -- message file" "\n inETreeFile -- input file, must be *.etreef or *.etreeb" "\n outIVfile -- output 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) ; } inETreeFileName = argv[3] ; outIVfileName = argv[4] ; fprintf(msgFile, "\n %s " "\n msglvl -- %d" "\n msgFile -- %s" "\n inETreeFile -- %s" "\n outIVfile -- %s" "\n", argv[0], msglvl, argv[2], inETreeFileName, outIVfileName) ; fflush(msgFile) ; /* ------------------------ read in the ETree object ------------------------ */ if ( strcmp(inETreeFileName, "none") == 0 ) { fprintf(msgFile, "\n no file to read from") ; exit(0) ; } 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) ; exit(-1) ; } 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) ; nvtx = ETree_nvtx(etree) ; bndwghts = ETree_bndwghts(etree) ; vtxToFront = ETree_vtxToFront(etree) ; nodwghts = ETree_nodwghts(etree) ; par = ETree_par(etree) ; fch = ETree_fch(etree) ; sib = ETree_sib(etree) ; tree = ETree_tree(etree) ; /* ----------------------------------------- create the map from fronts to components, top level separator(s) are component zero ----------------------------------------- */ mapIV = IV_new() ; IV_init(mapIV, nfront, NULL) ; map = IV_entries(mapIV) ; ncomp = 0 ; for ( J = Tree_preOTfirst(tree) ; J != -1 ; J = Tree_preOTnext(tree, J) ) { if ( (K = par[J]) == -1 ) { map[J] = 0 ; } else if ( map[K] != 0 ) { map[J] = map[K] ; } else if ( J == fch[K] && sib[J] == -1 && bndwghts[J] == nodwghts[K] + bndwghts[K] ) { map[J] = 0 ; } else { map[J] = ++ncomp ; } } fprintf(msgFile, "\n\n mapIV object") ; if ( msglvl > 2 ) { IV_writeForHumanEye(mapIV, msgFile) ; } else { IV_writeStats(mapIV, msgFile) ; } /* ---------------------------------------- fill the map from vertices to components ---------------------------------------- */ compidsIV = IV_new() ; IV_init(compidsIV, nvtx, NULL) ; compids = IV_entries(compidsIV) ; for ( v = 0 ; v < nvtx ; v++ ) { compids[v] = map[vtxToFront[v]] ; } fprintf(msgFile, "\n\n compidsIV object") ; if ( msglvl > 2 ) { IV_writeForHumanEye(compidsIV, msgFile) ; } else { IV_writeStats(compidsIV, msgFile) ; } fflush(msgFile) ; /* ----------------------- write out the IV object ----------------------- */ if ( strcmp(outIVfileName, "none") != 0 ) { MARKTIME(t1) ; rc = IV_writeToFile(compidsIV, outIVfileName) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %9.5f : write etree to file %s", t2 - t1, outIVfileName) ; } if ( rc != 1 ) { fprintf(msgFile, "\n return value %d from IV_writeToFile(%p,%s)", rc, compidsIV, outIVfileName) ; } /* ---------------- free the objects ---------------- */ ETree_free(etree) ; IV_free(mapIV) ; IV_free(compidsIV) ; fprintf(msgFile, "\n") ; fclose(msgFile) ; return(1) ; }
/*--------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) /* ------------------------------------------------------------ make ETree objects for nested dissection on a regular grid 1 -- vertex elimination tree 2 -- fundamental supernode front tree 3 -- merge only children if possible 4 -- merge all children if possible 5 -- split large non-leaf fronts created -- 98feb05, cca ------------------------------------------------------------ */ { char *outETreeFileName ; double ops[6] ; double t1, t2 ; EGraph *egraph ; ETree *etree0, *etree1, *etree2, *etree3, *etree4, *etree5 ; FILE *msgFile ; Graph *graph ; int nfronts[6], nfind[6], nzf[6] ; int maxsize, maxzeros, msglvl, n1, n2, n3, nvtx, rc, v ; int *newToOld, *oldToNew ; IV *nzerosIV ; if ( argc != 9 ) { fprintf(stdout, "\n\n usage : %s msglvl msgFile n1 n2 n3 maxzeros maxsize outFile" "\n msglvl -- message level" "\n msgFile -- message file" "\n n1 -- number of points in the first direction" "\n n2 -- number of points in the second direction" "\n n3 -- number of points in the third direction" "\n maxzeros -- number of points in the third direction" "\n maxsize -- maximum number of vertices in a front" "\n outFile -- output file, must be *.etreef or *.etreeb" "\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) ; } n1 = atoi(argv[3]) ; n2 = atoi(argv[4]) ; n3 = atoi(argv[5]) ; maxzeros = atoi(argv[6]) ; maxsize = atoi(argv[7]) ; outETreeFileName = argv[8] ; fprintf(msgFile, "\n %s " "\n msglvl -- %d" "\n msgFile -- %s" "\n n1 -- %d" "\n n2 -- %d" "\n n3 -- %d" "\n maxzeros -- %d" "\n maxsize -- %d" "\n outFile -- %s" "\n", argv[0], msglvl, argv[2], n1, n2, n3, maxzeros, maxsize, outETreeFileName) ; fflush(msgFile) ; /* ---------------------------- create the grid graph object ---------------------------- */ if ( n1 == 1 ) { egraph = EGraph_make9P(n2, n3, 1) ; } else if ( n2 == 1 ) { egraph = EGraph_make9P(n1, n3, 1) ; } else if ( n3 == 1 ) { egraph = EGraph_make9P(n1, n2, 1) ; } else { egraph = EGraph_make27P(n1, n2, n3, 1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n %d x %d x %d grid EGraph", n1, n2, n3) ; EGraph_writeForHumanEye(egraph, msgFile) ; fflush(msgFile) ; } graph = EGraph_mkAdjGraph(egraph) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n %d x %d x %d grid Graph", n1, n2, n3) ; Graph_writeForHumanEye(graph, msgFile) ; fflush(msgFile) ; } /* ---------------------------------- get the nested dissection ordering ---------------------------------- */ nvtx = n1*n2*n3 ; newToOld = IVinit(nvtx, -1) ; oldToNew = IVinit(nvtx, -1) ; mkNDperm(n1, n2, n3, newToOld, 0, n1-1, 0, n2-1, 0, n3-1) ; for ( v = 0 ; v < nvtx ; v++ ) { oldToNew[newToOld[v]] = v ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n %d x %d x %d nd ordering", n1, n2, n3) ; IVfprintf(msgFile, nvtx, oldToNew) ; fflush(msgFile) ; } /* ------------------------------------------ create the vertex elimination ETree object ------------------------------------------ */ etree0 = ETree_new() ; ETree_initFromGraphWithPerms(etree0, graph, newToOld, oldToNew) ; nfronts[0] = ETree_nfront(etree0) ; nfind[0] = ETree_nFactorIndices(etree0) ; nzf[0] = ETree_nFactorEntries(etree0, SPOOLES_SYMMETRIC) ; ops[0] = ETree_nFactorOps(etree0, SPOOLES_REAL, SPOOLES_SYMMETRIC) ; fprintf(msgFile, "\n vtx tree : %8d fronts, %8d indices, %8d |L|, %12.0f ops", nfronts[0], nfind[0], nzf[0], ops[0]) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n vertex elimination tree") ; ETree_writeForHumanEye(etree0, msgFile) ; fflush(msgFile) ; } /* --------------------------------------------- create the fundamental supernode ETree object --------------------------------------------- */ nzerosIV = IV_new() ; IV_init(nzerosIV, nvtx, NULL) ; IV_fill(nzerosIV, 0) ; etree1 = ETree_mergeFrontsOne(etree0, 0, nzerosIV) ; nfronts[1] = ETree_nfront(etree1) ; nfind[1] = ETree_nFactorIndices(etree1) ; nzf[1] = ETree_nFactorEntries(etree1, SPOOLES_SYMMETRIC) ; ops[1] = ETree_nFactorOps(etree1, SPOOLES_REAL, SPOOLES_SYMMETRIC) ; fprintf(msgFile, "\n fs tree : %8d fronts, %8d indices, %8d |L|, %12.0f ops", nfronts[1], nfind[1], nzf[1], ops[1]) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n fundamental supernode front tree") ; ETree_writeForHumanEye(etree1, msgFile) ; fprintf(msgFile, "\n\n nzerosIV") ; IV_writeForHumanEye(nzerosIV, msgFile) ; fflush(msgFile) ; } /* --------------------------- try to absorb only children --------------------------- */ etree2 = ETree_mergeFrontsOne(etree1, maxzeros, nzerosIV) ; nfronts[2] = ETree_nfront(etree2) ; nfind[2] = ETree_nFactorIndices(etree2) ; nzf[2] = ETree_nFactorEntries(etree2, SPOOLES_SYMMETRIC) ; ops[2] = ETree_nFactorOps(etree2, SPOOLES_REAL, SPOOLES_SYMMETRIC) ; fprintf(msgFile, "\n merge one : %8d fronts, %8d indices, %8d |L|, %12.0f ops", nfronts[2], nfind[2], nzf[2], ops[2]) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n front tree after mergeOne") ; ETree_writeForHumanEye(etree2, msgFile) ; fprintf(msgFile, "\n\n nzerosIV") ; IV_writeForHumanEye(nzerosIV, msgFile) ; fflush(msgFile) ; } /* -------------------------- try to absorb all children -------------------------- */ etree3 = ETree_mergeFrontsAll(etree2, maxzeros, nzerosIV) ; nfronts[3] = ETree_nfront(etree3) ; nfind[3] = ETree_nFactorIndices(etree3) ; nzf[3] = ETree_nFactorEntries(etree3, SPOOLES_SYMMETRIC) ; ops[3] = ETree_nFactorOps(etree3, SPOOLES_REAL, SPOOLES_SYMMETRIC) ; fprintf(msgFile, "\n merge all : %8d fronts, %8d indices, %8d |L|, %12.0f ops", nfronts[3], nfind[3], nzf[3], ops[3]) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n front tree after mergeAll") ; ETree_writeForHumanEye(etree3, msgFile) ; fprintf(msgFile, "\n\n nzerosIV") ; IV_writeForHumanEye(nzerosIV, msgFile) ; fflush(msgFile) ; } /* -------------------------------- try to absorb any other children -------------------------------- */ etree4 = etree3 ; /* etree4 = ETree_mergeFrontsAny(etree3, maxzeros, nzerosIV) ; nfronts[4] = ETree_nfront(etree4) ; nfind[4] = ETree_nFactorIndices(etree4) ; nzf[4] = ETree_nFactorEntries(etree4, SPOOLES_SYMMETRIC) ; ops[4] = ETree_nFactorOps(etree4, SPOOLES_REAL, SPOOLES_SYMMETRIC) ; fprintf(msgFile, "\n merge any : %8d fronts, %8d indices, %8d |L|, %12.0f ops", nfronts[4], nfind[4], nzf[4], ops[4]) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n front tree after mergeAny") ; ETree_writeForHumanEye(etree3, msgFile) ; fprintf(msgFile, "\n\n nzerosIV") ; IV_writeForHumanEye(nzerosIV, msgFile) ; fflush(msgFile) ; } */ /* -------------------- split the front tree -------------------- */ etree5 = ETree_splitFronts(etree4, NULL, maxsize, 0) ; nfronts[5] = ETree_nfront(etree5) ; nfind[5] = ETree_nFactorIndices(etree5) ; nzf[5] = ETree_nFactorEntries(etree5, SPOOLES_SYMMETRIC) ; ops[5] = ETree_nFactorOps(etree5, SPOOLES_REAL, SPOOLES_SYMMETRIC) ; fprintf(msgFile, "\n split : %8d fronts, %8d indices, %8d |L|, %12.0f ops", nfronts[5], nfind[5], nzf[5], ops[5]) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n front tree after split") ; ETree_writeForHumanEye(etree4, msgFile) ; fflush(msgFile) ; } fprintf(msgFile, "\n\n complex symmetric ops %.0f", ETree_nFactorOps(etree5, SPOOLES_COMPLEX, SPOOLES_SYMMETRIC)) ; /* -------------------------- write out the ETree object -------------------------- */ if ( strcmp(outETreeFileName, "none") != 0 ) { MARKTIME(t1) ; rc = ETree_writeToFile(etree5, outETreeFileName) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %9.5f : write etree to file %s", t2 - t1, outETreeFileName) ; if ( rc != 1 ) { fprintf(msgFile, "\n return value %d from ETree_writeToFile(%p,%s)", rc, etree5, outETreeFileName) ; } } /* ---------------- free the objects ---------------- */ ETree_free(etree0) ; ETree_free(etree1) ; ETree_free(etree2) ; ETree_free(etree3) ; /* ETree_free(etree4) ; */ ETree_free(etree5) ; EGraph_free(egraph) ; Graph_free(graph) ; IVfree(newToOld) ; IVfree(oldToNew) ; IV_free(nzerosIV) ; fprintf(msgFile, "\n") ; fclose(msgFile) ; return(1) ; }
//static void factor_MT(struct factorinfo *pfi, InpMtx *mtxA, int size, FILE *msgFile, int symmetryflag) void factor_MT(struct factorinfo *pfi, InpMtx *mtxA, int size, FILE *msgFile, int symmetryflag) { Graph *graph; IV *ownersIV; IVL *symbfacIVL; Chv *rootchv; /* Initialize pfi: */ pfi->size = size; pfi->msgFile = msgFile; DVfill(10, pfi->cpus, 0.0); /* * STEP 1 : find a low-fill ordering * (1) create the Graph object */ ssolve_creategraph(&graph, &pfi->frontETree, mtxA, size, msgFile); /* * STEP 2: get the permutation, permute the matrix and * front tree and get the symbolic factorization */ ssolve_permuteA(&pfi->oldToNewIV, &pfi->newToOldIV, &symbfacIVL, pfi->frontETree, mtxA, msgFile, symmetryflag); /* * STEP 3: Prepare distribution to multiple threads/cpus */ { DV *cumopsDV; int nfront; nfront = ETree_nfront(pfi->frontETree); pfi->nthread = num_cpus; if (pfi->nthread > nfront) pfi->nthread = nfront; cumopsDV = DV_new(); DV_init(cumopsDV, pfi->nthread, NULL); ownersIV = ETree_ddMap(pfi->frontETree, SPOOLES_REAL, symmetryflag, cumopsDV, 1. / (2. * pfi->nthread)); if (DEBUG_LVL > 1) { fprintf(msgFile, "\n\n map from fronts to threads"); IV_writeForHumanEye(ownersIV, msgFile); fprintf(msgFile, "\n\n factor operations for each front"); DV_writeForHumanEye(cumopsDV, msgFile); fflush(msgFile); } else { fprintf(msgFile, "\n\n Using %d threads\n", pfi->nthread); } DV_free(cumopsDV); } /* * STEP 4: initialize the front matrix object */ { pfi->frontmtx = FrontMtx_new(); pfi->mtxmanager = SubMtxManager_new(); SubMtxManager_init(pfi->mtxmanager, LOCK_IN_PROCESS, 0); FrontMtx_init(pfi->frontmtx, pfi->frontETree, symbfacIVL, SPOOLES_REAL, symmetryflag, FRONTMTX_DENSE_FRONTS, SPOOLES_PIVOTING, LOCK_IN_PROCESS, 0, NULL, pfi->mtxmanager, DEBUG_LVL, pfi->msgFile); } /* * STEP 5: compute the numeric factorization in parallel */ { ChvManager *chvmanager; int stats[20]; int error; chvmanager = ChvManager_new(); ChvManager_init(chvmanager, LOCK_IN_PROCESS, 1); IVfill(20, stats, 0); rootchv = FrontMtx_MT_factorInpMtx(pfi->frontmtx, mtxA, MAGIC_TAU, MAGIC_DTOL, chvmanager, ownersIV, 0, &error, pfi->cpus, stats, DEBUG_LVL, pfi->msgFile); ChvManager_free(chvmanager); if (DEBUG_LVL > 1) { fprintf(msgFile, "\n\n factor matrix"); FrontMtx_writeForHumanEye(pfi->frontmtx, pfi->msgFile); fflush(pfi->msgFile); } if (rootchv != NULL) { fprintf(pfi->msgFile, "\n\n matrix found to be singular\n"); exit(-1); } if (error >= 0) { fprintf(pfi->msgFile, "\n\n fatal error at front %d", error); exit(-1); } } /* * STEP 6: post-process the factorization */ ssolve_postfactor(pfi->frontmtx, pfi->msgFile); /* * STEP 7: get the solve map object for the parallel solve */ { pfi->solvemap = SolveMap_new(); SolveMap_ddMap(pfi->solvemap, symmetryflag, FrontMtx_upperBlockIVL(pfi->frontmtx), FrontMtx_lowerBlockIVL(pfi->frontmtx), pfi->nthread, ownersIV, FrontMtx_frontTree(pfi->frontmtx), RNDSEED, DEBUG_LVL, pfi->msgFile); } /* cleanup: */ InpMtx_free(mtxA); IVL_free(symbfacIVL); Graph_free(graph); IV_free(ownersIV); }
/*--------------------------------------------------------------------*/ 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) ; }