⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 get_perm_c.c

📁 SuperLU 2.2版本。对大型、稀疏、非对称的线性系统的直接求解
💻 C
字号:
/* * -- Distributed SuperLU routine (version 2.1) -- * Lawrence Berkeley National Lab, Univ. of California Berkeley, * November 1, 2007 * Feburary 20, 2008 */#include "superlu_ddefs.h"voidget_metis(	  int_t n,         /* dimension of matrix B */	  int_t bnz,       /* number of nonzeros in matrix A. */	  int_t *b_colptr, /* column pointer of size n+1 for matrix B. */	  int_t *b_rowind, /* row indices of size bnz for matrix B. */	  int_t *perm_c    /* out - the column permutation vector. */	  ){#define METISOPTIONS 8    int ct, i, j, nm, numflag = 0; /* C-Style ordering */    int metis_options[METISOPTIONS];    int_t *perm, *iperm;    metis_options[0] = 0; /* Use Defaults for now */    perm = intMalloc_dist(n);    iperm = intMalloc_dist(n);    nm = n;#ifdef USE_METIS    /* Call metis */#undef USEEND#ifdef USEEND      METIS_EdgeND(&nm, b_colptr, b_rowind, &numflag, metis_options,		   perm, iperm);#else      METIS_NodeND(&nm, b_colptr, b_rowind, &numflag, metis_options,		   perm, iperm);#endif#endif      /* Copy the permutation vector into SuperLU data structure. */      for (i = 0; i < n; ++i) perm_c[i] = iperm[i];      SUPERLU_FREE(b_colptr);      SUPERLU_FREE(b_rowind);      SUPERLU_FREE(perm);      SUPERLU_FREE(iperm);}voidgetata_dist(	    const int_t m,    /* number of rows in matrix A. */	    const int_t n,    /* number of columns in matrix A. */	    const int_t nz,   /* number of nonzeros in matrix A */	    int_t *colptr,    /* column pointer of size n+1 for matrix A. */	    int_t *rowind,    /* row indices of size nz for matrix A. */	    int_t *atanz,     /* out - on exit, returns the actual number of				 nonzeros in matrix A'*A. */	    int_t **ata_colptr, /* out - size n+1 */	    int_t **ata_rowind  /* out - size *atanz */	    ){/* * Purpose * ======= * * Form the structure of A'*A. A is an m-by-n matrix in column oriented * format represented by (colptr, rowind). The output A'*A is in column * oriented format (symmetrically, also row oriented), represented by * (ata_colptr, ata_rowind). * * This routine is modified from GETATA routine by Tim Davis. * The complexity of this algorithm is: SUM_{i=1,m} r(i)^2, * i.e., the sum of the square of the row counts. * * Questions * ========= *     o  Do I need to withhold the *dense* rows? *     o  How do I know the number of nonzeros in A'*A? *  */    register int_t i, j, k, col, num_nz, ti, trow;    int_t *marker, *b_colptr, *b_rowind;    int_t *t_colptr, *t_rowind; /* a column oriented form of T = A' */    if ( !(marker = (int_t*) SUPERLU_MALLOC( (SUPERLU_MAX(m,n)+1) * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC fails for marker[]");    if ( !(t_colptr = (int_t*) SUPERLU_MALLOC( (m+1) * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC t_colptr[]");    if ( !(t_rowind = (int_t*) SUPERLU_MALLOC( nz * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC fails for t_rowind[]");        /* Get counts of each column of T, and set up column pointers */    for (i = 0; i < m; ++i) marker[i] = 0;    for (j = 0; j < n; ++j) {	for (i = colptr[j]; i < colptr[j+1]; ++i)	    ++marker[rowind[i]];    }    t_colptr[0] = 0;    for (i = 0; i < m; ++i) {	t_colptr[i+1] = t_colptr[i] + marker[i];	marker[i] = t_colptr[i];    }    /* Transpose the matrix from A to T */    for (j = 0; j < n; ++j)	for (i = colptr[j]; i < colptr[j+1]; ++i) {	    col = rowind[i];	    t_rowind[marker[col]] = j;	    ++marker[col];	}        /* ----------------------------------------------------------------       compute B = T * A, where column j of B is:       Struct (B_*j) =    UNION   ( Struct (T_*k) )                        A_kj != 0       do not include the diagonal entry          ( Partition A as: A = (A_*1, ..., A_*n)         Then B = T * A = (T * A_*1, ..., T * A_*n), where         T * A_*j = (T_*1, ..., T_*m) * A_*j.  )       ---------------------------------------------------------------- */    /* Zero the diagonal flag */    for (i = 0; i < n; ++i) marker[i] = -1;    /* First pass determines number of nonzeros in B */    num_nz = 0;    for (j = 0; j < n; ++j) {	/* Flag the diagonal so it's not included in the B matrix */	marker[j] = j;	for (i = colptr[j]; i < colptr[j+1]; ++i) {	    /* A_kj is nonzero, add pattern of column T_*k to B_*j */	    k = rowind[i];	    for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) {		trow = t_rowind[ti];		if ( marker[trow] != j ) {		    marker[trow] = j;		    num_nz++;		}	    }	}    }    *atanz = num_nz;        /* Allocate storage for A'*A */    if ( !(*ata_colptr = (int_t*) SUPERLU_MALLOC( (n+1) * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC fails for ata_colptr[]");    if ( *atanz ) {	if ( !(*ata_rowind = (int_t*)SUPERLU_MALLOC(*atanz*sizeof(int_t)) ) ) {	    fprintf(stderr, ".. atanz = %ld\n", *atanz);	    ABORT("SUPERLU_MALLOC fails for ata_rowind[]");	}    }    b_colptr = *ata_colptr; /* aliasing */    b_rowind = *ata_rowind;        /* Zero the diagonal flag */    for (i = 0; i < n; ++i) marker[i] = -1;        /* Compute each column of B, one at a time */    num_nz = 0;    for (j = 0; j < n; ++j) {	b_colptr[j] = num_nz;		/* Flag the diagonal so it's not included in the B matrix */	marker[j] = j;	for (i = colptr[j]; i < colptr[j+1]; ++i) {	    /* A_kj is nonzero, add pattern of column T_*k to B_*j */	    k = rowind[i];	    for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) {		trow = t_rowind[ti];		if ( marker[trow] != j ) {		    marker[trow] = j;		    b_rowind[num_nz++] = trow;		}	    }	}    }    b_colptr[n] = num_nz;           SUPERLU_FREE(marker);    SUPERLU_FREE(t_colptr);    SUPERLU_FREE(t_rowind);}voidat_plus_a_dist(	       const int_t n,    /* number of columns in matrix A. */	       const int_t nz,   /* number of nonzeros in matrix A */	       int_t *colptr,    /* column pointer of size n+1 for matrix A. */	       int_t *rowind,    /* row indices of size nz for matrix A. */	       int_t *bnz,       /* out - on exit, returns the actual number of				    nonzeros in matrix A'+A. */	       int_t **b_colptr, /* out - size n+1 */	       int_t **b_rowind  /* out - size *bnz */	       ){/* * Purpose * ======= * * Form the structure of A'+A. A is an n-by-n matrix in column oriented * format represented by (colptr, rowind). The output A'+A is in column * oriented format (symmetrically, also row oriented), represented by * (b_colptr, b_rowind). * */    register int_t i, j, k, col, num_nz;    int_t *t_colptr, *t_rowind; /* a column oriented form of T = A' */    int_t *marker;    if ( !(marker = (int_t*) SUPERLU_MALLOC( n * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC fails for marker[]");    if ( !(t_colptr = (int_t*) SUPERLU_MALLOC( (n+1) * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC fails for t_colptr[]");    if ( !(t_rowind = (int_t*) SUPERLU_MALLOC( nz * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC fails t_rowind[]");        /* Get counts of each column of T, and set up column pointers */    for (i = 0; i < n; ++i) marker[i] = 0;    for (j = 0; j < n; ++j) {	for (i = colptr[j]; i < colptr[j+1]; ++i)	    ++marker[rowind[i]];    }    t_colptr[0] = 0;    for (i = 0; i < n; ++i) {	t_colptr[i+1] = t_colptr[i] + marker[i];	marker[i] = t_colptr[i];    }    /* Transpose the matrix from A to T */    for (j = 0; j < n; ++j)	for (i = colptr[j]; i < colptr[j+1]; ++i) {	    col = rowind[i];	    t_rowind[marker[col]] = j;	    ++marker[col];	}    /* ----------------------------------------------------------------       compute B = A + T, where column j of B is:       Struct (B_*j) = Struct (A_*k) UNION Struct (T_*k)       do not include the diagonal entry       ---------------------------------------------------------------- */    /* Zero the diagonal flag */    for (i = 0; i < n; ++i) marker[i] = -1;    /* First pass determines number of nonzeros in B */    num_nz = 0;    for (j = 0; j < n; ++j) {	/* Flag the diagonal so it's not included in the B matrix */	marker[j] = j;	/* Add pattern of column A_*k to B_*j */	for (i = colptr[j]; i < colptr[j+1]; ++i) {	    k = rowind[i];	    if ( marker[k] != j ) {		marker[k] = j;		++num_nz;	    }	}	/* Add pattern of column T_*k to B_*j */	for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) {	    k = t_rowind[i];	    if ( marker[k] != j ) {		marker[k] = j;		++num_nz;	    }	}    }    *bnz = num_nz;        /* Allocate storage for A+A' */    if ( !(*b_colptr = (int_t*) SUPERLU_MALLOC( (n+1) * sizeof(int_t)) ) )	ABORT("SUPERLU_MALLOC fails for b_colptr[]");    if ( *bnz ) {	if ( !(*b_rowind = (int_t*) SUPERLU_MALLOC( *bnz * sizeof(int_t)) ) )	    ABORT("SUPERLU_MALLOC fails for b_rowind[]");    }        /* Zero the diagonal flag */    for (i = 0; i < n; ++i) marker[i] = -1;        /* Compute each column of B, one at a time */    num_nz = 0;    for (j = 0; j < n; ++j) {	(*b_colptr)[j] = num_nz;		/* Flag the diagonal so it's not included in the B matrix */	marker[j] = j;	/* Add pattern of column A_*k to B_*j */	for (i = colptr[j]; i < colptr[j+1]; ++i) {	    k = rowind[i];	    if ( marker[k] != j ) {		marker[k] = j;		(*b_rowind)[num_nz++] = k;	    }	}	/* Add pattern of column T_*k to B_*j */	for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) {	    k = t_rowind[i];	    if ( marker[k] != j ) {		marker[k] = j;		(*b_rowind)[num_nz++] = k;	    }	}    }    (*b_colptr)[n] = num_nz;           SUPERLU_FREE(marker);    SUPERLU_FREE(t_colptr);    SUPERLU_FREE(t_rowind);} /* at_plus_a_dist */voidget_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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -