Blender V2.61 - r43446
|
00001 00004 #include "ssp_defs.h" 00005 00006 int check_perm(char *, int , int *); 00007 00008 00009 void 00010 sp_preorder(superlu_options_t *options, SuperMatrix *A, int *perm_c, 00011 int *etree, SuperMatrix *AC) 00012 { 00013 /* 00014 * Purpose 00015 * ======= 00016 * 00017 * sp_preorder() permutes the columns of the original matrix. It performs 00018 * the following steps: 00019 * 00020 * 1. Apply column permutation perm_c[] to A's column pointers to form AC; 00021 * 00022 * 2. If options->Fact = DOFACT, then 00023 * (1) Compute column elimination tree etree[] of AC'AC; 00024 * (2) Post order etree[] to get a postordered elimination tree etree[], 00025 * and a postorder permutation post[]; 00026 * (3) Apply post[] permutation to columns of AC; 00027 * (4) Overwrite perm_c[] with the product perm_c * post. 00028 * 00029 * Arguments 00030 * ========= 00031 * 00032 * options (input) superlu_options_t* 00033 * Specifies whether or not the elimination tree will be re-used. 00034 * If options->Fact == DOFACT, this means first time factor A, 00035 * etree is computed, postered, and output. 00036 * Otherwise, re-factor A, etree is input, unchanged on exit. 00037 * 00038 * A (input) SuperMatrix* 00039 * Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number 00040 * of the linear equations is A->nrow. Currently, the type of A can be: 00041 * Stype = NC or SLU_NCP; Mtype = SLU_GE. 00042 * In the future, more general A may be handled. 00043 * 00044 * perm_c (input/output) int* 00045 * Column permutation vector of size A->ncol, which defines the 00046 * permutation matrix Pc; perm_c[i] = j means column i of A is 00047 * in position j in A*Pc. 00048 * If options->Fact == DOFACT, perm_c is both input and output. 00049 * On output, it is changed according to a postorder of etree. 00050 * Otherwise, perm_c is input. 00051 * 00052 * etree (input/output) int* 00053 * Elimination tree of Pc'*A'*A*Pc, dimension A->ncol. 00054 * If options->Fact == DOFACT, etree is an output argument, 00055 * otherwise it is an input argument. 00056 * Note: etree is a vector of parent pointers for a forest whose 00057 * vertices are the integers 0 to A->ncol-1; etree[root]==A->ncol. 00058 * 00059 * AC (output) SuperMatrix* 00060 * The resulting matrix after applied the column permutation 00061 * perm_c[] to matrix A. The type of AC can be: 00062 * Stype = SLU_NCP; Dtype = A->Dtype; Mtype = SLU_GE. 00063 * 00064 */ 00065 00066 NCformat *Astore; 00067 NCPformat *ACstore; 00068 int *iwork, *post; 00069 register int n, i; 00070 00071 n = A->ncol; 00072 00073 /* Apply column permutation perm_c to A's column pointers so to 00074 obtain NCP format in AC = A*Pc. */ 00075 AC->Stype = SLU_NCP; 00076 AC->Dtype = A->Dtype; 00077 AC->Mtype = A->Mtype; 00078 AC->nrow = A->nrow; 00079 AC->ncol = A->ncol; 00080 Astore = A->Store; 00081 ACstore = AC->Store = (void *) SUPERLU_MALLOC( sizeof(NCPformat) ); 00082 if ( !ACstore ) ABORT("SUPERLU_MALLOC fails for ACstore"); 00083 ACstore->nnz = Astore->nnz; 00084 ACstore->nzval = Astore->nzval; 00085 ACstore->rowind = Astore->rowind; 00086 ACstore->colbeg = (int*) SUPERLU_MALLOC(n*sizeof(int)); 00087 if ( !(ACstore->colbeg) ) ABORT("SUPERLU_MALLOC fails for ACstore->colbeg"); 00088 ACstore->colend = (int*) SUPERLU_MALLOC(n*sizeof(int)); 00089 if ( !(ACstore->colend) ) ABORT("SUPERLU_MALLOC fails for ACstore->colend"); 00090 00091 #ifdef DEBUG 00092 print_int_vec("pre_order:", n, perm_c); 00093 check_perm("Initial perm_c", n, perm_c); 00094 #endif 00095 00096 for (i = 0; i < n; i++) { 00097 ACstore->colbeg[perm_c[i]] = Astore->colptr[i]; 00098 ACstore->colend[perm_c[i]] = Astore->colptr[i+1]; 00099 } 00100 00101 if ( options->Fact == DOFACT ) { 00102 #undef ETREE_ATplusA 00103 #ifdef ETREE_ATplusA 00104 /*-------------------------------------------- 00105 COMPUTE THE ETREE OF Pc*(A'+A)*Pc'. 00106 --------------------------------------------*/ 00107 int *b_colptr, *b_rowind, bnz, j; 00108 int *c_colbeg, *c_colend; 00109 00110 /*printf("Use etree(A'+A)\n");*/ 00111 00112 /* Form B = A + A'. */ 00113 at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind, 00114 &bnz, &b_colptr, &b_rowind); 00115 00116 /* Form C = Pc*B*Pc'. */ 00117 c_colbeg = (int*) SUPERLU_MALLOC(2*n*sizeof(int)); 00118 c_colend = c_colbeg + n; 00119 if (!c_colbeg ) ABORT("SUPERLU_MALLOC fails for c_colbeg/c_colend"); 00120 for (i = 0; i < n; i++) { 00121 c_colbeg[perm_c[i]] = b_colptr[i]; 00122 c_colend[perm_c[i]] = b_colptr[i+1]; 00123 } 00124 for (j = 0; j < n; ++j) { 00125 for (i = c_colbeg[j]; i < c_colend[j]; ++i) { 00126 b_rowind[i] = perm_c[b_rowind[i]]; 00127 } 00128 } 00129 00130 /* Compute etree of C. */ 00131 sp_symetree(c_colbeg, c_colend, b_rowind, n, etree); 00132 00133 SUPERLU_FREE(b_colptr); 00134 if ( bnz ) SUPERLU_FREE(b_rowind); 00135 SUPERLU_FREE(c_colbeg); 00136 00137 #else 00138 /*-------------------------------------------- 00139 COMPUTE THE COLUMN ELIMINATION TREE. 00140 --------------------------------------------*/ 00141 sp_coletree(ACstore->colbeg, ACstore->colend, ACstore->rowind, 00142 A->nrow, A->ncol, etree); 00143 #endif 00144 #ifdef DEBUG 00145 print_int_vec("etree:", n, etree); 00146 #endif 00147 00148 /* In symmetric mode, do not do postorder here. */ 00149 if ( options->SymmetricMode == NO ) { 00150 /* Post order etree */ 00151 post = (int *) TreePostorder(n, etree); 00152 /* for (i = 0; i < n+1; ++i) inv_post[post[i]] = i; 00153 iwork = post; */ 00154 00155 #ifdef DEBUG 00156 print_int_vec("post:", n+1, post); 00157 check_perm("post", n, post); 00158 #endif 00159 iwork = (int*) SUPERLU_MALLOC((n+1)*sizeof(int)); 00160 if ( !iwork ) ABORT("SUPERLU_MALLOC fails for iwork[]"); 00161 00162 /* Renumber etree in postorder */ 00163 for (i = 0; i < n; ++i) iwork[post[i]] = post[etree[i]]; 00164 for (i = 0; i < n; ++i) etree[i] = iwork[i]; 00165 00166 #ifdef DEBUG 00167 print_int_vec("postorder etree:", n, etree); 00168 #endif 00169 00170 /* Postmultiply A*Pc by post[] */ 00171 for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colbeg[i]; 00172 for (i = 0; i < n; ++i) ACstore->colbeg[i] = iwork[i]; 00173 for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colend[i]; 00174 for (i = 0; i < n; ++i) ACstore->colend[i] = iwork[i]; 00175 00176 for (i = 0; i < n; ++i) 00177 iwork[i] = post[perm_c[i]]; /* product of perm_c and post */ 00178 for (i = 0; i < n; ++i) perm_c[i] = iwork[i]; 00179 00180 #ifdef DEBUG 00181 print_int_vec("Pc*post:", n, perm_c); 00182 check_perm("final perm_c", n, perm_c); 00183 #endif 00184 SUPERLU_FREE (post); 00185 SUPERLU_FREE (iwork); 00186 } /* end postordering */ 00187 00188 } /* if options->Fact == DOFACT ... */ 00189 00190 } 00191 00192 int check_perm(char *what, int n, int *perm) 00193 { 00194 register int i; 00195 int *marker; 00196 marker = (int *) calloc(n, sizeof(int)); 00197 00198 for (i = 0; i < n; ++i) { 00199 if ( marker[perm[i]] == 1 || perm[i] >= n ) { 00200 printf("%s: Not a valid PERM[%d] = %d\n", what, i, perm[i]); 00201 ABORT("check_perm"); 00202 } else { 00203 marker[perm[i]] = 1; 00204 } 00205 } 00206 00207 SUPERLU_FREE(marker); 00208 return 0; 00209 }