/*--------------------------------------------------------------------*/ int InpMtx_createGraph (InpMtx *mtxA, Graph *graph) /* ---------------------------------------------------- read in a InpMtx object and create the Graph object created -- 97feb14, cca ---------------------------------------------------- */ { int count, msglvl, nvtx, rc ; IVL *adjIVL ; InpMtx_changeStorageMode(mtxA, 3) ; nvtx = 1 + IV_max(&mtxA->ivec1IV) ; count = 1 + IV_max(&mtxA->ivec2IV) ; if ( nvtx < count ) { nvtx = count ; } /* ------------------------------------ create the full adjacency IVL object ------------------------------------ */ adjIVL = InpMtx_fullAdjacency(mtxA) ; /* --------------------- fill the Graph object --------------------- */ Graph_init2(graph, 0, nvtx, 0, adjIVL->tsize, nvtx, adjIVL->tsize, adjIVL, NULL, NULL) ; return(1) ; }
/* --------------------------------------------------------- set the compids[] vector using a global map from vertices to domains and interface nodes. DDmapIV -- IV object that contains the map from vertices to domains and interface nodes created -- 96mar17, cca --------------------------------------------------------- */ void GPart_DDviaProjection ( GPart *gpart, IV *DDmapIV ) { int *compids, *domainMap, *map, *vtxMap ; int dom, domloc, ndom, ndomloc, nvtx, vglob, vloc ; /* --------------- check the input --------------- */ if ( gpart == NULL || DDmapIV == NULL ) { fprintf(stderr, "\n fatal error in GPart_DDviaProjection(%p,%p)" "\n bad input\n", gpart, DDmapIV) ; exit(-1) ; } nvtx = gpart->nvtx ; compids = IV_entries(&gpart->compidsIV) ; /* -------------------------- find the number of domains -------------------------- */ vtxMap = IV_entries(&gpart->vtxMapIV) ; map = IV_entries(DDmapIV) ; ndom = IV_max(DDmapIV) ; /* ------------------------ check for a quick return ------------------------ */ if ( gpart->par == NULL ) { IVcopy(nvtx, compids, map) ; gpart->ncomp = ndom ; return ; } /* ---------------------------------------- fill compids[] with the local domain ids ---------------------------------------- */ domainMap = IVinit(ndom+1, -1) ; ndomloc = 0 ; for ( vloc = 0 ; vloc < nvtx ; vloc++ ) { vglob = vtxMap[vloc] ; if ( (dom = map[vglob]) > 0 ) { if ( (domloc = domainMap[dom]) == -1 ) { domloc = domainMap[dom] = ++ndomloc ; } compids[vloc] = domloc ; } else { compids[vloc] = 0 ; } } gpart->ncomp = ndomloc ; IVfree(domainMap) ; return ; }
/*--------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) /* ---------------------------------------------------- read in a InpMtx object and create the Graph object created -- 97feb14, cca ---------------------------------------------------- */ { InpMtx *inpmtx ; FILE *msgFile ; Graph *graph ; int count, msglvl, nvtx, rc ; IVL *adjIVL ; if ( argc != 5 ) { fprintf(stdout, "\n\n usage : %s msglvl msgFile inFile outFile" "\n msglvl -- message level" "\n msgFile -- message file" "\n inFile -- input file, must be *.inpmtxf or *.inpmtxb" "\n outFile -- output file, must be *.graphf or *.graphb" "\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) ; } fprintf(msgFile, "\n %s " "\n msglvl -- %d" "\n msgFile -- %s" "\n inFile -- %s" "\n outFile -- %s" "\n", argv[0], msglvl, argv[2], argv[3], argv[4]) ; fflush(msgFile) ; /* -------------------------- read in the InpMtx object -------------------------- */ inpmtx = InpMtx_new() ; if ( strcmp(argv[3], "none") == 0 ) { fprintf(msgFile, "\n no file to read from") ; exit(0) ; } rc = InpMtx_readFromFile(inpmtx, argv[3]) ; fprintf(msgFile, "\n return value %d from InpMtx_readFromFile(%p,%s)", rc, inpmtx, argv[3]) ; if ( rc != 1 ) { exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n after reading InpMtx object from file %s", argv[3]) ; InpMtx_writeForHumanEye(inpmtx, msgFile) ; fflush(msgFile) ; } InpMtx_changeStorageMode(inpmtx, 3) ; nvtx = 1 + IV_max(&inpmtx->ivec1IV) ; count = 1 + IV_max(&inpmtx->ivec2IV) ; if ( nvtx < count ) { nvtx = count ; } /* ------------------------------------ create the full adjacency IVL object ------------------------------------ */ adjIVL = InpMtx_fullAdjacency(inpmtx) ; /* --------------------- fill the Graph object --------------------- */ graph = Graph_new() ; Graph_init2(graph, 0, nvtx, 0, adjIVL->tsize, nvtx, adjIVL->tsize, adjIVL, NULL, NULL) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n Graph object") ; Graph_writeForHumanEye(graph, msgFile) ; fflush(msgFile) ; } /* --------------------------------- check that the graph is symmetric --------------------------------- */ if ( (rc = Graph_isSymmetric(graph)) == 1 ) { fprintf(msgFile, "\n\n graph is symmetric\n") ; } else { fprintf(msgFile, "\n\n graph is not symmetric\n") ; } /* --------------------------- write out the Graph object --------------------------- */ if ( strcmp(argv[4], "none") != 0 ) { rc = Graph_writeToFile(graph, argv[4]) ; fprintf(msgFile, "\n return value %d from Graph_writeToFile(%p,%s)", rc, graph, argv[4]) ; } /* ------------------------ free the working storage ------------------------ */ Graph_free(graph) ; InpMtx_free(inpmtx) ; fprintf(msgFile, "\n") ; fclose(msgFile) ; return(1) ; }
/* ------------------------------------------------------------------ purpose -- return an ETree object for a nested dissection ordering graph -- graph to order maxdomainsize -- used to control the incomplete nested dissection process. any subgraph whose weight is less than maxdomainsize is not split further. seed -- random number seed msglvl -- message level, 0 --> no output, 1 --> timings msgFile -- message file created -- 97nov06, cca ------------------------------------------------------------------ */ ETree * orderViaND ( Graph *graph, int maxdomainsize, int seed, int msglvl, FILE *msgFile ) { double t1, t2 ; DSTree *dstree ; ETree *etree ; int nvtx, Nvtx ; IV *eqmapIV, *stagesIV ; /* --------------- check the input --------------- */ if ( graph == NULL || maxdomainsize <= 0 || (msglvl > 0 && msgFile == NULL) ) { fprintf(stderr, "\n fatal error in orderViaND(%p,%d,%d,%d,%p)" "\n bad input\n", graph, maxdomainsize, seed, msglvl, msgFile) ; exit(-1) ; } /* ------------------------------ compress the graph if worth it ------------------------------ */ nvtx = graph->nvtx ; MARKTIME(t1) ; eqmapIV = Graph_equivMap(graph) ; MARKTIME(t2) ; if ( msglvl > 0 ) { fprintf(msgFile, "\n CPU %8.3f : get equivalence map", t2 - t1) ; fflush(msgFile) ; } Nvtx = 1 + IV_max(eqmapIV) ; if ( Nvtx <= COMPRESS_FRACTION * nvtx ) { MARKTIME(t1) ; graph = Graph_compress2(graph, eqmapIV, 1) ; MARKTIME(t2) ; if ( msglvl > 0 ) { fprintf(msgFile, "\n CPU %8.3f : compress graph", t2 - t1) ; fflush(msgFile) ; } } else { IV_free(eqmapIV) ; eqmapIV = NULL ; } MARKTIME(t1) ; IVL_sortUp(graph->adjIVL) ; MARKTIME(t2) ; if ( msglvl > 0 ) { fprintf(msgFile, "\n CPU %8.3f : sort adjacency", t2 - t1) ; fflush(msgFile) ; } /* ----------------------------- get the domain separator tree ----------------------------- */ { GPart *gpart ; DDsepInfo *info ; info = DDsepInfo_new() ; info->seed = seed ; info->maxcompweight = maxdomainsize ; info->alpha = 0.1 ; gpart = GPart_new() ; GPart_init(gpart, graph) ; GPart_setMessageInfo(gpart, msglvl, msgFile) ; dstree = GPart_RBviaDDsep(gpart, info) ; DSTree_renumberViaPostOT(dstree) ; if ( msglvl > 0 ) { DDsepInfo_writeCpuTimes(info, msgFile) ; } DDsepInfo_free(info) ; GPart_free(gpart) ; } /* --------------------- get the stages vector --------------------- */ stagesIV = DSTree_NDstages(dstree) ; DSTree_free(dstree) ; /* --------------------------------------------- order the vertices and extract the front tree --------------------------------------------- */ { MSMDinfo *info ; MSMD *msmd ; info = MSMDinfo_new() ; info->seed = seed ; info->compressFlag = 2 ; info->msglvl = msglvl ; info->msgFile = msgFile ; msmd = MSMD_new() ; MSMD_order(msmd, graph, IV_entries(stagesIV), info) ; etree = MSMD_frontETree(msmd) ; if ( msglvl > 0 ) { MSMDinfo_print(info, msgFile) ; } MSMDinfo_free(info) ; MSMD_free(msmd) ; IV_free(stagesIV) ; } /* ------------------------------------------------- expand the front tree if the graph was compressed ------------------------------------------------- */ if ( eqmapIV != NULL ) { ETree *etree2 = ETree_expand(etree, eqmapIV) ; ETree_free(etree) ; etree = etree2 ; Graph_free(graph) ; IV_free(eqmapIV) ; } else { MARKTIME(t1) ; IVL_sortUp(graph->adjIVL) ; MARKTIME(t2) ; if ( msglvl > 0 ) { fprintf(msgFile, "\n CPU %8.3f : sort adjacency", t2 - t1) ; fflush(msgFile) ; } } return(etree) ; }
/* ------------------------------------------------------------ purpose -- compute a QR factorization using multiple threads created -- 98may29, cca ------------------------------------------------------------ */ void FrontMtx_MT_QR_factor ( FrontMtx *frontmtx, InpMtx *mtxA, ChvManager *chvmanager, IV *ownersIV, double cpus[], double *pfacops, int msglvl, FILE *msgFile ) { ChvList *updlist ; double t0, t1 ; IVL *rowsIVL ; int ithread, myid, nthread, rc ; int *firstnz ; QR_factorData *data, *dataObjects ; /* --------------- check the input --------------- */ if ( frontmtx == NULL || mtxA == NULL || chvmanager == NULL || ownersIV == NULL || cpus == NULL || pfacops == NULL || (msglvl > 0 && msgFile == NULL) ) { fprintf(stderr, "\n fatal error in FrontMtx_MT_QR_factor()" "\n bad input\n") ; exit(-1) ; } nthread = 1 + IV_max(ownersIV) ; /* ---------------------------------------------------------------- create the update Chv list object create the rowsIVL object, where list(J) = list of rows that are assembled in front J firstnz[irowA] = first column with nonzero element in A(irowA,*) ---------------------------------------------------------------- */ MARKTIME(t0) ; updlist = FrontMtx_postList(frontmtx, ownersIV, LOCK_IN_PROCESS) ; FrontMtx_QR_setup(frontmtx, mtxA, &rowsIVL, &firstnz, msglvl, msgFile) ; MARKTIME(t1) ; cpus[0] = t1 - t0 ; /* ------------------------------------ create and load nthread data objects ------------------------------------ */ ALLOCATE(dataObjects, struct _QR_factorData, nthread) ; for ( myid = 0, data = dataObjects ; myid < nthread ; myid++, data++ ) { data->mtxA = mtxA ; data->rowsIVL = rowsIVL ; data->firstnz = firstnz ; data->ownersIV = ownersIV ; data->frontmtx = frontmtx ; data->chvmanager = chvmanager ; data->updlist = updlist ; data->myid = myid ; DVzero(7, data->cpus) ; data->facops = 0.0 ; data->msglvl = msglvl ; if ( msglvl > 0 ) { char buffer[20] ; sprintf(buffer, "res.%d", myid) ; if ( (data->msgFile = fopen(buffer, "w")) == NULL ) { fprintf(stderr, "\n fatal error in FrontMtx_MT_QR_factor()" "\n unable to open file %s", buffer) ; exit(-1) ; } } else { data->msgFile = NULL ; } } #if THREAD_TYPE == TT_SOLARIS /* ---------------------------------- Solaris threads. (1) set the concurrency (2) create nthread - 1 new threads (3) execute own thread (4) join the threads ---------------------------------- */ thr_setconcurrency(nthread) ; for ( myid = 0, data = dataObjects ; myid < nthread - 1 ; myid++, data++ ) { rc = thr_create(NULL, 0, FrontMtx_QR_workerFactor, data, 0, NULL) ; if ( rc != 0 ) { fprintf(stderr, "\n fatal error, myid = %d, rc = %d from thr_create()", myid, rc) ; exit(-1) ; } } FrontMtx_QR_workerFactor(data) ; for ( myid = 0 ; myid < nthread - 1 ; myid++ ) { thr_join(0, 0, 0) ; } #endif #if THREAD_TYPE == TT_POSIX /* ---------------------------------- POSIX threads. (1) if SGI, set the concurrency (2) create nthread new threads (3) join the threads ---------------------------------- */ { pthread_t *tids ; pthread_attr_t attr ; void *status ; /* --------------------------------------------------------- #### NOTE: for SGI machines, this command must be present #### for the thread scheduling to be efficient. #### this is NOT a POSIX call, but necessary --------------------------------------------------------- pthread_setconcurrency(nthread) ; */ pthread_attr_init(&attr) ; /* pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) ; */ pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS) ; ALLOCATE(tids, pthread_t, nthread) ; for ( myid = 0 ; myid < nthread ; myid++ ) { #ifdef _MSC_VER tids[myid].p = 0; tids[myid].x = 0; #else tids[myid] = 0 ; #endif } for ( myid = 0, data = dataObjects ; myid < nthread ; myid++, data++ ) { rc = pthread_create(&tids[myid], &attr, FrontMtx_QR_workerFactor, data) ; if ( rc != 0 ) { fprintf(stderr, "\n fatal error in FrontMtx_MT_QR_factor()" "\n myid = %d, rc = %d from pthread_create()", myid, rc) ; exit(-1) ; } else if ( msglvl > 2 ) { fprintf(stderr, "\n thread %d created", myid) ; } } for ( myid = 0 ; myid < nthread ; myid++ ) { pthread_join(tids[myid], &status) ; } FREE(tids) ; pthread_attr_destroy(&attr) ; } #endif /* ---------------------------------------------- fill the cpu vector and factor operation count ---------------------------------------------- */ *pfacops = 0 ; for ( myid = 0, data = dataObjects ; myid < nthread ; myid++, data++ ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n thread %d cpus", myid) ; DVfprintf(msgFile, 7, data->cpus) ; } for ( ithread = 0 ; ithread < 7 ; ithread++ ) { cpus[ithread] += data->cpus[ithread] ; } *pfacops += data->facops ; } /* ------------- free the data ------------- */ ChvList_free(updlist) ; IVL_free(rowsIVL) ; IVfree(firstnz) ; FREE(dataObjects) ; return ; }
/* ----------------------------------------------------------------- compress a tree based on a map from old vertices to new vertices. the restriction on the map is that the set {u | map[u] = U} must be connected for all U. created -- 95nov15, cca modified -- 96jan04, cca bug fixed, N computed incorrectly modified -- 96jun23, cca in calling sequence, int map[] converted to IV *mapIV ----------------------------------------------------------------- */ Tree * Tree_compress ( Tree *tree, IV *mapIV ) { int n, N, u, U, v, V ; int *head, *link, *map ; Tree *tree2 ; /* --------------- check the input --------------- */ if ( tree == NULL || (n = tree->n) <= 0 || mapIV == NULL || n != IV_size(mapIV) || (map = IV_entries(mapIV)) == NULL ) { fprintf(stderr, "\n fatal error in Tree_compress(%p,%p)" "\n bad input\n", tree, mapIV) ; exit(-1) ; } /* ----------------------- initialize the new tree ----------------------- */ N = 1 + IV_max(mapIV) ; tree2 = Tree_new() ; Tree_init1(tree2, N) ; /* ----------------------------------------------------------- get the head/link construct to map old nodes into new nodes ----------------------------------------------------------- */ head = IVinit(N, -1) ; link = IVinit(n, -1) ; for ( v = 0 ; v < n ; v++ ) { if ( (V = map[v]) < 0 || V >= N ) { fprintf(stderr, "\n fatal error in Tree_compress(%p,%p)" "\n map[%d] = %d, N = %d\n", tree, map, v, V, N) ; exit(-1) ; } link[v] = head[V] ; head[V] = v ; } /* --------------------- fill the tree vectors --------------------- */ for ( U = 0 ; U < N ; U++ ) { for ( u = head[U] ; u != -1 ; u = link[u] ) { if ( (v = tree->par[u]) == -1 ) { tree2->par[U] = -1 ; break ; } else if ( (V = map[v]) != U ) { tree2->par[U] = V ; break ; } } } Tree_setFchSibRoot(tree2) ; /* ------------------------ free the working storage ------------------------ */ IVfree(head) ; IVfree(link) ; return(tree2) ; }
/* -------------------------------------------------------- purpose -- return an ETree object for a multiple minimum degree ordering graph -- graph to order seed -- random number seed msglvl -- message level, 0 --> no output, 1 --> timings msgFile -- message file created -- 97nov08, cca -------------------------------------------------------- */ ETree * orderViaMMD ( Graph *graph, int seed, int msglvl, FILE *msgFile ) { double t1, t2 ; ETree *etree ; int nvtx, Nvtx ; IV *eqmapIV ; /* --------------- check the input --------------- */ if ( graph == NULL || (msglvl > 0 && msgFile == NULL) ) { fprintf(stderr, "\n fatal error in orderViaMMD(%p,%d,%d,%p)" "\n bad input\n", graph, seed, msglvl, msgFile) ; exit(-1) ; } /* ------------------------------ compress the graph if worth it ------------------------------ */ nvtx = graph->nvtx ; MARKTIME(t1) ; eqmapIV = Graph_equivMap(graph) ; MARKTIME(t2) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : get equivalence map", t2 - t1) ; fflush(msgFile) ; } Nvtx = 1 + IV_max(eqmapIV) ; if ( Nvtx <= COMPRESS_FRACTION * nvtx ) { MARKTIME(t1) ; graph = Graph_compress2(graph, eqmapIV, 1) ; MARKTIME(t2) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : compress graph", t2 - t1) ; fflush(msgFile) ; } } else { IV_free(eqmapIV) ; eqmapIV = NULL ; } MARKTIME(t1) ; IVL_sortUp(graph->adjIVL) ; MARKTIME(t2) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : sort adjacency", t2 - t1) ; fflush(msgFile) ; } /* --------------------------------------------- order the vertices and extract the front tree --------------------------------------------- */ { MSMDinfo *info ; MSMD *msmd ; info = MSMDinfo_new() ; info->seed = seed ; info->compressFlag = 2 ; info->msglvl = msglvl ; info->msgFile = msgFile ; msmd = MSMD_new() ; MSMD_order(msmd, graph, NULL, info) ; etree = MSMD_frontETree(msmd) ; if ( msglvl > 1 ) { MSMDinfo_print(info, msgFile) ; } MSMDinfo_free(info) ; MSMD_free(msmd) ; } /* ------------------------------------------------- expand the front tree if the graph was compressed ------------------------------------------------- */ if ( eqmapIV != NULL ) { ETree *etree2 = ETree_expand(etree, eqmapIV) ; ETree_free(etree) ; etree = etree2 ; Graph_free(graph) ; IV_free(eqmapIV) ; } else { MARKTIME(t1) ; IVL_sortUp(graph->adjIVL) ; MARKTIME(t2) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : sort adjacency", t2 - t1) ; fflush(msgFile) ; } } return(etree) ; }
/* ------------------------------------------------------------------- purpose -- given an InpMtx object that contains the structure of A, initialize the bridge data structure for the serial factor's and solve's. note: all parameters are pointers to be compatible with fortran's call by reference. return value -- 1 -- normal return -1 -- bridge is NULL -2 -- mtxA is NULL created -- 98sep17, cca ------------------------------------------------------------------- */ int BridgeMT_setup ( BridgeMT *bridge, InpMtx *mtxA ) { double t0, t1, t2 ; ETree *frontETree ; FILE *msgFile ; Graph *graph ; int compressed, msglvl, nedges, neqns, Neqns ; IV *eqmapIV ; IVL *adjIVL, *symbfacIVL ; MARKTIME(t0) ; /* -------------------- check the input data -------------------- */ if ( bridge == NULL ) { fprintf(stderr, "\n fatal error in BridgeMT_setup()" "\n data is NULL\n") ; return(-1) ; } if ( mtxA == NULL ) { fprintf(stderr, "\n fatal error in BridgeMT_setup()" "\n A is NULL\n") ; return(-2) ; } msglvl = bridge->msglvl ; msgFile = bridge->msgFile ; neqns = bridge->neqns ; if ( ! (INPMTX_IS_BY_ROWS(mtxA) || INPMTX_IS_BY_COLUMNS(mtxA)) ) { /* ------------------------------ change coordinate type to rows ------------------------------ */ InpMtx_changeCoordType(mtxA, INPMTX_BY_ROWS) ; } if ( ! INPMTX_IS_BY_VECTORS(mtxA) ) { /* ------------------------------ change storage mode to vectors ------------------------------ */ InpMtx_changeStorageMode(mtxA, INPMTX_BY_VECTORS) ; } /* --------------------------- create a Graph object for A --------------------------- */ MARKTIME(t1) ; graph = Graph_new() ; adjIVL = InpMtx_fullAdjacency(mtxA); nedges = bridge->nedges = IVL_tsize(adjIVL), Graph_init2(graph, 0, neqns, 0, nedges, neqns, nedges, adjIVL, NULL, NULL) ; MARKTIME(t2) ; bridge->cpus[0] += t2 - t1 ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : time to create Graph", t2 - t1) ; fflush(msgFile) ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n\n graph of the input matrix") ; Graph_writeForHumanEye(graph, msgFile) ; fflush(msgFile) ; } /* ------------------ compress the graph ------------------ */ MARKTIME(t1) ; eqmapIV = Graph_equivMap(graph) ; Neqns = bridge->Neqns = 1 + IV_max(eqmapIV) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n graph's equivalence map") ; IV_writeForHumanEye(eqmapIV, msgFile) ; fflush(msgFile) ; } if ( Neqns < bridge->compressCutoff * neqns ) { Graph *cgraph ; /* ------------------ compress the graph ------------------ */ cgraph = Graph_compress2(graph, eqmapIV, 1) ; Graph_free(graph) ; graph = cgraph ; compressed = 1 ; bridge->Nedges = graph->nedges ; } else { compressed = 0 ; } MARKTIME(t2) ; bridge->cpus[1] += t2 - t1 ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : time to create compressed graph", t2 - t1) ; fflush(msgFile) ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n\n graph to order") ; Graph_writeForHumanEye(graph, msgFile) ; fflush(msgFile) ; } /* --------------- order the graph --------------- */ MARKTIME(t1) ; if ( bridge->maxdomainsize <= 0 ) { bridge->maxdomainsize = neqns/32 ; } if ( bridge->maxdomainsize <= 0 ) { bridge->maxdomainsize = 1 ; } if ( bridge->maxnzeros < 0 ) { bridge->maxnzeros = 0.01*neqns ; } if ( bridge->maxsize < 0 ) { bridge->maxsize = neqns ; } frontETree = orderViaBestOfNDandMS(graph, bridge->maxdomainsize, bridge->maxnzeros, bridge->maxsize, bridge->seed, msglvl, msgFile) ; MARKTIME(t2) ; bridge->cpus[2] += t2 - t1 ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : time to order graph", t2 - t1) ; fflush(msgFile) ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n\n front tree from ordering") ; ETree_writeForHumanEye(frontETree, msgFile) ; fflush(msgFile) ; } MARKTIME(t1) ; if ( compressed == 1 ) { ETree *etree ; IVL *tempIVL ; /* ---------------------------------------------------------- compute the symbolic factorization of the compressed graph ---------------------------------------------------------- */ tempIVL = SymbFac_initFromGraph(frontETree, graph) ; /* ------------------------------------------------------- expand the symbolic factorization to the original graph ------------------------------------------------------- */ symbfacIVL = IVL_expand(tempIVL, eqmapIV) ; IVL_free(tempIVL) ; /* --------------------- expand the front tree --------------------- */ etree = ETree_expand(frontETree, eqmapIV) ; ETree_free(frontETree) ; frontETree = etree ; } else { /* -------------------------------------------------------- compute the symbolic factorization of the original graph -------------------------------------------------------- */ symbfacIVL = SymbFac_initFromGraph(frontETree, graph) ; } MARKTIME(t2) ; bridge->frontETree = frontETree ; bridge->symbfacIVL = symbfacIVL ; /* ---------------------------------------------- get the old-to-new and new-to-old permutations ---------------------------------------------- */ bridge->oldToNewIV = ETree_oldToNewVtxPerm(frontETree) ; bridge->newToOldIV = ETree_newToOldVtxPerm(frontETree) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n old-to-new permutation") ; IV_writeForHumanEye(bridge->oldToNewIV, msgFile) ; fprintf(msgFile, "\n\n new-to-old permutation") ; IV_writeForHumanEye(bridge->newToOldIV, msgFile) ; fflush(msgFile) ; } /* ------------------------------------------------------ overwrite the symbolic factorization with the permuted indices and sort the lists into ascending order ------------------------------------------------------ */ IVL_overwrite(symbfacIVL, bridge->oldToNewIV) ; IVL_sortUp(symbfacIVL) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n symbolic factorization") ; IVL_writeForHumanEye(symbfacIVL, msgFile) ; fflush(msgFile) ; } /* -------------------------------------- permute the vertices in the front tree -------------------------------------- */ ETree_permuteVertices(frontETree, bridge->oldToNewIV) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n permuted front etree") ; ETree_writeForHumanEye(frontETree, msgFile) ; fflush(msgFile) ; } MARKTIME(t2) ; bridge->cpus[3] += t2 - t1 ; if ( msglvl > 1 ) { fprintf(msgFile, "\n CPU %8.3f : time for symbolic factorization", t2 - t1) ; fflush(msgFile) ; } /* ------------------------ free the working storage ------------------------ */ Graph_free(graph) ; IV_free(eqmapIV) ; MARKTIME(t2) ; bridge->cpus[4] += t2 - t0 ; return(1) ; }