Blender V2.61 - r43446
|
00001 00004 /* 00005 * -- SuperLU routine (version 2.0) -- 00006 * Univ. of California Berkeley, Xerox Palo Alto Research Center, 00007 * and Lawrence Berkeley National Lab. 00008 * November 15, 1997 00009 * 00010 */ 00011 00012 #include "ssp_defs.h" 00013 #include "colamd.h" 00014 00015 extern int genmmd_(int *, int *, int *, int *, int *, int *, int *, 00016 int *, int *, int *, int *, int *); 00017 00018 static void 00019 get_colamd( 00020 const int m, /* number of rows in matrix A. */ 00021 const int n, /* number of columns in matrix A. */ 00022 const int nnz,/* number of nonzeros in matrix A. */ 00023 int *colptr, /* column pointer of size n+1 for matrix A. */ 00024 int *rowind, /* row indices of size nz for matrix A. */ 00025 int *perm_c /* out - the column permutation vector. */ 00026 ) 00027 { 00028 int Alen, *A, i, info, *p; 00029 double *knobs; 00030 int stats[COLAMD_STATS]; 00031 00032 Alen = colamd_recommended(nnz, m, n); 00033 00034 if ( !(knobs = (double *) SUPERLU_MALLOC(COLAMD_KNOBS * sizeof(double))) ) 00035 ABORT("Malloc fails for knobs"); 00036 colamd_set_defaults(knobs); 00037 00038 if (!(A = (int *) SUPERLU_MALLOC(Alen * sizeof(int))) ) 00039 ABORT("Malloc fails for A[]"); 00040 if (!(p = (int *) SUPERLU_MALLOC((n+1) * sizeof(int))) ) 00041 ABORT("Malloc fails for p[]"); 00042 for (i = 0; i <= n; ++i) p[i] = colptr[i]; 00043 for (i = 0; i < nnz; ++i) A[i] = rowind[i]; 00044 info = colamd(m, n, Alen, A, p, knobs, stats); 00045 if ( info == FALSE ) ABORT("COLAMD failed"); 00046 00047 for (i = 0; i < n; ++i) perm_c[p[i]] = i; 00048 00049 SUPERLU_FREE(knobs); 00050 SUPERLU_FREE(A); 00051 SUPERLU_FREE(p); 00052 } 00053 00054 static void 00055 getata( 00056 const int m, /* number of rows in matrix A. */ 00057 const int n, /* number of columns in matrix A. */ 00058 const int nz, /* number of nonzeros in matrix A */ 00059 int *colptr, /* column pointer of size n+1 for matrix A. */ 00060 int *rowind, /* row indices of size nz for matrix A. */ 00061 int *atanz, /* out - on exit, returns the actual number of 00062 nonzeros in matrix A'*A. */ 00063 int **ata_colptr, /* out - size n+1 */ 00064 int **ata_rowind /* out - size *atanz */ 00065 ) 00066 /* 00067 * Purpose 00068 * ======= 00069 * 00070 * Form the structure of A'*A. A is an m-by-n matrix in column oriented 00071 * format represented by (colptr, rowind). The output A'*A is in column 00072 * oriented format (symmetrically, also row oriented), represented by 00073 * (ata_colptr, ata_rowind). 00074 * 00075 * This routine is modified from GETATA routine by Tim Davis. 00076 * The complexity of this algorithm is: SUM_{i=1,m} r(i)^2, 00077 * i.e., the sum of the square of the row counts. 00078 * 00079 * Questions 00080 * ========= 00081 * o Do I need to withhold the *dense* rows? 00082 * o How do I know the number of nonzeros in A'*A? 00083 * 00084 */ 00085 { 00086 register int i, j, k, col, num_nz, ti, trow; 00087 int *marker, *b_colptr, *b_rowind; 00088 int *t_colptr, *t_rowind; /* a column oriented form of T = A' */ 00089 00090 if ( !(marker = (int*) SUPERLU_MALLOC((SUPERLU_MAX(m,n)+1)*sizeof(int))) ) 00091 ABORT("SUPERLU_MALLOC fails for marker[]"); 00092 if ( !(t_colptr = (int*) SUPERLU_MALLOC((m+1) * sizeof(int))) ) 00093 ABORT("SUPERLU_MALLOC t_colptr[]"); 00094 if ( !(t_rowind = (int*) SUPERLU_MALLOC(nz * sizeof(int))) ) 00095 ABORT("SUPERLU_MALLOC fails for t_rowind[]"); 00096 00097 00098 /* Get counts of each column of T, and set up column pointers */ 00099 for (i = 0; i < m; ++i) marker[i] = 0; 00100 for (j = 0; j < n; ++j) { 00101 for (i = colptr[j]; i < colptr[j+1]; ++i) 00102 ++marker[rowind[i]]; 00103 } 00104 t_colptr[0] = 0; 00105 for (i = 0; i < m; ++i) { 00106 t_colptr[i+1] = t_colptr[i] + marker[i]; 00107 marker[i] = t_colptr[i]; 00108 } 00109 00110 /* Transpose the matrix from A to T */ 00111 for (j = 0; j < n; ++j) 00112 for (i = colptr[j]; i < colptr[j+1]; ++i) { 00113 col = rowind[i]; 00114 t_rowind[marker[col]] = j; 00115 ++marker[col]; 00116 } 00117 00118 00119 /* ---------------------------------------------------------------- 00120 compute B = T * A, where column j of B is: 00121 00122 Struct (B_*j) = UNION ( Struct (T_*k) ) 00123 A_kj != 0 00124 00125 do not include the diagonal entry 00126 00127 ( Partition A as: A = (A_*1, ..., A_*n) 00128 Then B = T * A = (T * A_*1, ..., T * A_*n), where 00129 T * A_*j = (T_*1, ..., T_*m) * A_*j. ) 00130 ---------------------------------------------------------------- */ 00131 00132 /* Zero the diagonal flag */ 00133 for (i = 0; i < n; ++i) marker[i] = -1; 00134 00135 /* First pass determines number of nonzeros in B */ 00136 num_nz = 0; 00137 for (j = 0; j < n; ++j) { 00138 /* Flag the diagonal so it's not included in the B matrix */ 00139 marker[j] = j; 00140 00141 for (i = colptr[j]; i < colptr[j+1]; ++i) { 00142 /* A_kj is nonzero, add pattern of column T_*k to B_*j */ 00143 k = rowind[i]; 00144 for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) { 00145 trow = t_rowind[ti]; 00146 if ( marker[trow] != j ) { 00147 marker[trow] = j; 00148 num_nz++; 00149 } 00150 } 00151 } 00152 } 00153 *atanz = num_nz; 00154 00155 /* Allocate storage for A'*A */ 00156 if ( !(*ata_colptr = (int*) SUPERLU_MALLOC( (n+1) * sizeof(int)) ) ) 00157 ABORT("SUPERLU_MALLOC fails for ata_colptr[]"); 00158 if ( *atanz ) { 00159 if ( !(*ata_rowind = (int*) SUPERLU_MALLOC( *atanz * sizeof(int)) ) ) 00160 ABORT("SUPERLU_MALLOC fails for ata_rowind[]"); 00161 } 00162 b_colptr = *ata_colptr; /* aliasing */ 00163 b_rowind = *ata_rowind; 00164 00165 /* Zero the diagonal flag */ 00166 for (i = 0; i < n; ++i) marker[i] = -1; 00167 00168 /* Compute each column of B, one at a time */ 00169 num_nz = 0; 00170 for (j = 0; j < n; ++j) { 00171 b_colptr[j] = num_nz; 00172 00173 /* Flag the diagonal so it's not included in the B matrix */ 00174 marker[j] = j; 00175 00176 for (i = colptr[j]; i < colptr[j+1]; ++i) { 00177 /* A_kj is nonzero, add pattern of column T_*k to B_*j */ 00178 k = rowind[i]; 00179 for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) { 00180 trow = t_rowind[ti]; 00181 if ( marker[trow] != j ) { 00182 marker[trow] = j; 00183 b_rowind[num_nz++] = trow; 00184 } 00185 } 00186 } 00187 } 00188 b_colptr[n] = num_nz; 00189 00190 SUPERLU_FREE(marker); 00191 SUPERLU_FREE(t_colptr); 00192 SUPERLU_FREE(t_rowind); 00193 } 00194 00195 00196 static void 00197 at_plus_a( 00198 const int n, /* number of columns in matrix A. */ 00199 const int nz, /* number of nonzeros in matrix A */ 00200 int *colptr, /* column pointer of size n+1 for matrix A. */ 00201 int *rowind, /* row indices of size nz for matrix A. */ 00202 int *bnz, /* out - on exit, returns the actual number of 00203 nonzeros in matrix A'*A. */ 00204 int **b_colptr, /* out - size n+1 */ 00205 int **b_rowind /* out - size *bnz */ 00206 ) 00207 { 00208 /* 00209 * Purpose 00210 * ======= 00211 * 00212 * Form the structure of A'+A. A is an n-by-n matrix in column oriented 00213 * format represented by (colptr, rowind). The output A'+A is in column 00214 * oriented format (symmetrically, also row oriented), represented by 00215 * (b_colptr, b_rowind). 00216 * 00217 */ 00218 register int i, j, k, col, num_nz; 00219 int *t_colptr, *t_rowind; /* a column oriented form of T = A' */ 00220 int *marker; 00221 00222 if ( !(marker = (int*) SUPERLU_MALLOC( n * sizeof(int)) ) ) 00223 ABORT("SUPERLU_MALLOC fails for marker[]"); 00224 if ( !(t_colptr = (int*) SUPERLU_MALLOC( (n+1) * sizeof(int)) ) ) 00225 ABORT("SUPERLU_MALLOC fails for t_colptr[]"); 00226 if ( !(t_rowind = (int*) SUPERLU_MALLOC( nz * sizeof(int)) ) ) 00227 ABORT("SUPERLU_MALLOC fails t_rowind[]"); 00228 00229 00230 /* Get counts of each column of T, and set up column pointers */ 00231 for (i = 0; i < n; ++i) marker[i] = 0; 00232 for (j = 0; j < n; ++j) { 00233 for (i = colptr[j]; i < colptr[j+1]; ++i) 00234 ++marker[rowind[i]]; 00235 } 00236 t_colptr[0] = 0; 00237 for (i = 0; i < n; ++i) { 00238 t_colptr[i+1] = t_colptr[i] + marker[i]; 00239 marker[i] = t_colptr[i]; 00240 } 00241 00242 /* Transpose the matrix from A to T */ 00243 for (j = 0; j < n; ++j) 00244 for (i = colptr[j]; i < colptr[j+1]; ++i) { 00245 col = rowind[i]; 00246 t_rowind[marker[col]] = j; 00247 ++marker[col]; 00248 } 00249 00250 00251 /* ---------------------------------------------------------------- 00252 compute B = A + T, where column j of B is: 00253 00254 Struct (B_*j) = Struct (A_*k) UNION Struct (T_*k) 00255 00256 do not include the diagonal entry 00257 ---------------------------------------------------------------- */ 00258 00259 /* Zero the diagonal flag */ 00260 for (i = 0; i < n; ++i) marker[i] = -1; 00261 00262 /* First pass determines number of nonzeros in B */ 00263 num_nz = 0; 00264 for (j = 0; j < n; ++j) { 00265 /* Flag the diagonal so it's not included in the B matrix */ 00266 marker[j] = j; 00267 00268 /* Add pattern of column A_*k to B_*j */ 00269 for (i = colptr[j]; i < colptr[j+1]; ++i) { 00270 k = rowind[i]; 00271 if ( marker[k] != j ) { 00272 marker[k] = j; 00273 ++num_nz; 00274 } 00275 } 00276 00277 /* Add pattern of column T_*k to B_*j */ 00278 for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) { 00279 k = t_rowind[i]; 00280 if ( marker[k] != j ) { 00281 marker[k] = j; 00282 ++num_nz; 00283 } 00284 } 00285 } 00286 *bnz = num_nz; 00287 00288 /* Allocate storage for A+A' */ 00289 if ( !(*b_colptr = (int*) SUPERLU_MALLOC( (n+1) * sizeof(int)) ) ) 00290 ABORT("SUPERLU_MALLOC fails for b_colptr[]"); 00291 if ( *bnz) { 00292 if ( !(*b_rowind = (int*) SUPERLU_MALLOC( *bnz * sizeof(int)) ) ) 00293 ABORT("SUPERLU_MALLOC fails for b_rowind[]"); 00294 } 00295 00296 /* Zero the diagonal flag */ 00297 for (i = 0; i < n; ++i) marker[i] = -1; 00298 00299 /* Compute each column of B, one at a time */ 00300 num_nz = 0; 00301 for (j = 0; j < n; ++j) { 00302 (*b_colptr)[j] = num_nz; 00303 00304 /* Flag the diagonal so it's not included in the B matrix */ 00305 marker[j] = j; 00306 00307 /* Add pattern of column A_*k to B_*j */ 00308 for (i = colptr[j]; i < colptr[j+1]; ++i) { 00309 k = rowind[i]; 00310 if ( marker[k] != j ) { 00311 marker[k] = j; 00312 (*b_rowind)[num_nz++] = k; 00313 } 00314 } 00315 00316 /* Add pattern of column T_*k to B_*j */ 00317 for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) { 00318 k = t_rowind[i]; 00319 if ( marker[k] != j ) { 00320 marker[k] = j; 00321 (*b_rowind)[num_nz++] = k; 00322 } 00323 } 00324 } 00325 (*b_colptr)[n] = num_nz; 00326 00327 SUPERLU_FREE(marker); 00328 SUPERLU_FREE(t_colptr); 00329 SUPERLU_FREE(t_rowind); 00330 } 00331 00332 void 00333 get_perm_c(int ispec, SuperMatrix *A, int *perm_c) 00334 /* 00335 * Purpose 00336 * ======= 00337 * 00338 * GET_PERM_C obtains a permutation matrix Pc, by applying the multiple 00339 * minimum degree ordering code by Joseph Liu to matrix A'*A or A+A'. 00340 * or using approximate minimum degree column ordering by Davis et. al. 00341 * The LU factorization of A*Pc tends to have less fill than the LU 00342 * factorization of A. 00343 * 00344 * Arguments 00345 * ========= 00346 * 00347 * ispec (input) int 00348 * Specifies the type of column ordering to reduce fill: 00349 * = 1: minimum degree on the structure of A^T * A 00350 * = 2: minimum degree on the structure of A^T + A 00351 * = 3: approximate minimum degree for unsymmetric matrices 00352 * If ispec == 0, the natural ordering (i.e., Pc = I) is returned. 00353 * 00354 * A (input) SuperMatrix* 00355 * Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number 00356 * of the linear equations is A->nrow. Currently, the type of A 00357 * can be: Stype = NC; Dtype = _D; Mtype = GE. In the future, 00358 * more general A can be handled. 00359 * 00360 * perm_c (output) int* 00361 * Column permutation vector of size A->ncol, which defines the 00362 * permutation matrix Pc; perm_c[i] = j means column i of A is 00363 * in position j in A*Pc. 00364 * 00365 */ 00366 { 00367 NCformat *Astore = A->Store; 00368 int m, n, bnz, *b_colptr, i; 00369 int delta, maxint, nofsub, *invp; 00370 int *b_rowind, *dhead, *qsize, *llist, *marker; 00371 /* double t, SuperLU_timer_(); */ 00372 00373 /* make gcc happy */ 00374 b_rowind=NULL; 00375 b_colptr=NULL; 00376 00377 m = A->nrow; 00378 n = A->ncol; 00379 00380 /* t = SuperLU_timer_(); */ 00381 switch ( ispec ) { 00382 case 0: /* Natural ordering */ 00383 for (i = 0; i < n; ++i) perm_c[i] = i; 00384 #if ( PRNTlevel>=1 ) 00385 printf("Use natural column ordering.\n"); 00386 #endif 00387 return; 00388 case 1: /* Minimum degree ordering on A'*A */ 00389 getata(m, n, Astore->nnz, Astore->colptr, Astore->rowind, 00390 &bnz, &b_colptr, &b_rowind); 00391 #if ( PRNTlevel>=1 ) 00392 printf("Use minimum degree ordering on A'*A.\n"); 00393 #endif 00394 /*t = SuperLU_timer_() - t; 00395 printf("Form A'*A time = %8.3f\n", t);*/ 00396 break; 00397 case 2: /* Minimum degree ordering on A'+A */ 00398 if ( m != n ) ABORT("Matrix is not square"); 00399 at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind, 00400 &bnz, &b_colptr, &b_rowind); 00401 #if ( PRNTlevel>=1 ) 00402 printf("Use minimum degree ordering on A'+A.\n"); 00403 #endif 00404 /*t = SuperLU_timer_() - t; 00405 printf("Form A'+A time = %8.3f\n", t);*/ 00406 break; 00407 case 3: /* Approximate minimum degree column ordering. */ 00408 get_colamd(m, n, Astore->nnz, Astore->colptr, Astore->rowind, 00409 perm_c); 00410 #if ( PRNTlevel>=1 ) 00411 printf(".. Use approximate minimum degree column ordering.\n"); 00412 #endif 00413 return; 00414 default: 00415 ABORT("Invalid ISPEC"); 00416 return; 00417 } 00418 00419 if ( bnz != 0 ) { 00420 /* t = SuperLU_timer_(); */ 00421 00422 /* Initialize and allocate storage for GENMMD. */ 00423 delta = 1; /* DELTA is a parameter to allow the choice of nodes 00424 whose degree <= min-degree + DELTA. */ 00425 maxint = 2147483647; /* 2**31 - 1 */ 00426 invp = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int)); 00427 if ( !invp ) ABORT("SUPERLU_MALLOC fails for invp."); 00428 dhead = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int)); 00429 if ( !dhead ) ABORT("SUPERLU_MALLOC fails for dhead."); 00430 qsize = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int)); 00431 if ( !qsize ) ABORT("SUPERLU_MALLOC fails for qsize."); 00432 llist = (int *) SUPERLU_MALLOC(n*sizeof(int)); 00433 if ( !llist ) ABORT("SUPERLU_MALLOC fails for llist."); 00434 marker = (int *) SUPERLU_MALLOC(n*sizeof(int)); 00435 if ( !marker ) ABORT("SUPERLU_MALLOC fails for marker."); 00436 00437 /* Transform adjacency list into 1-based indexing required by GENMMD.*/ 00438 for (i = 0; i <= n; ++i) ++b_colptr[i]; 00439 for (i = 0; i < bnz; ++i) ++b_rowind[i]; 00440 00441 genmmd_(&n, b_colptr, b_rowind, perm_c, invp, &delta, dhead, 00442 qsize, llist, marker, &maxint, &nofsub); 00443 00444 /* Transform perm_c into 0-based indexing. */ 00445 for (i = 0; i < n; ++i) --perm_c[i]; 00446 00447 SUPERLU_FREE(b_colptr); 00448 SUPERLU_FREE(b_rowind); 00449 SUPERLU_FREE(invp); 00450 SUPERLU_FREE(dhead); 00451 SUPERLU_FREE(qsize); 00452 SUPERLU_FREE(llist); 00453 SUPERLU_FREE(marker); 00454 00455 /* t = SuperLU_timer_() - t; 00456 printf("call GENMMD time = %8.3f\n", t);*/ 00457 00458 } else { /* Empty adjacency structure */ 00459 for (i = 0; i < n; ++i) perm_c[i] = i; 00460 } 00461 00462 }