/*! \brief * * <pre> * Purpose * ======= * * GET_PERM_C_DIST obtains a permutation matrix Pc, by applying the multiple * minimum degree ordering code by Joseph Liu to matrix A'*A or A+A', * or using approximate minimum degree column ordering by Davis et. al. * The LU factorization of A*Pc tends to have less fill than the LU * factorization of A. * * Arguments * ========= * * ispec (input) colperm_t * Specifies what type of column permutation to use to reduce fill. * = NATURAL: natural ordering (i.e., Pc = I) * = MMD_AT_PLUS_A: minimum degree ordering on structure of A'+A * = MMD_ATA: minimum degree ordering on structure of A'*A * = METIS_AT_PLUS_A: MeTis on A'+A * * A (input) SuperMatrix* * Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number * of the linear equations is A->nrow. Currently, the type of A * can be: Stype = SLU_NC; Dtype = SLU_D; Mtype = SLU_GE. * In the future, more general A can be handled. * * perm_c (output) int* * Column permutation vector of size A->ncol, which defines the * permutation matrix Pc; perm_c[i] = j means column i of A is * in position j in A*Pc. * </pre> */ void get_perm_c_dist(int_t pnum, int_t ispec, SuperMatrix *A, int_t *perm_c) { NCformat *Astore = A->Store; int_t m, n, bnz = 0, *b_colptr, *b_rowind, i; int_t delta, maxint, nofsub, *invp; int_t *dhead, *qsize, *llist, *marker; double t, SuperLU_timer_(); #if ( DEBUGlevel>=1 ) CHECK_MALLOC(pnum, "Enter get_perm_c_dist()"); #endif m = A->nrow; n = A->ncol; t = SuperLU_timer_(); switch ( ispec ) { case NATURAL: /* Natural ordering */ for (i = 0; i < n; ++i) perm_c[i] = i; #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use natural column ordering\n"); #endif return; case MMD_AT_PLUS_A: /* Minimum degree ordering on A'+A */ if ( m != n ) ABORT("Matrix is not square"); at_plus_a_dist(n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); t = SuperLU_timer_() - t; /*printf("Form A'+A time = %8.3f\n", t);*/ #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use minimum degree ordering on A'+A.\n"); #endif break; case MMD_ATA: /* Minimum degree ordering on A'*A */ getata_dist(m, n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); t = SuperLU_timer_() - t; /*printf("Form A'*A time = %8.3f\n", t);*/ #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use minimum degree ordering on A'*A\n"); #endif break; case METIS_AT_PLUS_A: /* METIS ordering on A'+A */ if ( m != n ) ABORT("Matrix is not square"); at_plus_a_dist(n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); if ( bnz ) { /* non-empty adjacency structure */ get_metis(n, bnz, b_colptr, b_rowind, perm_c); } else { /* e.g., diagonal matrix */ for (i = 0; i < n; ++i) perm_c[i] = i; SUPERLU_FREE(b_colptr); /* b_rowind is not allocated in this case */ } #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use METIS ordering on A'+A\n"); #endif return; default: ABORT("Invalid ISPEC"); } if ( bnz ) { t = SuperLU_timer_(); /* Initialize and allocate storage for GENMMD. */ delta = 0; /* DELTA is a parameter to allow the choice of nodes whose degree <= min-degree + DELTA. */ maxint = 2147483647; /* 2**31 - 1 */ invp = (int_t *) SUPERLU_MALLOC((n+delta)*sizeof(int_t)); if ( !invp ) ABORT("SUPERLU_MALLOC fails for invp."); dhead = (int_t *) SUPERLU_MALLOC((n+delta)*sizeof(int_t)); if ( !dhead ) ABORT("SUPERLU_MALLOC fails for dhead."); qsize = (int_t *) SUPERLU_MALLOC((n+delta)*sizeof(int_t)); if ( !qsize ) ABORT("SUPERLU_MALLOC fails for qsize."); llist = (int_t *) SUPERLU_MALLOC(n*sizeof(int_t)); if ( !llist ) ABORT("SUPERLU_MALLOC fails for llist."); marker = (int_t *) SUPERLU_MALLOC(n*sizeof(int_t)); if ( !marker ) ABORT("SUPERLU_MALLOC fails for marker."); /* Transform adjacency list into 1-based indexing required by GENMMD.*/ for (i = 0; i <= n; ++i) ++b_colptr[i]; for (i = 0; i < bnz; ++i) ++b_rowind[i]; genmmd_dist_(&n, b_colptr, b_rowind, perm_c, invp, &delta, dhead, qsize, llist, marker, &maxint, &nofsub); /* Transform perm_c into 0-based indexing. */ for (i = 0; i < n; ++i) --perm_c[i]; SUPERLU_FREE(invp); SUPERLU_FREE(dhead); SUPERLU_FREE(qsize); SUPERLU_FREE(llist); SUPERLU_FREE(marker); SUPERLU_FREE(b_rowind); t = SuperLU_timer_() - t; /* printf("call GENMMD time = %8.3f\n", t);*/ } else { /* Empty adjacency structure */ for (i = 0; i < n; ++i) perm_c[i] = i; } SUPERLU_FREE(b_colptr); #if ( DEBUGlevel>=1 ) CHECK_MALLOC(pnum, "Exit get_perm_c_dist()"); #endif } /* get_perm_c_dist */
void get_perm_c_dist(int_t pnum, int_t ispec, SuperMatrix *A, int_t *perm_c) /* * Purpose * ======= * * GET_PERM_C_DIST obtains a permutation matrix Pc, by applying the multiple * minimum degree ordering code by Joseph Liu to matrix A'*A or A+A', * or using approximate minimum degree column ordering by Davis et. al. * The LU factorization of A*Pc tends to have less fill than the LU * factorization of A. * * Arguments * ========= * * ispec (input) colperm_t * Specifies what type of column permutation to use to reduce fill. * = NATURAL: natural ordering (i.e., Pc = I) * = MMD_AT_PLUS_A: minimum degree ordering on structure of A'+A * = MMD_ATA: minimum degree ordering on structure of A'*A * = METIS_AT_PLUS_A: MeTis on A'+A * * A (input) SuperMatrix* * Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number * of the linear equations is A->nrow. Currently, the type of A * can be: Stype = SLU_NC; Dtype = SLU_D; Mtype = SLU_GE. * In the future, more general A can be handled. * * perm_c (output) int* * Column permutation vector of size A->ncol, which defines the * permutation matrix Pc; perm_c[i] = j means column i of A is * in position j in A*Pc. * */ { NCformat *Astore = A->Store; int_t m, n, bnz = 0, *b_colptr, *b_rowind, i; int_t delta, maxint, nofsub, *invp; int_t *dhead, *qsize, *llist, *marker; double t, SuperLU_timer_(); #if ( DEBUGlevel>=1 ) CHECK_MALLOC(pnum, "Enter get_perm_c_dist()"); #endif m = A->nrow; n = A->ncol; t = SuperLU_timer_(); switch ( ispec ) { case NATURAL: /* Natural ordering */ for (i = 0; i < n; ++i) perm_c[i] = i; #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use natural column ordering\n"); #endif return; case MMD_AT_PLUS_A: /* Minimum degree ordering on A'+A */ if ( m != n ) ABORT("Matrix is not square"); at_plus_a_dist(n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); t = SuperLU_timer_() - t; /*printf("Form A'+A time = %8.3f\n", t);*/ #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use minimum degree ordering on A'+A.\n"); #endif break; case MMD_ATA: /* Minimum degree ordering on A'*A */ getata_dist(m, n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); t = SuperLU_timer_() - t; /*printf("Form A'*A time = %8.3f\n", t);*/ #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use minimum degree ordering on A'*A\n"); #endif break; case METIS_AT_PLUS_A: /* METIS ordering on A'+A */ if ( m != n ) ABORT("Matrix is not square"); at_plus_a_dist(n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); get_metis(n, bnz, b_colptr, b_rowind, perm_c); #if ( PRNTlevel>=1 ) if ( !pnum ) printf(".. Use METIS ordering on A'+A\n"); #endif return; default: ABORT("Invalid ISPEC"); } if ( bnz ) { t = SuperLU_timer_(); /* Initialize and allocate storage for GENMMD. */ delta = 0; /* DELTA is a parameter to allow the choice of nodes whose degree <= min-degree + DELTA. */ maxint = 2147483647; /* 2**31 - 1 */ invp = (int_t *) SUPERLU_MALLOC((n+delta)*sizeof(int_t)); if ( !invp ) ABORT("SUPERLU_MALLOC fails for invp."); dhead = (int_t *) SUPERLU_MALLOC((n+delta)*sizeof(int_t)); if ( !dhead ) ABORT("SUPERLU_MALLOC fails for dhead."); qsize = (int_t *) SUPERLU_MALLOC((n+delta)*sizeof(int_t)); if ( !qsize ) ABORT("SUPERLU_MALLOC fails for qsize."); llist = (int_t *) SUPERLU_MALLOC(n*sizeof(int_t)); if ( !llist ) ABORT("SUPERLU_MALLOC fails for llist."); marker = (int_t *) SUPERLU_MALLOC(n*sizeof(int_t)); if ( !marker ) ABORT("SUPERLU_MALLOC fails for marker."); /* Transform adjacency list into 1-based indexing required by GENMMD.*/ for (i = 0; i <= n; ++i) ++b_colptr[i]; for (i = 0; i < bnz; ++i) ++b_rowind[i]; genmmd_dist_(&n, b_colptr, b_rowind, perm_c, invp, &delta, dhead, qsize, llist, marker, &maxint, &nofsub); /* Transform perm_c into 0-based indexing. */ for (i = 0; i < n; ++i) --perm_c[i]; SUPERLU_FREE(invp); SUPERLU_FREE(dhead); SUPERLU_FREE(qsize); SUPERLU_FREE(llist); SUPERLU_FREE(marker); SUPERLU_FREE(b_rowind); t = SuperLU_timer_() - t; /* printf("call GENMMD time = %8.3f\n", t);*/ } else { /* Empty adjacency structure */ for (i = 0; i < n; ++i) perm_c[i] = i; } SUPERLU_FREE(b_colptr); #if ( DEBUGlevel>=1 ) CHECK_MALLOC(pnum, "Exit get_perm_c_dist()"); #endif } /* get_perm_c_dist */