/* ------------------------------------------------------------ create and return an ETree object that holds the front tree. created -- 96jun23, cca ------------------------------------------------------------ */ ETree * MSMD_frontETree ( MSMD *msmd ) { ETree *etree ; int front, iv, nfront, nvtx, root ; int *bndwghts, *fch, *nodwghts, *par, *sib, *vtxToFront ; MSMDvtx *v, *w ; /* --------------- check the input --------------- */ if ( msmd == NULL ) { fprintf(stderr, "\n fatal error in MSMD_frontETree(%p)" "\n bad input\n", msmd) ; exit(-1) ; } nvtx = msmd->nvtx ; /* -------------------------- count the number of fronts -------------------------- */ nfront = 0 ; fch = IVinit(nvtx, -1) ; sib = IVinit(nvtx, -1) ; root = -1 ; for ( iv = 0, v = msmd->vertices ; iv < nvtx ; iv++, v++ ) { #if MYDEBUG > 0 fprintf(stdout, "\n vertex %d, status %c, wght %d", v->id, v->status, v->wght) ; /* MSMDvtx_print(v, stdout) ; */ fflush(stdout) ; #endif switch ( v->status ) { case 'L' : case 'E' : if ( (w = v->par) != NULL ) { sib[v->id] = fch[w->id] ; fch[w->id] = v->id ; } else { sib[v->id] = root ; root = v->id ; } #if MYDEBUG > 0 fprintf(stdout, ", new front %d", nfront) ; fflush(stdout) ; #endif nfront++ ; break ; default : break ; } } #if MYDEBUG > 0 fprintf(stdout, "\n %d fronts", nfront) ; fflush(stdout) ; #endif /* --------------------------- initialize the ETree object --------------------------- */ etree = ETree_new() ; ETree_init1(etree, nfront, nvtx) ; nodwghts = IV_entries(etree->nodwghtsIV) ; bndwghts = IV_entries(etree->bndwghtsIV) ; vtxToFront = IV_entries(etree->vtxToFrontIV) ; /* ---------------------------------------------- fill the vtxToFront[] vector so representative vertices are mapped in a post-order traversal ---------------------------------------------- */ nfront = 0 ; iv = root ; while ( iv != -1 ) { while ( fch[iv] != -1 ) { iv = fch[iv] ; } v = msmd->vertices + iv ; vtxToFront[iv] = nfront++ ; #if MYDEBUG > 0 fprintf(stdout, "\n v = %d, vwght = %d, vtxToFront[%d] = %d", v->id, v->wght, iv, vtxToFront[iv]) ; fflush(stdout) ; #endif while ( sib[iv] == -1 && v->par != NULL ) { v = v->par ; iv = v->id ; vtxToFront[iv] = nfront++ ; #if MYDEBUG > 0 fprintf(stdout, "\n v = %d, vwght = %d, vtxToFront[%d] = %d", v->id, v->wght, iv, vtxToFront[iv]) ; fflush(stdout) ; #endif } iv = sib[iv] ; } IVfree(fch) ; IVfree(sib) ; /* -------------------------------------------------------------- fill in the vertex-to-front map for indistinguishable vertices -------------------------------------------------------------- */ for ( iv = 0, v = msmd->vertices ; iv < nvtx ; iv++, v++ ) { #if MYDEBUG > 0 fprintf(stdout, "\n v %d, wght = %d, status %c", v->id, v->wght, v->status) ; fflush(stdout) ; #endif switch ( v->status ) { case 'I' : #if MYDEBUG > 0 fprintf(stdout, "\n I : v %d", v->id) ; fflush(stdout) ; #endif w = v ; while ( w->par != NULL && w->status == 'I' ) { w = w->par ; #if MYDEBUG > 0 /* fprintf(stdout, " --> %d", w->id) ; */ fprintf(stdout, " %d", w->id) ; fflush(stdout) ; #endif } #if MYDEBUG > 0 fprintf(stdout, ", w %d, status %c", w->id, w->status) ; fflush(stdout) ; #endif switch ( w->status ) { case 'L' : case 'E' : vtxToFront[v->id] = vtxToFront[w->id] ; #if MYDEBUG > 0 fprintf(stdout, "\n I: vtxToFront[%d] = %d", iv, vtxToFront[iv]) ; fflush(stdout) ; #endif break ; default : #if MYDEBUG > 0 fprintf(stdout, "\n wow, v->rootpar = %d, status %c", w->id, w->status) ; fflush(stdout) ; #endif break ; } } } /* ------------------------------------------------------------ now fill in the parent Tree field, node and boundary weights ------------------------------------------------------------ */ par = etree->tree->par ; for ( iv = 0, v = msmd->vertices ; iv < nvtx ; iv++, v++ ) { #if MYDEBUG > 0 fprintf(stdout, "\n v %d, status %c", v->id, v->status) ; fflush(stdout) ; #endif switch ( v->status ) { case 'L' : case 'E' : front = vtxToFront[iv] ; #if MYDEBUG > 0 fprintf(stdout, ", front %d", front) ; fflush(stdout) ; #endif if ( (w = v->par) != NULL ) { par[vtxToFront[v->id]] = vtxToFront[w->id] ; #if MYDEBUG > 0 fprintf(stdout, ", par[%d] = %d", front, par[front]) ; fflush(stdout) ; #endif } bndwghts[front] = v->bndwght ; nodwghts[front] = v->wght ; break ; default : break ; } } /* ------------------------- set the other tree fields ------------------------- */ Tree_setFchSibRoot(etree->tree) ; return(etree) ; }
/* --------------------------------------------- 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 -- to read an ETree object from a formatted file return value -- 1 if success, 0 if failure created -- 95nov15, cca -------------------------------------------------------- */ int ETree_readFromFormattedFile ( ETree *etree, FILE *fp ) { int rc ; int itemp[2] ; /* --------------- check the input --------------- */ if ( etree == NULL || fp == NULL ) { fprintf(stderr, "\n error in ETree_readFromFormattedFile(%p,%p)" "\n bad input\n", etree, fp) ; return(0) ; } /* --------------------- clear the data fields --------------------- */ ETree_clearData(etree) ; /* --------------------------- initialize the ETree object --------------------------- */ ETree_init1(etree, 0, 0) ; /* ----------------------------- read in the two scalar fields ----------------------------- */ if ( (rc = IVfscanf(fp, 2, itemp)) != 2 ) { fprintf(stderr, "\n error in ETree_readFromFormattedFile(%p,%p)" "\n %d items of %d read\n", etree, fp, rc, 2) ; return(0) ; } etree->nfront = itemp[0] ; etree->nvtx = itemp[1] ; /* ----------------------- read in the Tree object ----------------------- */ Tree_readFromFormattedFile(etree->tree, fp) ; /* ------------------------------ read in the nodwghts IV object ------------------------------ */ IV_readFromFormattedFile(etree->nodwghtsIV, fp) ; /* ------------------------------ read in the bndwghts IV object ------------------------------ */ IV_readFromFormattedFile(etree->bndwghtsIV, fp) ; /* -------------------------------- read in the vtxToFront IV object -------------------------------- */ IV_readFromFormattedFile(etree->vtxToFrontIV, fp) ; return(1) ; }
/* ----------------------------------------------------------- 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) ; }
/* ------------------------------------------------- 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) ; }