static void relax_snode /************************************************************************/ ( const int_t n, /* number of columns in the matrix (input) */ int_t *et, /* column elimination tree (input) */ const int_t relax, /* max no of columns allowed in a relaxed snode (input) */ int_t *desc, /* number of descendants of each etree node. */ int_t *relax_end /* last column in a supernode (output) */ ) { /* * Purpose * ======= * relax_snode() identifies the initial relaxed supernodes, assuming that * the matrix has been reordered according to an postorder of the etree. * */ register int_t j, parent, nsuper; register int_t fsupc; /* beginning of a snode */ ifill_dist(relax_end, n, EMPTY); ifill_dist(desc, n+1, 0); nsuper = 0; /* Compute the number of descendants of each node in the etree. */ for (j = 0; j < n; j++) { parent = et[j]; if ( parent != n ) /* not the dummy root */ desc[parent] += desc[j] + 1; } /* Identify the relaxed supernodes by postorder traversal of the etree. */ for (j = 0; j < n; ) { parent = et[j]; fsupc = j; while ( parent != n && desc[parent] < relax ) { j = parent; parent = et[j]; } /* Found a supernode with j being the last column. */ relax_end[fsupc] = j; /* Last column is recorded. */ ++nsuper; ++j; /* Search for a new leaf. */ while ( desc[j] != 0 && j < n ) ++j; } #if ( PRNTlevel>=2 ) printf(".. No of relaxed snodes: %d\trelax: %d\n", nsuper, relax); #endif } /* RELAX_SNODE */
void super_stats_dist(int_t nsuper, int_t *xsup) { register int_t nsup1 = 0; int_t i, isize, whichb, bl, bh; int_t bucket[NBUCKS]; max_sup_size = 0; for (i = 0; i <= nsuper; i++) { isize = xsup[i+1] - xsup[i]; if ( isize == 1 ) nsup1++; if ( max_sup_size < isize ) max_sup_size = isize; } printf(" Supernode statistics:\n\tno of super = %d\n", nsuper+1); printf("\tmax supernode size = %d\n", max_sup_size); printf("\tno of size 1 supernodes = %d\n", nsup1); /* Histogram of the supernode sizes */ ifill_dist (bucket, NBUCKS, 0); for (i = 0; i <= nsuper; i++) { isize = xsup[i+1] - xsup[i]; whichb = (float) isize / max_sup_size * NBUCKS; if (whichb >= NBUCKS) whichb = NBUCKS - 1; bucket[whichb]++; } printf("\tHistogram of supernode sizes:\n"); for (i = 0; i < NBUCKS; i++) { bl = (float) i * max_sup_size / NBUCKS; bh = (float) (i+1) * max_sup_size / NBUCKS; printf("\tsnode: %d-%d\t\t%d\n", bl+1, bh, bucket[i]); } }
/*! \brief * * <pre> * Purpose * ======= * symbfact() performs a symbolic factorization on matrix A and sets up * the nonzero data structures which are suitable for supernodal Gaussian * elimination with no pivoting (GENP). This routine features: * o depth-first search (DFS) * o supernodes * o symmetric structure pruning * * Return value * ============ * < 0, number of bytes needed for LSUB. * = 0, matrix dimension is 1. * > 0, number of bytes allocated when out of memory. * </pre> */ int_t symbfact /************************************************************************/ ( superlu_options_t *options, /* input options */ int pnum, /* process number */ SuperMatrix *A, /* original matrix A permuted by columns (input) */ int_t *perm_c, /* column permutation vector (input) */ int_t *etree, /* column elimination tree (input) */ Glu_persist_t *Glu_persist, /* output */ Glu_freeable_t *Glu_freeable /* output */ ) { int_t m, n, min_mn, j, i, k, irep, nseg, pivrow, info; int_t *iwork, *perm_r, *segrep, *repfnz; int_t *xprune, *marker, *parent, *xplore; int_t relax, *desc, *relax_end; int_t nnzL, nnzU; #if ( DEBUGlevel>=1 ) CHECK_MALLOC(pnum, "Enter symbfact()"); #endif m = A->nrow; n = A->ncol; min_mn = SUPERLU_MIN(m, n); /* Allocate storage common to the symbolic factor routines */ info = symbfact_SubInit(DOFACT, NULL, 0, m, n, ((NCPformat*)A->Store)->nnz, Glu_persist, Glu_freeable); iwork = (int_t *) intMalloc_dist(6*m+2*n); perm_r = iwork; segrep = iwork + m; repfnz = segrep + m; marker = repfnz + m; parent = marker + m; xplore = parent + m; xprune = xplore + m; relax_end = xprune + n; relax = sp_ienv_dist(2); ifill_dist(perm_r, m, EMPTY); ifill_dist(repfnz, m, EMPTY); ifill_dist(marker, m, EMPTY); Glu_persist->supno[0] = -1; Glu_persist->xsup[0] = 0; Glu_freeable->xlsub[0] = 0; Glu_freeable->xusub[0] = 0; /*for (j = 0; j < n; ++j) iperm_c[perm_c[j]] = j;*/ /* Identify relaxed supernodes. */ if ( !(desc = intMalloc_dist(n+1)) ) ABORT("Malloc fails for desc[]");; relax_snode(n, etree, relax, desc, relax_end); SUPERLU_FREE(desc); for (j = 0; j < min_mn; ) { if ( relax_end[j] != EMPTY ) { /* beginning of a relaxed snode */ k = relax_end[j]; /* end of the relaxed snode */ /* Determine union of the row structure of supernode (j:k). */ if ( (info = snode_dfs(A, j, k, xprune, marker, Glu_persist, Glu_freeable)) != 0 ) return info; for (i = j; i <= k; ++i) pivotL(i, perm_r, &pivrow, Glu_persist, Glu_freeable); j = k+1; } else { /* Perform a symbolic factorization on column j, and detects whether column j starts a new supernode. */ if ((info = column_dfs(A, j, perm_r, &nseg, segrep, repfnz, xprune, marker, parent, xplore, Glu_persist, Glu_freeable)) != 0) return info; /* Copy the U-segments to usub[*]. */ if ((info = set_usub(min_mn, j, nseg, segrep, repfnz, Glu_persist, Glu_freeable)) != 0) return info; pivotL(j, perm_r, &pivrow, Glu_persist, Glu_freeable); /* Prune columns [0:j-1] using column j. */ pruneL(j, perm_r, pivrow, nseg, segrep, repfnz, xprune, Glu_persist, Glu_freeable); /* Reset repfnz[*] to prepare for the next column. */ for (i = 0; i < nseg; i++) { irep = segrep[i]; repfnz[irep] = EMPTY; } ++j; } /* else */ } /* for j ... */ countnz_dist(min_mn, xprune, &nnzL, &nnzU, Glu_persist, Glu_freeable); /* Apply perm_r to L; Compress LSUB array. */ i = fixupL_dist(min_mn, perm_r, Glu_persist, Glu_freeable); if ( !pnum && (options->PrintStat == YES)) { printf("\tNonzeros in L %ld\n", nnzL); printf("\tNonzeros in U %ld\n", nnzU); printf("\tnonzeros in L+U %ld\n", nnzL + nnzU - min_mn); printf("\tnonzeros in LSUB %ld\n", i); } SUPERLU_FREE(iwork); #if ( PRNTlevel>=3 ) PrintInt10("lsub", Glu_freeable->xlsub[n], Glu_freeable->lsub); PrintInt10("xlsub", n+1, Glu_freeable->xlsub); PrintInt10("xprune", n, xprune); PrintInt10("usub", Glu_freeable->xusub[n], Glu_freeable->usub); PrintInt10("xusub", n+1, Glu_freeable->xusub); PrintInt10("supno", n, Glu_persist->supno); PrintInt10("xsup", (Glu_persist->supno[n])+2, Glu_persist->xsup); #endif #if ( DEBUGlevel>=1 ) CHECK_MALLOC(pnum, "Exit symbfact()"); #endif return (-i); } /* SYMBFACT */