/* ------------------------------------------- fill *pnrow with the number of rows and *prowind with a pointer to the rows indices created -- 98may04, cca ------------------------------------------- */ void FrontMtx_rowIndices ( FrontMtx *frontmtx, int J, int *pnrow, int **prowind ) { /* --------------- check the input --------------- */ if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront || pnrow == NULL || prowind == NULL ) { fprintf(stderr, "\n fatal error in FrontMtx_rowIndices(%p,%d,%p,%p)" "\n bad input\n", frontmtx, J, pnrow, prowind) ; spoolesFatal(); } if ( ! FRONTMTX_IS_PIVOTING(frontmtx) ) { IVL_listAndSize(frontmtx->symbfacIVL, J, pnrow, prowind) ; } else if ( FRONTMTX_IS_SYMMETRIC(frontmtx) || FRONTMTX_IS_HERMITIAN(frontmtx) ) { IVL_listAndSize(frontmtx->coladjIVL, J, pnrow, prowind) ; } else if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { IVL_listAndSize(frontmtx->rowadjIVL, J, pnrow, prowind) ; } return ; }
/* -------------------------------------------------- purpose -- fill *pnadj with the number of fronts K such that L_{K,J} != 0 and *padj with a pointer to a list of those fronts created -- 98may04, cca -------------------------------------------------- */ void FrontMtx_lowerAdjFronts ( FrontMtx *frontmtx, int J, int *pnadj, int **padj ) { /* --------------- check the input --------------- */ if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront || pnadj == NULL || padj == NULL ) { fprintf(stderr, "\n fatal error in FrontMtx_lowerAdjFronts(%p,%d,%p,%p)" "\n bad input\n", frontmtx, J, pnadj, padj) ; spoolesFatal(); } if ( FRONTMTX_IS_1D_MODE(frontmtx) ) { fprintf(stderr, "\n fatal error in FrontMtx_lowerAdjFronts()" "\n data mode is 1-D, not 2-D\n") ; spoolesFatal(); } else if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { IVL_listAndSize(frontmtx->lowerblockIVL, J, pnadj, padj) ; } else { IVL_listAndSize(frontmtx->upperblockIVL, J, pnadj, padj) ; } return ; }
/* --------------------------------------------- fill *pncol with the number of columns and *pcolind with a pointer to the column indices created -- 98may04, cca --------------------------------------------- */ void FrontMtx_columnIndices ( FrontMtx *frontmtx, int J, int *pncol, int **pcolind ) { /* --------------- check the input --------------- */ if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront || pncol == NULL || pcolind == NULL ) { fprintf(stderr, "\n fatal error in FrontMtx_columnIndices(%p,%d,%p,%p)" "\n bad input\n", frontmtx, J, pncol, pcolind) ; spoolesFatal(); } if ( ! FRONTMTX_IS_PIVOTING(frontmtx) ) { IVL_listAndSize(frontmtx->symbfacIVL, J, pncol, pcolind) ; } else { IVL_listAndSize(frontmtx->coladjIVL, J, pncol, pcolind) ; } return ; }
/* ------------------------------------------------- purpose -- to write an IVL object for a human eye return value -- 1 if success, 0 otherwise created -- 95sep29, cca ------------------------------------------------- */ int IVL_writeForHumanEye ( IVL *ivl, FILE *fp ) { int ierr, j, size, rc ; int *ind ; if ( ivl == NULL || fp == NULL ) { fprintf(stderr, "\n fatal error in IVL_writeForHumanEye(%p,%p)" "\n bad input\n", ivl, fp) ; spoolesFatal(); } if ( (rc = IVL_writeStats(ivl, fp)) == 0 ) { fprintf(stderr, "\n fatal error in IVL_writeForHumanEye(%p,%p)" "\n rc = %d, return from IVL_writeStats(%p,%p)\n", ivl, fp, rc, ivl, fp) ; return(0) ; } for ( j = 0 ; j < ivl->nlist ; j++ ) { IVL_listAndSize(ivl, j, &size, &ind) ; if ( size > 0 ) { fprintf(fp, "\n %5d :", j) ; IVfp80(fp, size, ind, 8, &ierr) ; if ( ierr < 0 ) { fprintf(stderr, "\n fatal error in IVL_writeForHumanEye(%p,%p)" "\n ierr = %d, return from IVfp80, list %d\n", ivl, fp, ierr, j) ; return(0) ; } } } return(1) ; }
/* -------------------------------------------------- purpose -- fill *pnadj with the number of fronts K such that U_{J,K} != 0 and *padj with a pointer to a list of those fronts created -- 98may04, cca -------------------------------------------------- */ void FrontMtx_upperAdjFronts ( FrontMtx *frontmtx, int J, int *pnadj, int **padj ) { /* --------------- check the input --------------- */ if ( frontmtx == NULL || J < 0 || J >= frontmtx->nfront || pnadj == NULL || padj == NULL ) { fprintf(stderr, "\n fatal error in FrontMtx_upperAdjFronts(%p,%d,%p,%p)" "\n bad input\n", frontmtx, J, pnadj, padj) ; exit(-1) ; } if ( FRONTMTX_IS_1D_MODE(frontmtx) ) { fprintf(stderr, "\n fatal error in FrontMtx_upperAdjFronts()" "\n data mode is 1, not 2\n") ; exit(-1) ; } IVL_listAndSize(frontmtx->upperblockIVL, J, pnadj, padj) ; return ; }
/* -------------------------------------------------- purpose -- to write an IVL object to a binary file return value -- 1 if success, 0 otherwise created -- 95sep29, cca -------------------------------------------------- */ int IVL_writeToBinaryFile ( IVL *ivl, FILE *fp ) { int j, jsize, nlist, rc ; int *jind ; int itemp[3] ; /* --------------- check the input --------------- */ if ( ivl == NULL || fp == NULL || (nlist = ivl->nlist) <= 0 ) { fprintf(stderr, "\n fatal error in IVL_writeToBinaryFile(%p,%p)" "\n bad input\n", ivl, fp) ; spoolesFatal(); } itemp[0] = ivl->type ; itemp[1] = ivl->nlist ; itemp[2] = ivl->tsize ; rc = fwrite((void *) itemp, sizeof(int), 3, fp) ; if ( rc != 3 ) { fprintf(stderr, "\n error in IVL_writeToBinaryFile(%p,%p)" "\n %d of %d scalar items written\n", ivl, fp, rc, 3) ; return(0) ; } rc = fwrite((void *) ivl->sizes, sizeof(int), ivl->nlist, fp) ; if ( rc != ivl->nlist ) { fprintf(stderr, "\n error in IVL_writeToBinaryFile(%p,%p)" "\n ivl->sizes, %d of %d items written\n", ivl, fp, rc, ivl->nlist) ; return(0) ; } switch ( ivl->type ) { case IVL_NOTYPE : break ; case IVL_CHUNKED : case IVL_SOLO : case IVL_UNKNOWN : for ( j = 0 ; j < ivl->nlist ; j++ ) { IVL_listAndSize(ivl, j, &jsize, &jind) ; if ( jsize > 0 ) { rc = fwrite((void *) jind, sizeof(int), jsize, fp) ; if ( rc != jsize ) { fprintf(stderr, "\n error in IVL_writeToBinaryFile(%p,%p)" "\n list %d, %d of %d items written\n", ivl, fp, j, rc, jsize) ; return(0) ; } } } break ; } return(1) ; }
/* ------------------------------------------------------------------ this method is used during the setup for matrix-vector multiplies. each processor has computed the vertices it needs from other processors, these lists are contained in sendIVL. on return, recvIVL contains the lists of vertices this processor must send to all others. sendIVL -- on input, list[q] contains the vertices needed by this processor that are owned by q recvIVL -- on output, list[q] contains the vertices owned by this processor that are needed by q. note, if NULL on input, a new IVL object is allocated stats[] -- statistics vector stats[0] -- contains # of sends stats[1] -- contains # of receives stats[2] -- contains # of bytes sent stats[3] -- contains # of bytes received firsttag -- first tag for messages, tags in range [firsttag, firsttag+nproc-1] are used return value -- recvIVL created -- 98jul26, cca ------------------------------------------------------------------ */ IVL * IVL_MPI_alltoall ( IVL *sendIVL, IVL *recvIVL, int stats[], int msglvl, FILE *msgFile, int firsttag, MPI_Comm comm ) { int count, destination, lasttag, left, myid, nproc, offset, q, recvcount, right, sendcount, source, tag, tagbound ; int *incounts, *outcounts, *recvvec, *sendvec ; MPI_Status status ; /* --------------- check the input --------------- */ if ( sendIVL == NULL || stats == NULL || (msglvl > 0 && msgFile == NULL) ) { fprintf(msgFile, "\n fatal error in IVL_MPI_alltoall()" "\n bad input\n") ; exit(-1) ; } /* --------------------------------------- get id of self and number of processors --------------------------------------- */ MPI_Comm_rank(comm, &myid) ; MPI_Comm_size(comm, &nproc) ; if ( sendIVL->nlist != nproc ) { fprintf(msgFile, "\n fatal error in IVL_MPI_alltoall()" "\n sendIVL: nproc = %d, nlist = %d\n", nproc, sendIVL->nlist) ; exit(-1) ; } lasttag = firsttag + nproc ; if ( lasttag > (tagbound = maxTagMPI(comm)) ) { fprintf(stderr, "\n fatal error in IVL_MPI_alltoall()" "\n lasttag = %d, tag_bound = %d", lasttag, tagbound) ; exit(-1) ; } if ( recvIVL == NULL ) { recvIVL = IVL_new() ; } else { IVL_clearData(recvIVL) ; } IVL_init1(recvIVL, IVL_CHUNKED, nproc) ; /* ------------------------------------------ outcounts[] is sendIVL->sizes[] incounts[] will be recvIVL->sizes[] fill incounts via a call to MPI_Alltoall() and then initialize the recvIVL lists. ------------------------------------------ */ outcounts = sendIVL->sizes ; incounts = IVinit(nproc, 0) ; MPI_Alltoall((void *) outcounts, 1, MPI_INT, (void *) incounts, 1, MPI_INT, comm) ; for ( q = 0 ; q < nproc ; q++ ) { IVL_setList(recvIVL, q, incounts[q], NULL) ; } IVfree(incounts) ; /* --------------------------------------------------- load list myid of sendIVL into list myid of recvIVL --------------------------------------------------- */ IVL_listAndSize(sendIVL, myid, &sendcount, &sendvec) ; IVL_setList(recvIVL, myid, sendcount, sendvec) ; /* --------------------------------------------------------- now loop over the processes, send and receive information --------------------------------------------------------- */ for ( offset = 1, tag = firsttag ; offset < nproc ; offset++, tag++ ) { right = (myid + offset) % nproc ; if ( offset <= myid ) { left = myid - offset ; } else { left = nproc + myid - offset ; } IVL_listAndSize(sendIVL, right, &sendcount, &sendvec) ; IVL_listAndSize(recvIVL, left, &recvcount, &recvvec) ; if ( sendcount > 0 ) { destination = right ; stats[0]++ ; stats[2] += sendcount*sizeof(int) ; } else { destination = MPI_PROC_NULL ; } if ( recvcount > 0 ) { source = left ; stats[1]++ ; stats[3] += recvcount*sizeof(int) ; } else { source = MPI_PROC_NULL ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n offset %d, recvcount %d, source %d, sendcount %d, destination %d", offset, recvcount, source, sendcount, destination) ; fflush(msgFile) ; } /* ----------------- do a send/receive ----------------- */ MPI_Sendrecv((void *) sendvec, sendcount, MPI_INT, destination, tag, (void *) recvvec, recvcount, MPI_INT, source, tag, comm, &status) ; if ( source != MPI_PROC_NULL ) { MPI_Get_count(&status, MPI_INT, &count) ; if ( count != recvcount ) { fprintf(stderr, "\n fatal error in IVL_MPI_alltoall()" "\n proc %d : source %d, count %d, recvcount %d\n", myid, source, count, recvcount) ; exit(-1) ; } } if ( msglvl > 2 ) { fprintf(msgFile, "\n send/recv completed") ; fflush(msgFile) ; } } return(recvIVL) ; }
/* --------------------------------------------------- purpose -- to read an IVL object from a binary file return value -- 1 if success, 0 if failure created -- 95sep29, cca --------------------------------------------------- */ int IVL_readFromBinaryFile ( IVL *ivl, FILE *fp ) { int nlist, rc, type ; int itemp[3] ; int *sizes ; /* --------------- check the input --------------- */ if ( ivl == NULL || fp == NULL ) { fprintf(stderr, "\n fatal error in IVL_readFromBinaryFile(%p,%p)" "\n bad input\n", ivl, fp) ; return(0) ; } switch ( ivl->type ) { case IVL_CHUNKED : case IVL_SOLO : break ; default : fprintf(stderr, "\n error in IVL_readBinaryFile(%p,%p)" "\n bad type = %d", ivl, fp, ivl->type) ; return(0) ; } /* ------------------------------------------- save the ivl type and clear the data fields ------------------------------------------- */ type = ivl->type ; IVL_clearData(ivl) ; /* ----------------------------------- read in the three scalar parameters type, # of lists, # of indices ----------------------------------- */ if ( (rc = fread((void *) itemp, sizeof(int), 3, fp)) != 3 ) { fprintf(stderr, "\n error in IVL_readFromBinaryFile(%p,%p)" "\n itemp(3) : %d items of %d read\n", ivl, fp, rc, 3) ; return(0) ; } nlist = itemp[1] ; /* -------------------------- read in the sizes[] vector -------------------------- */ sizes = IVinit(nlist, 0) ; if ( (rc = fread((void *) sizes, sizeof(int), nlist, fp)) != nlist ) { fprintf(stderr, "\n error in IVL_readFromBinaryFile(%p,%p)" "\n sizes(%d) : %d items of %d read\n", ivl, fp, nlist, rc, nlist) ; return(0) ; } /* --------------------- initialize the object --------------------- */ IVL_init3(ivl, type, nlist, sizes) ; IVfree(sizes) ; /* ------------------- read in the indices ------------------- */ switch ( type ) { case IVL_SOLO : { int ilist, size ; int *ind ; for ( ilist = 0 ; ilist < nlist ; ilist++ ) { IVL_listAndSize(ivl, ilist, &size, &ind) ; if ( (rc = fread((void *) ind, sizeof(int), size, fp)) != size ) { fprintf(stderr, "\n error in IVL_readFromBinaryFile(%p,%p)" "\n list %d, %d items of %d read\n", ivl, fp, ilist, rc, size) ; return(0) ; } } } break ; case IVL_CHUNKED : { /* -------------------------------------------------------- read in the indices into the contiguous block of storage -------------------------------------------------------- */ if ( (rc = fread((void *) ivl->chunk->base, sizeof(int), ivl->tsize, fp)) != ivl->tsize ) { fprintf(stderr, "\n error in IVL_readFromBinaryFile(%p,%p)" "\n indices(%d) : %d items of %d read\n", ivl, fp, ivl->tsize, rc, ivl->tsize) ; return(0) ; } } break ; } return(1) ; }
/* ----------------------------------------------------- purpose -- to write an IVL object to a formatted file return value -- 1 if success, 0 otherwise created -- 95sep29, cca ----------------------------------------------------- */ int IVL_writeToFormattedFile ( IVL *ivl, FILE *fp ) { int count, ierr, j, jsize, nlist, rc ; int *jind ; /* --------------- check the input --------------- */ if ( ivl == NULL || fp == NULL || (nlist = ivl->nlist) <= 0 ) { fprintf(stderr, "\n fatal error in IVL_writeToFormattedFile(%p,%p)" "\n bad input\n", ivl, fp) ; spoolesFatal(); } /* ------------------------------------- write out the three scalar parameters ------------------------------------- */ rc = fprintf(fp, "\n %d %d %d", ivl->type, ivl->nlist, ivl->tsize) ; if ( rc < 0 ) { fprintf(stderr, "\n fatal error in IVL_writeToFormattedFile(%p,%p)" "\n rc = %d, return from first fprintf\n", ivl, fp, rc) ; return(0) ; } if ( ivl->nlist > 0 ) { IVfp80(fp, ivl->nlist, ivl->sizes, 80, &ierr) ; if ( ierr < 0 ) { fprintf(stderr, "\n fatal error in IVL_writeToFormattedFile(%p,%p)" "\n ierr = %d, return from sizes[] IVfp80\n", ivl, fp, ierr) ; return(0) ; } } switch ( ivl->type ) { case IVL_NOTYPE : break ; case IVL_UNKNOWN : case IVL_CHUNKED : case IVL_SOLO : for ( j = 0, count = 80 ; j < ivl->nlist ; j++ ) { IVL_listAndSize(ivl, j, &jsize, &jind) ; if ( jsize > 0 ) { count = IVfp80(fp, jsize, jind, count, &ierr) ; if ( ierr < 0 ) { fprintf(stderr, "\n fatal error in IVL_writeToFormattedFile(%p,%p)" "\n ierr = %d, return from IVfp80, list %d\n", ivl, fp, ierr, j) ; return(0) ; } } } break ; } return(1) ; }
/* --------------------------------------------------------------------- purpose -- take a Graph object and a map to expand it, create and return a bigger unit weight Graph object. this is useful for expanding a compressed graph into a unit weight graph. created -- 96mar02, cca --------------------------------------------------------------------- */ Graph * Graph_expand ( Graph *g, int nvtxbig, int map[] ) { Graph *gbig ; int count, ii, nedge, nvtx, v, vbig, vsize, w ; int *head, *indices, *link, *mark, *vadj ; IVL *adjIVL, *adjbigIVL ; /* --------------- check the input --------------- */ if ( g == NULL || nvtxbig <= 0 || map == NULL ) { fprintf(stderr, "\n fatal error in Graph_expand(%p,%d,%p)" "\n bad input\n", g, nvtxbig, map) ; spoolesFatal(); } nvtx = g->nvtx ; adjIVL = g->adjIVL ; /* ---------------------------------------- set up the linked lists for the vertices ---------------------------------------- */ head = IVinit(nvtx, -1) ; link = IVinit(nvtxbig, -1) ; for ( vbig = 0 ; vbig < nvtxbig ; vbig++ ) { v = map[vbig] ; link[vbig] = head[v] ; head[v] = vbig ; } /* -------------------------------- create the expanded Graph object -------------------------------- */ gbig = Graph_new() ; Graph_init1(gbig, 0, nvtxbig, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ; adjbigIVL = gbig->adjIVL ; /* ------------------------------------------- fill the lists in the expanded Graph object ------------------------------------------- */ indices = IVinit(nvtxbig, -1) ; mark = IVinit(nvtx, -1) ; nedge = 0 ; for ( v = 0 ; v < nvtx ; v++ ) { if ( head[v] != -1 ) { /* ------------------------------ load the indices that map to v ------------------------------ */ mark[v] = v ; count = 0 ; for ( vbig = head[v] ; vbig != -1 ; vbig = link[vbig] ) { indices[count++] = vbig ; } /* --------------------------------------------------- load the indices that map to vertices adjacent to v --------------------------------------------------- */ IVL_listAndSize(adjIVL, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { w = vadj[ii] ; if ( w < nvtx && mark[w] != v ) { mark[w] = v ; for ( vbig = head[w] ; vbig != -1 ; vbig = link[vbig] ) { indices[count++] = vbig ; } } } /* -------------------------------------- sort the index list in ascending order -------------------------------------- */ IVqsortUp(count, indices) ; /* ------------------------------------------------------- each vertex in the big IVL object has its own list. ------------------------------------------------------- */ for ( vbig = head[v] ; vbig != -1 ; vbig = link[vbig] ) { IVL_setList(adjbigIVL, vbig, count, indices) ; nedge += count ; } } } gbig->nedges = nedge ; /* ------------------------ free the working storage ------------------------ */ IVfree(head) ; IVfree(link) ; IVfree(indices) ; IVfree(mark) ; return(gbig) ; }
/* ------------------------------------------------------ purpose -- to read an IVL object from a formatted file return value -- 1 if success, 0 if failure created -- 95sep29, cca ------------------------------------------------------ */ int IVL_readFromFormattedFile ( IVL *ivl, FILE *fp ) { int nlist, rc, type ; int itemp[3] ; int *sizes ; /* --------------- check the input --------------- */ if ( ivl == NULL || fp == NULL ) { fprintf(stderr, "\n error in IVL_readFromFormattedFile(%p,%p)" "\n bad input\n", ivl, fp) ; return(0) ; } switch ( ivl->type ) { case IVL_CHUNKED : case IVL_SOLO : break ; default : fprintf(stderr, "\n error in IVL_readFormattedFile(%p,%p)" "\n bad type = %d", ivl, fp, ivl->type) ; return(0) ; } /* ------------------------------------------- save the ivl type and clear the data fields ------------------------------------------- */ type = ivl->type ; IVL_clearData(ivl) ; /* ----------------------------------- read in the three scalar parameters type, # of lists, # of indices ----------------------------------- */ if ( (rc = IVfscanf(fp, 3, itemp)) != 3 ) { fprintf(stderr, "\n error in IVL_readFromFormattedFile(%p,%p)" "\n %d items of %d read\n", ivl, fp, rc, 3) ; return(0) ; } nlist = itemp[1] ; /* fprintf(stdout, "\n itemp = { %d %d %d } ", itemp[0], itemp[1], itemp[2]) ; */ /* -------------------------- read in the sizes[] vector -------------------------- */ sizes = IVinit(nlist, 0) ; if ( (rc = IVfscanf(fp, nlist, sizes)) != nlist ) { fprintf(stderr, "\n error in IVL_readFromFormattedFile(%p,%p)" "\n %d items of %d read\n", ivl, fp, rc, nlist) ; return(0) ; } /* --------------------- initialize the object --------------------- */ IVL_init3(ivl, type, nlist, sizes) ; IVfree(sizes) ; /* ----------------------- now read in the indices ----------------------- */ switch ( type ) { case IVL_SOLO : { int ilist, size ; int *ind ; for ( ilist = 0 ; ilist < nlist ; ilist++ ) { IVL_listAndSize(ivl, ilist, &size, &ind) ; if ( size > 0 ) { if ( (rc = IVfscanf(fp, size, ind)) != size ) { fprintf(stderr, "\n error in IVL_readFromFormattedFile(%p,%p)" "\n list %d, %d items of %d read\n", ivl, fp, ilist, rc, size) ; return(0) ; } } } } break ; case IVL_CHUNKED : { /* -------------------------------------------------------- read in the indices into the contiguous block of storage -------------------------------------------------------- */ if ( (rc = IVfscanf(fp, ivl->tsize, ivl->chunk->base)) != ivl->tsize ) { fprintf(stderr, "\n error in IVL_readFromFormattedFile(%p,%p)" "\n %d items of %d read\n", ivl, fp, rc, ivl->tsize) ; return(0) ; } } break ; } 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) ; }
/* --------------------------------------------------------------- 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 ; }
/*--------------------------------------------------------------------*/ 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 -- map the off diagonal blocks to processes in a random fashion created -- 98mar19, cca -------------------------------------- */ void SolveMap_randomMap ( SolveMap *solvemap, int symmetryflag, IVL *upperBlockIVL, IVL *lowerBlockIVL, int nproc, IV *ownersIV, int seed, int msglvl, FILE *msgFile ) { Drand drand ; int ii, J, K, loc, nadj, nblockLower, nblockUpper, nfront, proc ; int *adj, *colids, *map, *owners, *rowids ; /* --------------- check the input --------------- */ if ( solvemap == NULL || symmetryflag < 0 || upperBlockIVL == NULL || ownersIV == NULL ) { fprintf(stderr, "\n fatal error in SolveMap_randomMap(%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_randomMap(): 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) ; } /* -------------------------------------- initialize the random number generator -------------------------------------- */ Drand_setDefaultFields(&drand) ; Drand_setUniform(&drand, 0, nproc) ; /* ---------------------------------------- map the upper blocks in a random fashion ---------------------------------------- */ 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 ) { 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 ( lowerBlockIVL != NULL ) { /* ---------------------------------------- map the lower blocks in a random fashion ---------------------------------------- */ 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 ) { 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++ ; } } } } return ; }
/* ---------------------------------------------------- create a Graph object that holds the adjacency graph of the assembled elements. created -- 95nov03, cca ---------------------------------------------------- */ Graph * EGraph_mkAdjGraph ( EGraph *egraph ) { int elem, esize, i, nelem, nvtx, v, vsize, w ; int *eind, *head, *link, *marker, *offsets, *vind ; IVL *eadjIVL, *gadjIVL ; Graph *graph ; /* --------------- check the input --------------- */ if ( egraph == NULL || (eadjIVL = egraph->adjIVL) == NULL ) { fprintf(stderr, "\n fatal error in EGraph_mkAdjGraph(%p)" "\n bad input\n", egraph) ; spoolesFatal(); } nelem = egraph->nelem ; nvtx = egraph->nvtx ; /* -------------------------------- set up the linked list structure -------------------------------- */ head = IVinit(nvtx, -1) ; link = IVinit(nelem, -1) ; offsets = IVinit(nelem, 0) ; /* ----------------------------------------------------------- sort the vertices in each element list into ascending order and link them into their first vertex ----------------------------------------------------------- */ for ( elem = 0 ; elem < nelem ; elem++ ) { IVL_listAndSize(eadjIVL, elem, &esize, &eind) ; if ( esize > 0 ) { IVqsortUp(esize, eind) ; v = eind[0] ; link[elem] = head[v] ; head[v] = elem ; } } /* --------------------------- create the new Graph object --------------------------- */ graph = Graph_new() ; Graph_init1(graph, egraph->type, nvtx, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ; gadjIVL = graph->adjIVL ; /* ---------------------- loop over the vertices ---------------------- */ vind = IVinit(nvtx, -1) ; marker = IVinit(nvtx, -1) ; for ( v = 0 ; v < nvtx ; v++ ) { /* --------------------------------- loop over the supporting elements --------------------------------- */ vsize = 0 ; vind[vsize++] = v ; marker[v] = v ; while ( (elem = head[v]) != -1 ) { /* fprintf(stdout, "\n checking out element %d :", jelem) ; */ head[v] = link[elem] ; IVL_listAndSize(eadjIVL, elem, &esize, &eind) ; for ( i = 0 ; i < esize ; i++ ) { w = eind[i] ; if ( marker[w] != v ) { marker[w] = v ; vind[vsize++] = w ; } } if ( (i = ++offsets[elem]) < esize ) { w = eind[i] ; link[elem] = head[w] ; head[w] = elem ; } } IVqsortUp(vsize, vind) ; IVL_setList(gadjIVL, v, vsize, vind) ; } graph->nedges = gadjIVL->tsize ; if ( egraph->type == 0 ) { graph->totvwght = nvtx ; } else if ( egraph->type == 1 ) { /* ------------------------------ fill the vertex weights vector ------------------------------ */ IVcopy(nvtx, graph->vwghts, egraph->vwghts) ; graph->totvwght = IVsum(nvtx, graph->vwghts) ; } graph->totewght = graph->nedges ; /* ------------------------ free the working storage ------------------------ */ IVfree(head) ; IVfree(link) ; IVfree(marker) ; IVfree(vind) ; IVfree(offsets) ; return(graph) ; }
/* -------------------------------------------------------------------- fill *pndom with ndom, the number of domains. fill *pnseg with nseg, the number of segments. domains are numbered in [0, ndom), segments in [ndom,ndom+nseg). return -- an IV object that contains the map from vertices to segments created -- 99feb29, cca -------------------------------------------------------------------- */ IV * GPart_domSegMap ( GPart *gpart, int *pndom, int *pnseg ) { FILE *msgFile ; Graph *g ; int adjdom, count, d, first, ierr, ii, jj1, jj2, last, ndom, msglvl, nextphi, nPhi, nPsi, nV, phi, phi0, phi1, phi2, phi3, psi, sigma, size, size0, size1, size2, v, vsize, w ; int *adj, *adj0, *adj1, *adj2, *compids, *dmark, *dsmap, *head, *link, *list, *offsets, *PhiToPsi, *PhiToV, *PsiToSigma, *vadj, *VtoPhi ; IV *dsmapIV ; IVL *PhiByPhi, *PhiByPowD, *PsiByPowD ; /* -------------------- set the initial time -------------------- */ icputimes = 0 ; MARKTIME(cputimes[icputimes]) ; /* --------------- check the input --------------- */ if ( gpart == NULL || (g = gpart->g) == NULL || pndom == NULL || pnseg == NULL ) { fprintf(stderr, "\n fatal error in GPart_domSegMap(%p,%p,%p)" "\n bad input\n", gpart, pndom, pnseg) ; exit(-1) ; } compids = IV_entries(&gpart->compidsIV) ; msglvl = gpart->msglvl ; msgFile = gpart->msgFile ; /* ------------------------ create the map IV object ------------------------ */ nV = g->nvtx ; dsmapIV = IV_new() ; IV_init(dsmapIV, nV, NULL) ; dsmap = IV_entries(dsmapIV) ; /* ---------------------------------- check compids[] and get the number of domains and interface vertices ---------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; ndom = nPhi = 0 ; for ( v = 0 ; v < nV ; v++ ) { if ( (d = compids[v]) < 0 ) { fprintf(stderr, "\n fatal error in GPart_domSegMap(%p,%p,%p)" "\n compids[%d] = %d\n", gpart, pndom, pnseg, v, compids[v]) ; exit(-1) ; } else if ( d == 0 ) { nPhi++ ; } else if ( ndom < d ) { ndom = d ; } } *pndom = ndom ; if ( msglvl > 1 ) { fprintf(msgFile, "\n\n Inside GPart_domSegMap") ; fprintf(msgFile, "\n %d domains, %d Phi vertices", ndom, nPhi) ; } if ( ndom == 1 ) { IVfill(nV, dsmap, 0) ; *pndom = 1 ; *pnseg = 0 ; return(dsmapIV) ; } /* -------------------------------- get the maps PhiToV : [0,nPhi) |---> [0,nV) VtoPhi : [0,nV) |---> [0,nPhi) -------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PhiToV = IVinit(nPhi, -1) ; VtoPhi = IVinit(nV, -1) ; for ( v = 0, phi = 0 ; v < nV ; v++ ) { if ( (d = compids[v]) == 0 ) { PhiToV[phi] = v ; VtoPhi[v] = phi++ ; } } if ( phi != nPhi ) { fprintf(stderr, "\n fatal error in GPart_domSegMap(%p,%p,%p)" "\n phi = %d != %d = nPhi\n", gpart, pndom, pnseg, phi, nPhi) ; exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiToV(%d) :", nPhi) ; IVfp80(msgFile, nPhi, PhiToV, 15, &ierr) ; fflush(msgFile) ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n VtoPhi(%d) :", nV) ; IVfp80(msgFile, nV, VtoPhi, 15, &ierr) ; fflush(msgFile) ; } /* --------------------------------------------------- create an IVL object, PhiByPowD, to hold lists from the interface vertices to their adjacent domains --------------------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; dmark = IVinit(ndom+1, -1) ; if ( nPhi >= ndom ) { list = IVinit(nPhi, -1) ; } else { list = IVinit(ndom, -1) ; } PhiByPowD = IVL_new() ; IVL_init1(PhiByPowD, IVL_CHUNKED, nPhi) ; for ( phi = 0 ; phi < nPhi ; phi++ ) { v = PhiToV[phi] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; /* if ( phi == 0 ) { int ierr ; fprintf(msgFile, "\n adj(%d,%d) = ", v, phi) ; IVfp80(msgFile, vsize, vadj, 15, &ierr) ; fflush(msgFile) ; } */ count = 0 ; for ( ii = 0 ; ii < vsize ; ii++ ) { if ( (w = vadj[ii]) < nV && (d = compids[w]) > 0 && dmark[d] != phi ) { dmark[d] = phi ; list[count++] = d ; } } if ( count > 0 ) { IVqsortUp(count, list) ; IVL_setList(PhiByPowD, phi, count, list) ; } } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiByPowD : interface x adjacent domains") ; IVL_writeForHumanEye(PhiByPowD, msgFile) ; fflush(msgFile) ; } /* ------------------------------------------------------- create an IVL object, PhiByPhi to hold lists from the interface vertices to interface vertices. (s,t) are in the list if (s,t) is an edge in the graph and s and t do not share an adjacent domain ------------------------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PhiByPhi = IVL_new() ; IVL_init1(PhiByPhi, IVL_CHUNKED, nPhi) ; offsets = IVinit(nPhi, 0) ; head = IVinit(nPhi, -1) ; link = IVinit(nPhi, -1) ; for ( phi1 = 0 ; phi1 < nPhi ; phi1++ ) { count = 0 ; if ( msglvl > 2 ) { v = PhiToV[phi1] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; fprintf(msgFile, "\n checking out phi = %d, v = %d", phi1, v) ; fprintf(msgFile, "\n adj(%d) : ", v) ; IVfp80(msgFile, vsize, vadj, 10, &ierr) ; } /* ------------------------------------------------------------- get (phi1, phi0) edges that were previously put into the list ------------------------------------------------------------- */ if ( msglvl > 3 ) { if ( head[phi1] == -1 ) { fprintf(msgFile, "\n no previous edges") ; } else { fprintf(msgFile, "\n previous edges :") ; } } for ( phi0 = head[phi1] ; phi0 != -1 ; phi0 = nextphi ) { if ( msglvl > 3 ) { fprintf(msgFile, " %d", phi0) ; } nextphi = link[phi0] ; list[count++] = phi0 ; IVL_listAndSize(PhiByPhi, phi0, &size0, &adj0) ; if ( (ii = ++offsets[phi0]) < size0 ) { /* ---------------------------- link phi0 into the next list ---------------------------- */ phi2 = adj0[ii] ; link[phi0] = head[phi2] ; head[phi2] = phi0 ; } } /* -------------------------- get new edges (phi1, phi2) -------------------------- */ IVL_listAndSize(PhiByPowD, phi1, &size1, &adj1) ; v = PhiToV[phi1] ; Graph_adjAndSize(g, v, &vsize, &vadj) ; for ( ii = 0 ; ii < vsize ; ii++ ) { if ( (w = vadj[ii]) < nV && compids[w] == 0 && (phi2 = VtoPhi[w]) > phi1 ) { if ( msglvl > 3 ) { fprintf(msgFile, "\n checking out phi2 = %d", phi2) ; } /* -------------------------------------------------- see if phi1 and phi2 have a common adjacent domain -------------------------------------------------- */ IVL_listAndSize(PhiByPowD, phi2, &size2, &adj2) ; adjdom = 0 ; jj1 = jj2 = 0 ; while ( jj1 < size1 && jj2 < size2 ) { if ( adj1[jj1] < adj2[jj2] ) { jj1++ ; } else if ( adj1[jj1] > adj2[jj2] ) { jj2++ ; } else { if ( msglvl > 3 ) { fprintf(msgFile, ", common adj domain %d", adj1[jj1]) ; } adjdom = 1 ; break ; } } if ( adjdom == 0 ) { if ( msglvl > 3 ) { fprintf(msgFile, ", no adjacent domain") ; } list[count++] = phi2 ; } } } if ( count > 0 ) { /* --------------------- set the list for phi1 --------------------- */ IVqsortUp(count, list) ; IVL_setList(PhiByPhi, phi1, count, list) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n edge list for %d :", phi1) ; IVfp80(msgFile, count, list, 15, &ierr) ; } for ( ii = 0, phi2 = -1 ; ii < count ; ii++ ) { if ( list[ii] > phi1 ) { offsets[phi1] = ii ; phi2 = list[ii] ; break ; } } if ( phi2 != -1 ) { if ( msglvl > 2 ) { fprintf(msgFile, "\n linking %d into list for %d", phi1, phi2) ; } link[phi1] = head[phi2] ; head[phi2] = phi1 ; } /* phi2 = list[0] ; link[phi1] = head[phi2] ; head[phi2] = phi1 ; */ } } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiByPhi : interface x interface") ; IVL_writeForHumanEye(PhiByPhi, msgFile) ; fflush(msgFile) ; } /* -------------------- get the PhiToPsi map -------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PhiToPsi = IVinit(nPhi, -1) ; nPsi = 0 ; for ( phi = 0 ; phi < nPhi ; phi++ ) { if ( PhiToPsi[phi] == -1 ) { /* --------------------------- phi not yet mapped to a psi --------------------------- */ first = last = 0 ; list[0] = phi ; PhiToPsi[phi] = nPsi ; while ( first <= last ) { phi2 = list[first++] ; IVL_listAndSize(PhiByPhi, phi2, &size, &adj) ; for ( ii = 0 ; ii < size ; ii++ ) { phi3 = adj[ii] ; if ( PhiToPsi[phi3] == -1 ) { PhiToPsi[phi3] = nPsi ; list[++last] = phi3 ; } } } nPsi++ ; } } if ( msglvl > 1 ) { fprintf(msgFile, "\n nPsi = %d", nPsi) ; fflush(msgFile) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n PhiToPsi(%d) :", nPhi) ; IVfp80(msgFile, nPhi, PhiToPsi, 15, &ierr) ; fflush(msgFile) ; } /* --------------------------------- create an IVL object, Psi --> 2^D --------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; IVfill(nPsi, head, -1) ; IVfill(nPhi, link, -1) ; for ( phi = 0 ; phi < nPhi ; phi++ ) { psi = PhiToPsi[phi] ; link[phi] = head[psi] ; head[psi] = phi ; } PsiByPowD = IVL_new() ; IVL_init1(PsiByPowD, IVL_CHUNKED, nPsi) ; IVfill(ndom+1, dmark, -1) ; for ( psi = 0 ; psi < nPsi ; psi++ ) { count = 0 ; for ( phi = head[psi] ; phi != -1 ; phi = link[phi] ) { v = PhiToV[phi] ; Graph_adjAndSize(g, v, &size, &adj) ; for ( ii = 0 ; ii < size ; ii++ ) { if ( (w = adj[ii]) < nV && (d = compids[w]) > 0 && dmark[d] != psi ) { dmark[d] = psi ; list[count++] = d ; } } } if ( count > 0 ) { IVqsortUp(count, list) ; IVL_setList(PsiByPowD, psi, count, list) ; } } if ( msglvl > 2 ) { fprintf(msgFile, "\n PsiByPowD(%d) :", nPhi) ; IVL_writeForHumanEye(PsiByPowD, msgFile) ; fflush(msgFile) ; } icputimes++ ; MARKTIME(cputimes[icputimes]) ; /* ------------------------------------- now get the map Psi |---> Sigma that is the equivalence map over PhiByPowD ------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; PsiToSigma = IVL_equivMap1(PsiByPowD) ; *pnseg = 1 + IVmax(nPsi, PsiToSigma, &ii) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n nSigma = %d", *pnseg) ; fprintf(msgFile, "\n PsiToSigma(%d) :", nPhi) ; IVfp80(msgFile, nPsi, PsiToSigma, 15, &ierr) ; fflush(msgFile) ; } /* -------------------------------------------------------------- now fill the map from the vertices to the domains and segments -------------------------------------------------------------- */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; for ( v = 0 ; v < nV ; v++ ) { if ( (d = compids[v]) > 0 ) { dsmap[v] = d - 1 ; } else { phi = VtoPhi[v] ; psi = PhiToPsi[phi] ; sigma = PsiToSigma[psi] ; dsmap[v] = ndom + sigma ; } } /* ------------------------ free the working storage ------------------------ */ icputimes++ ; MARKTIME(cputimes[icputimes]) ; IVL_free(PhiByPhi) ; IVL_free(PhiByPowD) ; IVL_free(PsiByPowD) ; IVfree(PhiToV) ; IVfree(VtoPhi) ; IVfree(dmark) ; IVfree(list) ; IVfree(PhiToPsi) ; IVfree(head) ; IVfree(link) ; IVfree(offsets) ; IVfree(PsiToSigma) ; icputimes++ ; MARKTIME(cputimes[icputimes]) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n domain/segment map timings split") ; fprintf(msgFile, "\n %9.5f : create the DSmap object" "\n %9.5f : get numbers of domain and interface vertices" "\n %9.5f : generate PhiToV and VtoPhi" "\n %9.5f : generate PhiByPowD" "\n %9.5f : generate PhiByPhi" "\n %9.5f : generate PhiToPsi" "\n %9.5f : generate PsiByPowD" "\n %9.5f : generate PsiToSigma" "\n %9.5f : generate dsmap" "\n %9.5f : free working storage" "\n %9.5f : total time", cputimes[1] - cputimes[0], cputimes[2] - cputimes[1], cputimes[3] - cputimes[2], cputimes[4] - cputimes[3], cputimes[5] - cputimes[4], cputimes[6] - cputimes[5], cputimes[7] - cputimes[6], cputimes[8] - cputimes[7], cputimes[9] - cputimes[8], cputimes[10] - cputimes[9], cputimes[11] - cputimes[0]) ; } return(dsmapIV) ; }
/* -------------------------------------------------------------- purpose -- create and return an A2 object that contains rows of A and rows from update matrices of the children. the matrix may not be in staircase form created -- 98may25, cca -------------------------------------------------------------- */ A2 * FrontMtx_QR_assembleFront ( FrontMtx *frontmtx, int J, InpMtx *mtxA, IVL *rowsIVL, int firstnz[], int colmap[], Chv *firstchild, DV *workDV, int msglvl, FILE *msgFile ) { A2 *frontJ ; Chv *chvI ; double *rowI, *rowJ, *rowentA ; int ii, irow, irowA, irowI, jcol, jj, jrow, ncolI, ncolJ, nentA, nrowI, nrowJ, nrowFromA ; int *colindA, *colindI, *colindJ, *map, *rowids, *rowsFromA ; /* --------------- check the input --------------- */ if ( frontmtx == NULL || mtxA == NULL || rowsIVL == NULL || (msglvl > 0 && msgFile == NULL) ) { fprintf(stderr, "\n fatal error in FrontMtx_QR_assembleFront()" "\n bad input\n") ; exit(-1) ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n\n inside FrontMtx_QR_assembleFront(%d)", J) ; fflush(msgFile) ; } /* -------------------------------------------------- set up the map from global to local column indices -------------------------------------------------- */ FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ; for ( jcol = 0 ; jcol < ncolJ ; jcol++ ) { colmap[colindJ[jcol]] = jcol ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n front %d's column indices", J) ; IVfprintf(msgFile, ncolJ, colindJ) ; fflush(msgFile) ; } /* ------------------------------------------------- compute the size of the front and map the global indices of the update matrices into local indices ------------------------------------------------- */ IVL_listAndSize(rowsIVL, J, &nrowFromA, &rowsFromA) ; nrowJ = nrowFromA ; if ( msglvl > 3 ) { fprintf(msgFile, "\n %d rows from A", nrowFromA) ; fflush(msgFile) ; } for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) { nrowJ += chvI->nD ; Chv_columnIndices(chvI, &ncolI, &colindI) ; for ( jcol = 0 ; jcol < ncolI ; jcol++ ) { colindI[jcol] = colmap[colindI[jcol]] ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n %d rows from child %d", chvI->nD, chvI->id) ; fflush(msgFile) ; } } /* ---------------------------------------------------------- get workspace for the rowids[nrowJ] and map[nrowJ] vectors ---------------------------------------------------------- */ if ( sizeof(int) == sizeof(double) ) { DV_setSize(workDV, 2*nrowJ) ; } else if ( 2*sizeof(int) == sizeof(double) ) { DV_setSize(workDV, nrowJ) ; } rowids = (int *) DV_entries(workDV) ; map = rowids + nrowJ ; IVramp(nrowJ, rowids, 0, 1) ; IVfill(nrowJ, map, -1) ; /* ----------------------------------------------------------------- get the map from incoming rows to their place in the front matrix ----------------------------------------------------------------- */ for ( irow = jrow = 0 ; irow < nrowFromA ; irow++, jrow++ ) { irowA = rowsFromA[irow] ; map[jrow] = colmap[firstnz[irowA]] ; } for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) { nrowI = chvI->nD ; Chv_columnIndices(chvI, &ncolI, &colindI) ; for ( irow = 0 ; irow < nrowI ; irow++, jrow++ ) { map[jrow] = colindI[irow] ; } } IV2qsortUp(nrowJ, map, rowids) ; for ( irow = 0 ; irow < nrowJ ; irow++ ) { map[rowids[irow]] = irow ; } /* ---------------------------- allocate the A2 front object ---------------------------- */ frontJ = A2_new() ; A2_init(frontJ, frontmtx->type, nrowJ, ncolJ, ncolJ, 1, NULL) ; A2_zero(frontJ) ; /* ------------------------------------ load the original rows of the matrix ------------------------------------ */ for ( jrow = 0 ; jrow < nrowFromA ; jrow++ ) { irowA = rowsFromA[jrow] ; rowJ = A2_row(frontJ, map[jrow]) ; if ( A2_IS_REAL(frontJ) ) { InpMtx_realVector(mtxA, irowA, &nentA, &colindA, &rowentA) ; } else if ( A2_IS_COMPLEX(frontJ) ) { InpMtx_complexVector(mtxA, irowA, &nentA, &colindA, &rowentA) ; } if ( msglvl > 3 ) { fprintf(msgFile, "\n loading row %d", irowA) ; fprintf(msgFile, "\n global indices") ; IVfprintf(msgFile, nentA, colindA) ; fflush(msgFile) ; } if ( A2_IS_REAL(frontJ) ) { for ( ii = 0 ; ii < nentA ; ii++ ) { jj = colmap[colindA[ii]] ; rowJ[jj] = rowentA[ii] ; } } else if ( A2_IS_COMPLEX(frontJ) ) { for ( ii = 0 ; ii < nentA ; ii++ ) { jj = colmap[colindA[ii]] ; rowJ[2*jj] = rowentA[2*ii] ; rowJ[2*jj+1] = rowentA[2*ii+1] ; } } } if ( msglvl > 3 ) { fprintf(msgFile, "\n after assembling rows of A") ; A2_writeForHumanEye(frontJ, msgFile) ; fflush(msgFile) ; } /* ---------------------------------- load the updates from the children ---------------------------------- */ for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) { nrowI = chvI->nD ; Chv_columnIndices(chvI, &ncolI, &colindI) ; if ( msglvl > 3 ) { fprintf(msgFile, "\n loading child %d", chvI->id) ; fprintf(msgFile, "\n child's column indices") ; IVfprintf(msgFile, ncolI, colindI) ; Chv_writeForHumanEye(chvI, msgFile) ; fflush(msgFile) ; } rowI = Chv_entries(chvI) ; for ( irowI = 0 ; irowI < nrowI ; irowI++, jrow++ ) { rowJ = A2_row(frontJ, map[jrow]) ; if ( A2_IS_REAL(frontJ) ) { for ( ii = irowI ; ii < ncolI ; ii++ ) { jj = colindI[ii] ; rowJ[jj] = rowI[ii] ; } rowI += ncolI - irowI - 1 ; } else if ( A2_IS_COMPLEX(frontJ) ) { for ( ii = irowI ; ii < ncolI ; ii++ ) { jj = colindI[ii] ; rowJ[2*jj] = rowI[2*ii] ; rowJ[2*jj+1] = rowI[2*ii+1] ; } rowI += 2*(ncolI - irowI - 1) ; } } if ( msglvl > 3 ) { fprintf(msgFile, "\n after assembling child %d", chvI->id) ; A2_writeForHumanEye(frontJ, msgFile) ; fflush(msgFile) ; } } return(frontJ) ; }
// 2008/03/12 kazuhide nakata void Newton::initialize_sparse_bMat(int m, IV *newToOldIV, IVL *symbfacIVL) { // bMat_type = SPARSE; // printf("SPARSE computation\n"); int* newToOld; newToOld = IV_entries(newToOldIV); NewArray(ordering,int,m); NewArray(reverse_ordering,int,m); for (int i=0; i<m; i++){ ordering[i] = newToOld[i]; } for (int i=0; i<m; i++){ reverse_ordering[ordering[i]] = i; } // separate front or back node int* counter; int nClique = IVL_nlist(symbfacIVL); int psize; int* pivec; bool* bnode; int* nFront; NewArray(counter,int ,m); NewArray(bnode ,bool,m); NewArray(nFront ,int ,nClique); for (int k=0; k<m; k++){ bnode[k] = false; counter[k] = -1; } // search number of front for (int l=nClique-1; l >= 0; l--){ IVL_listAndSize(symbfacIVL,l,&psize,&pivec); int i; for (i=0; i<psize; i++){ int ii = reverse_ordering[pivec[i]]; if (bnode[ii] == false){ counter[ii] = psize - i; bnode[ii] = true; } else { nFront[l] = i; break; } } if (i == psize){ nFront[l] = psize; } } // error check for (int k=0; k<m; k++){ if (counter[k] == -1){ rError("Newton::initialize_sparse_bMat: program bug"); } } // make index of diagonal NewArray(diagonalIndex,int,m+1); diagonalIndex[0] = 0; for (int k=1; k<m+1; k++){ diagonalIndex[k] = diagonalIndex[k-1] + counter[k-1]; } // initialize sparse_bMat sparse_bMat.initialize(m,m,SparseMatrix::SPARSE,diagonalIndex[m]); // initialize index of sparse_bmat int nonzeros = 0; for (int l=0; l<nClique; l++){ IVL_listAndSize(symbfacIVL,l,&psize,&pivec); for (int i=0; i<nFront[l]; i++){ int ii = reverse_ordering[pivec[i]]; for (int j=i; j<psize; j++){ int jj = reverse_ordering[pivec[j]]; int index = diagonalIndex[ii] + j - i; sparse_bMat.row_index[index] = ii; sparse_bMat.column_index[index] = jj; nonzeros++; } } } // error check if (nonzeros!= sparse_bMat.NonZeroNumber){ rError("Newton::initialize_sparse_bMat probram bug"); } sparse_bMat.NonZeroCount = nonzeros; // sparse_bMat.display(); DeleteArray(counter); DeleteArray(bnode); DeleteArray(nFront); }
/* -------------------------------------------------------------------- purpose -- to fill submtx with a submatrix of the front matrix. the fronts that form the submatrix are found in frontidsIV. all information in submtx is local, front #'s are from 0 to one less than the number of fronts in the submatrix, equation #'s are from 0 to one less than the number of rows and columns in the submatrix. the global row and column ids for the submatrix are stored in rowsIV and colsIV on return. return values --- 1 -- normal return -1 -- submtx is NULL -2 -- frontmtx is NULL -3 -- frontmtx is not in 2-D mode -4 -- frontidsIV is NULL -5 -- frontidsIV is invalid -6 -- rowsIV is NULL -7 -- colsIV is NULL -8 -- unable to create front tree -9 -- unable to create symbfacIVL -10 -- unable to create coladjIVL -11 -- unable to create rowadjIVL -12 -- unable to create upperblockIVL -13 -- unable to create lowerblockIVL created -- 98oct17, cca -------------------------------------------------------------------- */ int FrontMtx_initFromSubmatrix ( FrontMtx *submtx, FrontMtx *frontmtx, IV *frontidsIV, IV *rowsIV, IV *colsIV, int msglvl, FILE *msgFile ) { ETree *etreeSub ; int ii, J, Jsub, K, Ksub, ncol, nfront, nfrontSub, neqnSub, nJ, nrow, offset, rc, size, vSub ; int *bndwghts, *colind, *colmap, *cols, *frontSubIds, *list, *nodwghts, *rowind, *rowmap, *rows ; IV *frontsizesIVsub, *vtxIV ; IVL *coladjIVLsub, *lowerblockIVLsub, *rowadjIVLsub, *symbfacIVLsub, *upperblockIVLsub ; SubMtx *mtx ; /* --------------- check the input --------------- */ if ( submtx == NULL ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n submtx is NULL\n") ; return(-1) ; } if ( frontmtx == NULL ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n frontmtx is NULL\n") ; return(-2) ; } if ( ! FRONTMTX_IS_2D_MODE(frontmtx) ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n frontmtx mode is not 2D\n") ; return(-3) ; } if ( frontidsIV == NULL ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n frontidsIV is NULL\n") ; return(-4) ; } nfront = FrontMtx_nfront(frontmtx) ; IV_sizeAndEntries(frontidsIV, &nfrontSub, &frontSubIds) ; if ( nfrontSub < 0 || nfrontSub > nfront ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n invalid frontidsIV" "\n nfrontSub = %d, nfront %d\n", nfrontSub, nfront) ; return(-5) ; } for ( ii = 0 ; ii < nfrontSub ; ii++ ) { if ( (J = frontSubIds[ii]) < 0 || J >= nfront ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n invalid frontidsIV" "\n frontSubIds[%d] = %d, nfront = %d\n", ii, J, nfront) ; return(-5) ; } } if ( rowsIV == NULL ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n rowsIV is NULL\n") ; return(-6) ; } if ( colsIV == NULL ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n colsIV is NULL\n") ; return(-7) ; } /*--------------------------------------------------------------------*/ /* ----------------------------------------------------- clear the data for the submatrix and set the scalar values (some inherited from the global matrix) ----------------------------------------------------- */ FrontMtx_clearData(submtx) ; submtx->nfront = nfrontSub ; submtx->type = frontmtx->type ; submtx->symmetryflag = frontmtx->symmetryflag ; submtx->sparsityflag = frontmtx->sparsityflag ; submtx->pivotingflag = frontmtx->pivotingflag ; submtx->dataMode = FRONTMTX_2D_MODE ; /* --------------------------------------------------------------- initialize the front tree for the submatrix. note: on return, vtxIV is filled with the vertices originally in the submatrix, (pivoting may change this), needed to find symbolic factorization IVL object note: at return, the boundary weights are likely to be invalid, since we have no way of knowing what boundary indices for a front are really in the domain. this will be changed after we have the symbolic factorization. --------------------------------------------------------------- */ etreeSub = submtx->frontETree = ETree_new() ; vtxIV = IV_new() ; rc = ETree_initFromSubtree(etreeSub, frontidsIV, frontmtx->frontETree, vtxIV) ; if ( rc != 1 ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n unable to create submatrix's front ETree, rc = %d\n", rc) ; return(-8) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n submatrix ETree") ; ETree_writeForHumanEye(etreeSub, msgFile) ; fprintf(msgFile, "\n\n submatrix original equations") ; IV_writeForHumanEye(vtxIV, msgFile) ; fflush(msgFile) ; } /* ------------------------------------------------------ set the # of equations (perhap temporarily if pivoting has delayed some rows and columns), and the tree. ------------------------------------------------------ */ submtx->neqns = neqnSub = IV_size(vtxIV) ; submtx->tree = etreeSub->tree ; /* ----------------------------------------------------- initialize the symbolic factorization for the subtree ----------------------------------------------------- */ symbfacIVLsub = submtx->symbfacIVL = IVL_new() ; rc = IVL_initFromSubIVL(symbfacIVLsub, frontmtx->symbfacIVL, frontidsIV, vtxIV) ; if ( rc != 1 ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n unable to create submatrix's symbfac, rc = %d\n", rc) ; return(-9) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n submatrix symbolic factorizatio") ; IVL_writeForHumanEye(symbfacIVLsub, msgFile) ; fflush(msgFile) ; } /* --------------------------------------------- adjust the boundary weights of the front tree --------------------------------------------- */ nodwghts = ETree_nodwghts(etreeSub) ; bndwghts = ETree_bndwghts(etreeSub) ; for ( J = 0 ; J < nfrontSub ; J++ ) { IVL_listAndSize(symbfacIVLsub, J, &size, &list) ; bndwghts[J] = size - nodwghts[J] ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n submatrix ETree after bndweight adjustment") ; ETree_writeForHumanEye(etreeSub, msgFile) ; fflush(msgFile) ; } /* ------------------------------------- set the front sizes for the submatrix ------------------------------------- */ frontsizesIVsub = submtx->frontsizesIV = IV_new() ; IV_init(frontsizesIVsub, nfrontSub, NULL) ; IVgather(nfrontSub, IV_entries(frontsizesIVsub), IV_entries(frontmtx->frontsizesIV), IV_entries(frontidsIV)) ; neqnSub = submtx->neqns = IV_sum(frontsizesIVsub) ; if ( msglvl > 4 ) { fprintf(msgFile, "\n\n %d equations in submatrix", neqnSub) ; fprintf(msgFile, "\n\n front sizes for submatrix") ; IV_writeForHumanEye(frontsizesIVsub, msgFile) ; fflush(msgFile) ; } /* ------------------------------------------------------------------- fill rowsIV and colsIV with the row and column ids of the submatrix ------------------------------------------------------------------- */ IV_setSize(rowsIV, neqnSub) ; IV_setSize(colsIV, neqnSub) ; rows = IV_entries(rowsIV) ; cols = IV_entries(colsIV) ; for ( Jsub = offset = 0 ; Jsub < nfrontSub ; Jsub++ ) { if ( (nJ = FrontMtx_frontSize(submtx, Jsub)) > 0 ) { J = frontSubIds[Jsub] ; FrontMtx_columnIndices(frontmtx, J, &size, &list) ; IVcopy(nJ, cols + offset, list) ; FrontMtx_rowIndices(frontmtx, J, &size, &list) ; IVcopy(nJ, rows + offset, list) ; offset += nJ ; } } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n row ids for submatrix") ; IV_writeForHumanEye(rowsIV, msgFile) ; fprintf(msgFile, "\n\n column ids for submatrix") ; IV_writeForHumanEye(colsIV, msgFile) ; fflush(msgFile) ; } /* ---------------------------------- get the row and column adjacencies ---------------------------------- */ if ( FRONTMTX_IS_PIVOTING(frontmtx) ) { submtx->neqns = neqnSub ; coladjIVLsub = submtx->coladjIVL = IVL_new() ; rc = IVL_initFromSubIVL(coladjIVLsub, frontmtx->coladjIVL, frontidsIV, colsIV) ; if ( rc != 1 ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n unable to create submatrix's coladjIVL, rc = %d\n", rc) ; return(-10) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n submatrix col adjacency") ; IVL_writeForHumanEye(coladjIVLsub, msgFile) ; fflush(msgFile) ; } if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { rowadjIVLsub = submtx->rowadjIVL = IVL_new() ; rc = IVL_initFromSubIVL(rowadjIVLsub, frontmtx->rowadjIVL, frontidsIV, rowsIV) ; if ( rc != 1 ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n unable to create submatrix's rowadjIVL, rc = %d\n", rc) ; return(-11) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n submatrix row adjacency") ; IVL_writeForHumanEye(rowadjIVLsub, msgFile) ; fflush(msgFile) ; } } } IV_free(vtxIV) ; /* ---------------------------------------------- get the rowmap[] and colmap[] vectors, needed to translate indices in the submatrices ---------------------------------------------- */ colmap = IVinit(frontmtx->neqns, -1) ; for ( ii = 0 ; ii < neqnSub ; ii++ ) { colmap[cols[ii]] = ii ; } if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { rowmap = IVinit(frontmtx->neqns, -1) ; for ( ii = 0 ; ii < neqnSub ; ii++ ) { rowmap[rows[ii]] = ii ; } } else { rowmap = colmap ; } /* ----------------------------------------------------------- get the upper and lower block IVL objects for the submatrix ----------------------------------------------------------- */ upperblockIVLsub = submtx->upperblockIVL = IVL_new() ; rc = IVL_initFromSubIVL(upperblockIVLsub, frontmtx->upperblockIVL, frontidsIV, frontidsIV) ; if ( rc != 1 ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n unable to create upperblockIVL, rc = %d\n", rc) ; return(-12) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n upper block adjacency IVL object") ; IVL_writeForHumanEye(upperblockIVLsub, msgFile) ; fflush(msgFile) ; } if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { lowerblockIVLsub = submtx->lowerblockIVL = IVL_new() ; rc = IVL_initFromSubIVL(lowerblockIVLsub, frontmtx->lowerblockIVL, frontidsIV, frontidsIV) ; if ( rc != 1 ) { fprintf(stderr, "\n error in FrontMtx_initFromSubmatrix()" "\n unable to create lowerblockIVL, rc = %d\n", rc) ; return(-13) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n lower block adjacency IVL object") ; IVL_writeForHumanEye(lowerblockIVLsub, msgFile) ; fflush(msgFile) ; } } /* ---------------------------------------------------------------- allocate the vector and hash table(s) for the factor submatrices ---------------------------------------------------------------- */ ALLOCATE(submtx->p_mtxDJJ, struct _SubMtx *, nfrontSub) ; for ( J = 0 ; J < nfrontSub ; J++ ) { submtx->p_mtxDJJ[J] = NULL ; } submtx->upperhash = I2Ohash_new() ; I2Ohash_init(submtx->upperhash, nfrontSub, nfrontSub, nfrontSub) ; if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { submtx->lowerhash = I2Ohash_new() ; I2Ohash_init(submtx->lowerhash, nfrontSub, nfrontSub, nfrontSub) ; } /* ----------------------------------------------------------------- remove the diagonal submatrices from the factor matrix and insert into the submatrix object. note: front row and column ids must be changed to their local values, and the row and column indices must be mapped to local indices. ----------------------------------------------------------------- */ for ( Jsub = 0 ; Jsub < nfrontSub ; Jsub++ ) { J = frontSubIds[Jsub] ; if ( (mtx = frontmtx->p_mtxDJJ[J]) != NULL ) { SubMtx_setIds(mtx, Jsub, Jsub) ; SubMtx_columnIndices(mtx, &ncol, &colind) ; IVgather(ncol, colind, colmap, colind) ; SubMtx_rowIndices(mtx, &nrow, &rowind) ; IVgather(nrow, rowind, rowmap, rowind) ; submtx->p_mtxDJJ[Jsub] = mtx ; frontmtx->p_mtxDJJ[J] = NULL ; submtx->nentD += mtx->nent ; } } /* ---------------------------------------------------------------- remove the upper triangular submatrices from the factor matrix and insert into the submatrix object. note: front row and column ids must be changed to their local values. if the matrix is on the diagonal, i.e., U(J,J), its row and column indices must be mapped to local indices. ---------------------------------------------------------------- */ for ( Jsub = 0 ; Jsub < nfrontSub ; Jsub++ ) { J = frontSubIds[Jsub] ; FrontMtx_upperAdjFronts(submtx, Jsub, &size, &list) ; for ( ii = 0 ; ii < size ; ii++ ) { Ksub = list[ii] ; K = frontSubIds[Ksub] ; if ( 1 == I2Ohash_remove(frontmtx->upperhash, J, K, (void *) &mtx) ) { SubMtx_setIds(mtx, Jsub, Ksub) ; if ( K == J ) { SubMtx_columnIndices(mtx, &ncol, &colind) ; IVgather(ncol, colind, colmap, colind) ; SubMtx_rowIndices(mtx, &nrow, &rowind) ; IVgather(nrow, rowind, rowmap, rowind) ; } I2Ohash_insert(submtx->upperhash, Jsub, Ksub, (void *) mtx) ; submtx->nentU += mtx->nent ; } } } if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { /* ---------------------------------------------------------------- remove the lower triangular submatrices from the factor matrix and insert into the submatrix object. note: front row and column ids must be changed to their local values. if the matrix is on the diagonal, i.e., L(J,J), its row and column indices must be mapped to local indices. ---------------------------------------------------------------- */ for ( Jsub = 0 ; Jsub < nfrontSub ; Jsub++ ) { J = frontSubIds[Jsub] ; FrontMtx_lowerAdjFronts(submtx, Jsub, &size, &list) ; for ( ii = 0 ; ii < size ; ii++ ) { Ksub = list[ii] ; K = frontSubIds[Ksub] ; if ( 1 == I2Ohash_remove(frontmtx->lowerhash, K, J, (void *) &mtx) ) { SubMtx_setIds(mtx, Ksub, Jsub) ; if ( K == J ) { SubMtx_columnIndices(mtx, &ncol, &colind) ; IVgather(ncol, colind, colmap, colind) ; SubMtx_rowIndices(mtx, &nrow, &rowind) ; IVgather(nrow, rowind, rowmap, rowind) ; } I2Ohash_insert(submtx->lowerhash, Ksub, Jsub, (void *) mtx); submtx->nentL += mtx->nent ; } } } } /* ------------------------ free the working storage ------------------------ */ IVfree(colmap) ; if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { IVfree(rowmap) ; } return(1) ; }
/* ------------------------------------------------------------- purpose -- the IVL object ivl and IV object ownersIV are both found on each process. the ownersIV object is identical over all the processes, and owners[ii] tells which processes owns list ii of the ivl object. on return from this method, the ivl object is replicated over all the processes. each process sends the lists that it owns to all the other processes. created -- 98apr03, cca ------------------------------------------------------------- */ void IVL_MPI_allgather ( IVL *ivl, IV *ownersIV, int stats[], int msglvl, FILE *msgFile, int firsttag, MPI_Comm comm ) { int count, destination, ii, ilist, incount, jlist, jproc, left, maxcount, myid, nlist, nmylists, notherlists, nowners, nproc, offset, outcount, right, size, source, tag ; int *counts, *inbuffer, *list, *outbuffer, *owners ; MPI_Status status ; /* --------------- check the input --------------- */ if ( ivl == NULL || ownersIV == NULL ) { fprintf(stderr, "\n fatal error in IVL_MPI_allgather()" "\n ivl = %p, ownersIV = %p\n", ivl, ownersIV) ; exit(-1) ; } /* ---------------------------------------------- get id of self, # of processes and # of fronts ---------------------------------------------- */ MPI_Comm_rank(comm, &myid) ; MPI_Comm_size(comm, &nproc) ; nlist = ivl->nlist ; IV_sizeAndEntries(ownersIV, &nowners, &owners) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n\n inside IVL_MPI_allgather()" "\n nproc = %d, myid = %d, nlist = %d, nowners = %d", nproc, myid, nlist, nowners) ; fflush(msgFile) ; } if ( nlist != nowners || owners == NULL ) { fprintf(stderr, "\n fatal error in IVL_MPI_allgather()" "\n nlist = %d, nowners = %d, owners = %p\n", nlist, nowners, owners) ; exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n ivl") ; IVL_writeForHumanEye(ivl, msgFile) ; fprintf(msgFile, "\n\n ownersIV") ; IV_writeForHumanEye(ownersIV, msgFile) ; fflush(msgFile) ; } /* ----------------------------------------------- step 1 : determine the size of the message that this process will send to the others ----------------------------------------------- */ for ( ilist = 0, outcount = 1 ; ilist < nlist ; ilist++ ) { if ( owners[ilist] < 0 || owners[ilist] >= nproc ) { fprintf(stderr, "\n owners[%d] = %d", ilist, owners[ilist]) ; exit(-1) ; } if ( owners[ilist] == myid ) { outcount += 2 ; IVL_listAndSize(ivl, ilist, &size, &list) ; outcount += size ; } } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n outcount = %d", outcount) ; fflush(msgFile) ; } /* ---------------------------------------------------- do an all-to-all gather/scatter counts[jproc] = # of int's in the message from jproc ---------------------------------------------------- */ counts = IVinit(nproc, 0) ; counts[myid] = outcount ; MPI_Allgather((void *) &counts[myid], 1, MPI_INT, (void *) counts, 1, MPI_INT, comm) ; if ( msglvl > 1 ) { fprintf(msgFile, "\n\n counts") ; IVfprintf(msgFile, nproc, counts) ; fflush(msgFile) ; } /* ----------------------------- set up the in and out buffers ----------------------------- */ if ( outcount > 0 ) { outbuffer = IVinit(outcount, -1) ; for ( ilist = nmylists = 0, ii = 1 ; ilist < nlist ; ilist++ ) { if ( owners[ilist] == myid ) { nmylists++ ; IVL_listAndSize(ivl, ilist, &size, &list) ; outbuffer[ii++] = ilist ; outbuffer[ii++] = size ; if ( size > 0 ) { IVcopy(size, &outbuffer[ii], list) ; ii += size ; } } } outbuffer[0] = nmylists ; if ( ii != outcount ) { fprintf(stderr, "\n myid = %d, ii = %d, outcount = %d", myid, ii, outcount) ; fprintf(msgFile, "\n myid = %d, ii = %d, outcount = %d", myid, ii, outcount) ; exit(-1) ; } } else { outbuffer = NULL ; } maxcount = IVmax(nproc, counts, &jproc) ; if ( maxcount > 0 ) { inbuffer = IVinit(maxcount, -1) ; } else { inbuffer = NULL ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n outbuffer %p, maxcount %d, inbuffer %p", outbuffer, maxcount, inbuffer) ; fflush(msgFile) ; } /* ------------------------------------- step 2: loop over the other processes send and receive information ------------------------------------- */ for ( offset = 1, tag = firsttag ; offset < nproc ; offset++, tag++ ) { right = (myid + offset) % nproc ; if ( offset <= myid ) { left = myid - offset ; } else { left = nproc + myid - offset ; } if ( outcount > 0 ) { destination = right ; stats[0]++ ; stats[2] += outcount*sizeof(int) ; } else { destination = MPI_PROC_NULL ; } incount = counts[left] ; if ( incount > 0 ) { source = left ; stats[1]++ ; stats[3] += incount*sizeof(int) ; } else { source = MPI_PROC_NULL ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n offset %d, source %d, destination %d", offset, source, destination) ; fflush(msgFile) ; } /* ----------------- do a send/receive ----------------- */ MPI_Sendrecv(outbuffer, outcount, MPI_INT, destination, tag, inbuffer, incount, MPI_INT, source, tag, comm, &status) ; if ( source != MPI_PROC_NULL ) { MPI_Get_count(&status, MPI_INT, &count) ; if ( count != incount ) { fprintf(stderr, "\n 1. fatal error in IVL_MPI_allgather()" "\n proc %d : source = %d, count = %d, incount = %d\n", myid, source, count, incount) ; exit(-1) ; } } /* ---------------------------- set the values in the vector ---------------------------- */ notherlists = inbuffer[0] ; for ( ilist = 0, ii = 1 ; ilist < notherlists ; ilist++ ) { jlist = inbuffer[ii++] ; size = inbuffer[ii++] ; if ( size > 0 ) { IVL_setList(ivl, jlist, size, &inbuffer[ii]) ; ii += size ; } } if ( ii != incount ) { fprintf(msgFile, "\n ii = %d, incount = %d", ii, incount) ; fprintf(stderr, "\n ii = %d, incount = %d", ii, incount) ; exit(-1) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n after setting values") ; IVL_writeForHumanEye(ivl, msgFile) ; fflush(msgFile) ; } } /* ------------------------ free the working storage ------------------------ */ IVfree(counts) ; if ( outbuffer != NULL ) { IVfree(outbuffer) ; } if ( inbuffer != NULL ) { IVfree(inbuffer) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n leaving IVL_MPI_gatherall()") ; fflush(msgFile) ; } return ; }
/* ------------------------------------------------------------------- purpose -- take an adjacency structure in the (offsets[neqns+1], adjncy[*]) form and load the Graph object g -- pointer to Graph object, must be initialized with nvtx = neqns neqns -- # of equations offsets -- offsets vector adjncy -- big adjacency vector note, the adjacency for list v is found in adjncy[offsets[v]:offsets[v+1]-1] also note, offsets[] and adjncy[] must be zero based, if (offsets,adjncy) come from a harwell-boeing file, they use the fortran numbering, so each value must be decremented to conform with C's zero based numbering flag -- task flag flag = 0 --> just set the adjacency list for v to be that found in adjncy[offsets[v]:offsets[v+1]-1] flag = 1 --> the input adjancency is just the upper triangle (or strict upper triangle) as from a harwell-boeing file. fill the Graph object with the full adjacency structure, including (v,v) edges created -- 96mar16, cca ------------------------------------------------------------------- */ void Graph_fillFromOffsets ( Graph *g, int neqns, int offsets[], int adjncy[], int flag ) { IVL *adjIVL ; /* --------------- check the input --------------- */ if ( g == NULL || neqns <= 0 || offsets == NULL || adjncy == NULL || flag < 0 || flag > 1 ) { fprintf(stderr, "\n fatal error in Graph_fillFromOffsets(%p,%d,%p,%p,%d)" "\n bad input\n", g, neqns, offsets, adjncy, flag) ; exit(-1) ; } /* --------------------------- initialize the Graph object --------------------------- */ Graph_init1(g, 0, neqns, 0, 0, IVL_CHUNKED, IVL_CHUNKED) ; adjIVL = g->adjIVL ; if ( flag == 0 ) { int count, ii, nedge, v, w ; int *list, *mark ; /* ---------------------------------------------- simple map, do not enforce symmetric structure ---------------------------------------------- */ list = IVinit(neqns, -1) ; mark = IVinit(neqns, -1) ; for ( v = 0, nedge = 0 ; v < neqns ; v++ ) { count = 0 ; for ( ii = offsets[v] ; ii < offsets[v+1] ; ii++ ) { w = adjncy[ii] ; if ( v == neqns ) { fprintf(stdout, "\n hey there!! (v,w) = (%d,%d)", v, w) ; } if ( 0 <= w && w < neqns && mark[w] != v ) { list[count++] = w ; mark[w] = v ; } } if ( mark[v] != v ) { list[count++] = v ; mark[v] = v ; } IVqsortUp(count, list) ; IVL_setList(adjIVL, v, count, list) ; nedge += count ; } g->totvwght = neqns ; g->totewght = g->nedges = nedge ; /* ---------------------------- now free the working storage ---------------------------- */ IVfree(list) ; IVfree(mark) ; } else { int ii, jj, u, v, vsize, w ; int *head, *link, *list, *sizes, *vadj ; int **p_adj ; /* ------------------------------------------- enforce symmetric structure and (v,v) edges make a first pass to check the input ------------------------------------------- */ fprintf(stdout, "\n offsets") ; IVfprintf(stdout, neqns+1, offsets) ; for ( v = 0 ; v < neqns ; v++ ) { fprintf(stdout, "\n v = %d", v) ; for ( ii = offsets[v] ; ii < offsets[v+1] ; ii++ ) { fprintf(stdout, "\n w = %d", adjncy[ii]) ; if ( (w = adjncy[ii]) < v || neqns <= w ) { fprintf(stderr, "\n fatal error in Graph_fillFromOffsets(%p,%d,%p,%p,%d)" "\n list %d, entry %d\n", g, neqns, offsets, adjncy, flag, v, w) ; exit(-1) ; } } } head = IVinit(neqns, -1) ; link = IVinit(neqns, -1) ; list = IVinit(neqns, -1) ; sizes = IVinit(neqns, 0) ; p_adj = PIVinit(neqns) ; for ( v = 0 ; v < neqns ; v++ ) { vsize = 0 ; /* ------------------------- add edges to vertices < v ------------------------- */ while ( (u = head[v]) != -1 ) { head[v] = link[u] ; list[vsize++] = u ; if ( --sizes[u] > 0 ) { w = *(++p_adj[u]) ; link[u] = head[w] ; head[w] = u ; } } /* ----------------- add in edge (v,v) ----------------- */ list[vsize++] = v ; jj = vsize ; /* ------------------------- add edges to vertices > v ------------------------- */ for ( ii = offsets[v] ; ii < offsets[v+1] ; ii++ ) { if ( (w = adjncy[ii]) != v ) { list[vsize++] = w ; } } /* --------------------- sort and set the list --------------------- */ IVqsortUp(vsize, list) ; IVL_setList(adjIVL, v, vsize, list) ; /* -------------------------------------------------- link v to first vertex in its lists greater than v -------------------------------------------------- */ if ( jj < vsize ) { IVL_listAndSize(adjIVL, v, &vsize, &vadj) ; w = vadj[jj] ; link[v] = head[w] ; head[w] = v ; sizes[v] = vsize - jj ; p_adj[v] = &vadj[jj] ; } g->nedges += vsize ; } g->totvwght = neqns ; g->totewght = g->nedges ; /* ---------------------------- now free the working storage ---------------------------- */ IVfree(head) ; IVfree(link) ; IVfree(list) ; IVfree(sizes) ; PIVfree(p_adj) ; } return ; }
/*--------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) /* -------------------------------------------------------------------- this program tests the Graph_MPI_Bcast() method (1) process root generates a random Graph object and computes its checksum (2) process root broadcasts the Graph object to the other processors (3) each process computes the checksum of its Graph object (4) the checksums are compared on root created -- 98sep10, cca -------------------------------------------------------------------- */ { char *buffer ; double chksum, t1, t2 ; double *sums ; Drand drand ; int iproc, length, loc, msglvl, myid, nitem, nproc, nvtx, root, seed, size, type, v ; int *list ; FILE *msgFile ; Graph *graph ; /* --------------------------------------------------------------- find out the identity of this process and the number of process --------------------------------------------------------------- */ MPI_Init(&argc, &argv) ; MPI_Comm_rank(MPI_COMM_WORLD, &myid) ; MPI_Comm_size(MPI_COMM_WORLD, &nproc) ; fprintf(stdout, "\n process %d of %d, argc = %d", myid, nproc, argc) ; fflush(stdout) ; if ( argc != 8 ) { fprintf(stdout, "\n\n usage : %s msglvl msgFile type nvtx nitem root seed " "\n msglvl -- message level" "\n msgFile -- message file" "\n type -- type of graph" "\n nvtx -- # of vertices" "\n nitem -- # of items used to generate graph" "\n root -- root processor for broadcast" "\n seed -- random number seed" "\n", argv[0]) ; return(0) ; } msglvl = atoi(argv[1]) ; if ( strcmp(argv[2], "stdout") == 0 ) { msgFile = stdout ; } else { length = strlen(argv[2]) + 1 + 4 ; buffer = CVinit(length, '\0') ; sprintf(buffer, "%s.%d", argv[2], myid) ; if ( (msgFile = fopen(buffer, "w")) == NULL ) { fprintf(stderr, "\n fatal error in %s" "\n unable to open file %s\n", argv[0], argv[2]) ; return(-1) ; } CVfree(buffer) ; } type = atoi(argv[3]) ; nvtx = atoi(argv[4]) ; nitem = atoi(argv[5]) ; root = atoi(argv[6]) ; seed = atoi(argv[7]) ; fprintf(msgFile, "\n %s " "\n msglvl -- %d" "\n msgFile -- %s" "\n type -- %d" "\n nvtx -- %d" "\n nitem -- %d" "\n root -- %d" "\n seed -- %d" "\n", argv[0], msglvl, argv[2], type, nvtx, nitem, root, seed) ; fflush(msgFile) ; /* ----------------------- set up the Graph object ----------------------- */ MARKTIME(t1) ; graph = Graph_new() ; if ( myid == root ) { InpMtx *inpmtx ; int nedges, totewght, totvwght, v ; int *adj, *vwghts ; IVL *adjIVL, *ewghtIVL ; /* ----------------------- generate a random graph ----------------------- */ inpmtx = InpMtx_new() ; InpMtx_init(inpmtx, INPMTX_BY_ROWS, INPMTX_INDICES_ONLY, nitem, 0) ; Drand_setDefaultFields(&drand) ; Drand_setSeed(&drand, seed) ; Drand_setUniform(&drand, 0, nvtx) ; Drand_fillIvector(&drand, nitem, InpMtx_ivec1(inpmtx)) ; Drand_fillIvector(&drand, nitem, InpMtx_ivec2(inpmtx)) ; InpMtx_setNent(inpmtx, nitem) ; InpMtx_changeStorageMode(inpmtx, INPMTX_BY_VECTORS) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n inpmtx mtx filled with raw entries") ; InpMtx_writeForHumanEye(inpmtx, msgFile) ; fflush(msgFile) ; } adjIVL = InpMtx_fullAdjacency(inpmtx) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n full adjacency structure") ; IVL_writeForHumanEye(adjIVL, msgFile) ; fflush(msgFile) ; } nedges = adjIVL->tsize ; if ( type == 1 || type == 3 ) { Drand_setUniform(&drand, 1, 10) ; vwghts = IVinit(nvtx, 0) ; Drand_fillIvector(&drand, nvtx, vwghts) ; totvwght = IVsum(nvtx, vwghts) ; if ( msglvl > 2 ) { fprintf(msgFile, "\n\n vertex weights") ; IVfprintf(msgFile, nvtx, vwghts) ; fflush(msgFile) ; } } else { vwghts = NULL ; totvwght = nvtx ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n totvwght %d", totvwght) ; fflush(msgFile) ; } if ( type == 2 || type == 3 ) { ewghtIVL = IVL_new() ; IVL_init1(ewghtIVL, IVL_CHUNKED, nvtx) ; Drand_setUniform(&drand, 1, 100) ; totewght = 0 ; for ( v = 0 ; v < nvtx ; v++ ) { IVL_listAndSize(adjIVL, v, &size, &adj) ; IVL_setList(ewghtIVL, v, size, NULL) ; IVL_listAndSize(ewghtIVL, v, &size, &adj) ; Drand_fillIvector(&drand, size, adj) ; totewght += IVsum(size, adj) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n ewghtIVL") ; IVL_writeForHumanEye(ewghtIVL, msgFile) ; fflush(msgFile) ; } } else { ewghtIVL = NULL ; totewght = nedges ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n totewght %d", totewght) ; fflush(msgFile) ; } Graph_init2(graph, type, nvtx, 0, nedges, totvwght, totewght, adjIVL, vwghts, ewghtIVL) ; InpMtx_free(inpmtx) ; } MARKTIME(t2) ; fprintf(msgFile, "\n CPU %8.3f : initialize the Graph object", t2 - t1) ; fflush(msgFile) ; if ( msglvl > 2 ) { Graph_writeForHumanEye(graph, msgFile) ; } else { Graph_writeStats(graph, msgFile) ; } fflush(msgFile) ; if ( myid == root ) { /* ---------------------------------------- compute the checksum of the Graph object ---------------------------------------- */ chksum = graph->type + graph->nvtx + graph->nvbnd + graph->nedges + graph->totvwght + graph->totewght ; for ( v = 0 ; v < nvtx ; v++ ) { IVL_listAndSize(graph->adjIVL, v, &size, &list) ; chksum += 1 + v + size + IVsum(size, list) ; } if ( graph->vwghts != NULL ) { chksum += IVsum(nvtx, graph->vwghts) ; } if ( graph->ewghtIVL != NULL ) { for ( v = 0 ; v < nvtx ; v++ ) { IVL_listAndSize(graph->ewghtIVL, v, &size, &list) ; chksum += 1 + v + size + IVsum(size, list) ; } } fprintf(msgFile, "\n\n local chksum = %12.4e", chksum) ; fflush(msgFile) ; } /* -------------------------- broadcast the Graph object -------------------------- */ MARKTIME(t1) ; graph = Graph_MPI_Bcast(graph, root, msglvl, msgFile, MPI_COMM_WORLD) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %8.3f : broadcast the Graph object", t2 - t1) ; if ( msglvl > 2 ) { Graph_writeForHumanEye(graph, msgFile) ; } else { Graph_writeStats(graph, msgFile) ; } /* ---------------------------------------- compute the checksum of the Graph object ---------------------------------------- */ chksum = graph->type + graph->nvtx + graph->nvbnd + graph->nedges + graph->totvwght + graph->totewght ; for ( v = 0 ; v < nvtx ; v++ ) { IVL_listAndSize(graph->adjIVL, v, &size, &list) ; chksum += 1 + v + size + IVsum(size, list) ; } if ( graph->vwghts != NULL ) { chksum += IVsum(nvtx, graph->vwghts) ; } if ( graph->ewghtIVL != NULL ) { for ( v = 0 ; v < nvtx ; v++ ) { IVL_listAndSize(graph->ewghtIVL, v, &size, &list) ; chksum += 1 + v + size + IVsum(size, list) ; } } fprintf(msgFile, "\n\n local chksum = %12.4e", chksum) ; fflush(msgFile) ; /* --------------------------------------- gather the checksums from the processes --------------------------------------- */ sums = DVinit(nproc, 0.0) ; MPI_Gather((void *) &chksum, 1, MPI_DOUBLE, (void *) sums, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD) ; if ( myid == 0 ) { fprintf(msgFile, "\n\n sums") ; DVfprintf(msgFile, nproc, sums) ; for ( iproc = 0 ; iproc < nproc ; iproc++ ) { sums[iproc] -= chksum ; } fprintf(msgFile, "\n\n errors") ; DVfprintf(msgFile, nproc, sums) ; fprintf(msgFile, "\n\n maxerror = %12.4e", DVmax(nproc, sums, &loc)); } /* ---------------- free the objects ---------------- */ DVfree(sums) ; Graph_free(graph) ; /* ------------------------ exit the MPI environment ------------------------ */ MPI_Finalize() ; fprintf(msgFile, "\n") ; fclose(msgFile) ; return(0) ; }
/*--------------------------------------------------------------------*/ int main ( int argc, char *argv[] ) /* ------------------------------------------------- this program tests the IVL_MPI_allgather() method (1) each process generates the same owners[n] map (2) each process creates an IVL object and fills its owned lists with random numbers (3) the processes gather-all's the lists of ivl created -- 98apr03, cca ------------------------------------------------- */ { char *buffer ; double chksum, globalsum, t1, t2 ; Drand drand ; int ilist, length, myid, msglvl, nlist, nproc, rc, seed, size, tag ; int *list, *owners, *vec ; int stats[4], tstats[4] ; IV *ownersIV ; IVL *ivl ; FILE *msgFile ; /* --------------------------------------------------------------- find out the identity of this process and the number of process --------------------------------------------------------------- */ MPI_Init(&argc, &argv) ; MPI_Comm_rank(MPI_COMM_WORLD, &myid) ; MPI_Comm_size(MPI_COMM_WORLD, &nproc) ; fprintf(stdout, "\n process %d of %d, argc = %d", myid, nproc, argc) ; fflush(stdout) ; if ( argc != 5 ) { fprintf(stdout, "\n\n usage : %s msglvl msgFile n seed " "\n msglvl -- message level" "\n msgFile -- message file" "\n nlist -- number of lists in the IVL object" "\n seed -- random number seed" "\n", argv[0]) ; return(0) ; } msglvl = atoi(argv[1]) ; if ( strcmp(argv[2], "stdout") == 0 ) { msgFile = stdout ; } else { length = strlen(argv[2]) + 1 + 4 ; buffer = CVinit(length, '\0') ; sprintf(buffer, "%s.%d", argv[2], myid) ; if ( (msgFile = fopen(buffer, "w")) == NULL ) { fprintf(stderr, "\n fatal error in %s" "\n unable to open file %s\n", argv[0], argv[2]) ; return(-1) ; } CVfree(buffer) ; } nlist = atoi(argv[3]) ; seed = atoi(argv[4]) ; fprintf(msgFile, "\n %s " "\n msglvl -- %d" "\n msgFile -- %s" "\n nlist -- %d" "\n seed -- %d" "\n", argv[0], msglvl, argv[2], nlist, seed) ; fflush(msgFile) ; /* ---------------------------- generate the ownersIV object ---------------------------- */ MARKTIME(t1) ; ownersIV = IV_new() ; IV_init(ownersIV, nlist, NULL) ; owners = IV_entries(ownersIV) ; Drand_setDefaultFields(&drand) ; Drand_setSeed(&drand, seed) ; Drand_setUniform(&drand, 0, nproc) ; Drand_fillIvector(&drand, nlist, owners) ; MARKTIME(t2) ; fprintf(msgFile, "\n CPU %8.3f : initialize the ownersIV object", t2 - t1) ; fflush(msgFile) ; fprintf(msgFile, "\n\n ownersIV generated") ; if ( msglvl > 2 ) { IV_writeForHumanEye(ownersIV, msgFile) ; } else { IV_writeStats(ownersIV, msgFile) ; } fflush(msgFile) ; /* -------------------------------------------- set up the IVL object and fill owned entries -------------------------------------------- */ MARKTIME(t1) ; ivl = IVL_new() ; IVL_init1(ivl, IVL_CHUNKED, nlist) ; vec = IVinit(nlist, -1) ; Drand_setSeed(&drand, seed + myid) ; Drand_setUniform(&drand, 0, nlist) ; for ( ilist = 0 ; ilist < nlist ; ilist++ ) { if ( owners[ilist] == myid ) { size = (int) Drand_value(&drand) ; Drand_fillIvector(&drand, size, vec) ; IVL_setList(ivl, ilist, size, vec) ; } } MARKTIME(t2) ; fprintf(msgFile, "\n CPU %8.3f : initialize the IVL object", t2 - t1) ; fflush(msgFile) ; if ( msglvl > 2 ) { IVL_writeForHumanEye(ivl, msgFile) ; } else { IVL_writeStats(ivl, msgFile) ; } fflush(msgFile) ; /* -------------------------------------------- compute the local checksum of the ivl object -------------------------------------------- */ for ( ilist = 0, chksum = 0.0 ; ilist < nlist ; ilist++ ) { if ( owners[ilist] == myid ) { IVL_listAndSize(ivl, ilist, &size, &list) ; chksum += 1 + ilist + size + IVsum(size, list) ; } } fprintf(msgFile, "\n\n local partial chksum = %12.4e", chksum) ; fflush(msgFile) ; /* ----------------------- get the global checksum ----------------------- */ rc = MPI_Allreduce((void *) &chksum, (void *) &globalsum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD) ; /* -------------------------------- execute the all-gather operation -------------------------------- */ tag = 47 ; IVzero(4, stats) ; IVL_MPI_allgather(ivl, ownersIV, stats, msglvl, msgFile, tag, MPI_COMM_WORLD) ; if ( msglvl > 0 ) { fprintf(msgFile, "\n\n return from IVL_MPI_allgather()") ; fprintf(msgFile, "\n local send stats : %10d messages with %10d bytes" "\n local recv stats : %10d messages with %10d bytes", stats[0], stats[2], stats[1], stats[3]) ; fflush(msgFile) ; } MPI_Reduce((void *) stats, (void *) tstats, 4, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD) ; if ( myid == 0 ) { fprintf(msgFile, "\n total send stats : %10d messages with %10d bytes" "\n total recv stats : %10d messages with %10d bytes", tstats[0], tstats[2], tstats[1], tstats[3]) ; fflush(msgFile) ; } if ( msglvl > 2 ) { fprintf(msgFile, "\n\n ivl") ; IVL_writeForHumanEye(ivl, msgFile) ; fflush(msgFile) ; } /* ----------------------------------------- compute the checksum of the entire object ----------------------------------------- */ for ( ilist = 0, chksum = 0.0 ; ilist < nlist ; ilist++ ) { IVL_listAndSize(ivl, ilist, &size, &list) ; chksum += 1 + ilist + size + IVsum(size, list) ; } fprintf(msgFile, "\n globalsum = %12.4e, chksum = %12.4e, error = %12.4e", globalsum, chksum, fabs(globalsum - chksum)) ; fflush(msgFile) ; /* ---------------- free the objects ---------------- */ IV_free(ownersIV) ; IVL_free(ivl) ; /* ------------------------ exit the MPI environment ------------------------ */ MPI_Finalize() ; fprintf(msgFile, "\n") ; fclose(msgFile) ; return(0) ; }
/* ---------------------------------------------- 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 ; }
/* --------------------------------------------------------------- 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 ; }