Blender V2.61 - r43446
|
00001 00006 /* 00007 * -- SuperLU routine (version 3.0) -- 00008 * Univ. of California Berkeley, Xerox Palo Alto Research Center, 00009 * and Lawrence Berkeley National Lab. 00010 * October 15, 2003 00011 * 00012 */ 00013 /* 00014 Copyright (c) 1994 by Xerox Corporation. All rights reserved. 00015 00016 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY 00017 EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. 00018 00019 Permission is hereby granted to use or copy this program for any 00020 purpose, provided the above notices are retained on all copies. 00021 Permission to modify the code and to distribute modified code is 00022 granted, provided the above notices are retained, and a notice that 00023 the code was modified is included with the above copyright notice. 00024 */ 00025 00026 #include "ssp_defs.h" 00027 00028 /* What type of supernodes we want */ 00029 #define T2_SUPER 00030 00031 int 00032 scolumn_dfs( 00033 const int m, /* in - number of rows in the matrix */ 00034 const int jcol, /* in */ 00035 int *perm_r, /* in */ 00036 int *nseg, /* modified - with new segments appended */ 00037 int *lsub_col, /* in - defines the RHS vector to start the dfs */ 00038 int *segrep, /* modified - with new segments appended */ 00039 int *repfnz, /* modified */ 00040 int *xprune, /* modified */ 00041 int *marker, /* modified */ 00042 int *parent, /* working array */ 00043 int *xplore, /* working array */ 00044 GlobalLU_t *Glu /* modified */ 00045 ) 00046 { 00047 /* 00048 * Purpose 00049 * ======= 00050 * "column_dfs" performs a symbolic factorization on column jcol, and 00051 * decide the supernode boundary. 00052 * 00053 * This routine does not use numeric values, but only use the RHS 00054 * row indices to start the dfs. 00055 * 00056 * A supernode representative is the last column of a supernode. 00057 * The nonzeros in U[*,j] are segments that end at supernodal 00058 * representatives. The routine returns a list of such supernodal 00059 * representatives in topological order of the dfs that generates them. 00060 * The location of the first nonzero in each such supernodal segment 00061 * (supernodal entry location) is also returned. 00062 * 00063 * Local parameters 00064 * ================ 00065 * nseg: no of segments in current U[*,j] 00066 * jsuper: jsuper=EMPTY if column j does not belong to the same 00067 * supernode as j-1. Otherwise, jsuper=nsuper. 00068 * 00069 * marker2: A-row --> A-row/col (0/1) 00070 * repfnz: SuperA-col --> PA-row 00071 * parent: SuperA-col --> SuperA-col 00072 * xplore: SuperA-col --> index to L-structure 00073 * 00074 * Return value 00075 * ============ 00076 * 0 success; 00077 * > 0 number of bytes allocated when run out of space. 00078 * 00079 */ 00080 int jcolp1, jcolm1, jsuper, nsuper, nextl; 00081 int k, krep, krow, kmark, kperm; 00082 int *marker2; /* Used for small panel LU */ 00083 int fsupc; /* First column of a snode */ 00084 int myfnz; /* First nonz column of a U-segment */ 00085 int chperm, chmark, chrep, kchild; 00086 int xdfs, maxdfs, kpar, oldrep; 00087 int jptr, jm1ptr; 00088 int ito, ifrom, istop; /* Used to compress row subscripts */ 00089 int mem_error; 00090 int *xsup, *supno, *lsub, *xlsub; 00091 int nzlmax; 00092 static int first = 1, maxsuper; 00093 00094 xsup = Glu->xsup; 00095 supno = Glu->supno; 00096 lsub = Glu->lsub; 00097 xlsub = Glu->xlsub; 00098 nzlmax = Glu->nzlmax; 00099 00100 if ( first ) { 00101 maxsuper = sp_ienv(3); 00102 first = 0; 00103 } 00104 jcolp1 = jcol + 1; 00105 jcolm1 = jcol - 1; 00106 nsuper = supno[jcol]; 00107 jsuper = nsuper; 00108 nextl = xlsub[jcol]; 00109 marker2 = &marker[2*m]; 00110 00111 00112 /* For each nonzero in A[*,jcol] do dfs */ 00113 for (k = 0; lsub_col[k] != EMPTY; k++) { 00114 00115 krow = lsub_col[k]; 00116 lsub_col[k] = EMPTY; 00117 kmark = marker2[krow]; 00118 00119 /* krow was visited before, go to the next nonz */ 00120 if ( kmark == jcol ) continue; 00121 00122 /* For each unmarked nbr krow of jcol 00123 * krow is in L: place it in structure of L[*,jcol] 00124 */ 00125 marker2[krow] = jcol; 00126 kperm = perm_r[krow]; 00127 00128 if ( kperm == EMPTY ) { 00129 lsub[nextl++] = krow; /* krow is indexed into A */ 00130 if ( nextl >= nzlmax ) { 00131 if ((mem_error = sLUMemXpand(jcol, nextl, LSUB, &nzlmax, Glu))) 00132 return (mem_error); 00133 lsub = Glu->lsub; 00134 } 00135 if ( kmark != jcolm1 ) jsuper = EMPTY;/* Row index subset testing */ 00136 } else { 00137 /* krow is in U: if its supernode-rep krep 00138 * has been explored, update repfnz[*] 00139 */ 00140 krep = xsup[supno[kperm]+1] - 1; 00141 myfnz = repfnz[krep]; 00142 00143 if ( myfnz != EMPTY ) { /* Visited before */ 00144 if ( myfnz > kperm ) repfnz[krep] = kperm; 00145 /* continue; */ 00146 } 00147 else { 00148 /* Otherwise, perform dfs starting at krep */ 00149 oldrep = EMPTY; 00150 parent[krep] = oldrep; 00151 repfnz[krep] = kperm; 00152 xdfs = xlsub[krep]; 00153 maxdfs = xprune[krep]; 00154 00155 do { 00156 /* 00157 * For each unmarked kchild of krep 00158 */ 00159 while ( xdfs < maxdfs ) { 00160 00161 kchild = lsub[xdfs]; 00162 xdfs++; 00163 chmark = marker2[kchild]; 00164 00165 if ( chmark != jcol ) { /* Not reached yet */ 00166 marker2[kchild] = jcol; 00167 chperm = perm_r[kchild]; 00168 00169 /* Case kchild is in L: place it in L[*,k] */ 00170 if ( chperm == EMPTY ) { 00171 lsub[nextl++] = kchild; 00172 if ( nextl >= nzlmax ) { 00173 if ((mem_error = 00174 sLUMemXpand(jcol,nextl,LSUB,&nzlmax,Glu))) 00175 return (mem_error); 00176 lsub = Glu->lsub; 00177 } 00178 if ( chmark != jcolm1 ) jsuper = EMPTY; 00179 } else { 00180 /* Case kchild is in U: 00181 * chrep = its supernode-rep. If its rep has 00182 * been explored, update its repfnz[*] 00183 */ 00184 chrep = xsup[supno[chperm]+1] - 1; 00185 myfnz = repfnz[chrep]; 00186 if ( myfnz != EMPTY ) { /* Visited before */ 00187 if ( myfnz > chperm ) 00188 repfnz[chrep] = chperm; 00189 } else { 00190 /* Continue dfs at super-rep of kchild */ 00191 xplore[krep] = xdfs; 00192 oldrep = krep; 00193 krep = chrep; /* Go deeper down G(L^t) */ 00194 parent[krep] = oldrep; 00195 repfnz[krep] = chperm; 00196 xdfs = xlsub[krep]; 00197 maxdfs = xprune[krep]; 00198 } /* else */ 00199 00200 } /* else */ 00201 00202 } /* if */ 00203 00204 } /* while */ 00205 00206 /* krow has no more unexplored nbrs; 00207 * place supernode-rep krep in postorder DFS. 00208 * backtrack dfs to its parent 00209 */ 00210 segrep[*nseg] = krep; 00211 ++(*nseg); 00212 kpar = parent[krep]; /* Pop from stack, mimic recursion */ 00213 if ( kpar == EMPTY ) break; /* dfs done */ 00214 krep = kpar; 00215 xdfs = xplore[krep]; 00216 maxdfs = xprune[krep]; 00217 00218 } while ( kpar != EMPTY ); /* Until empty stack */ 00219 00220 } /* else */ 00221 00222 } /* else */ 00223 00224 } /* for each nonzero ... */ 00225 00226 /* Check to see if j belongs in the same supernode as j-1 */ 00227 if ( jcol == 0 ) { /* Do nothing for column 0 */ 00228 nsuper = supno[0] = 0; 00229 } else { 00230 fsupc = xsup[nsuper]; 00231 jptr = xlsub[jcol]; /* Not compressed yet */ 00232 jm1ptr = xlsub[jcolm1]; 00233 00234 #ifdef T2_SUPER 00235 if ( (nextl-jptr != jptr-jm1ptr-1) ) jsuper = EMPTY; 00236 #endif 00237 /* Make sure the number of columns in a supernode doesn't 00238 exceed threshold. */ 00239 if ( jcol - fsupc >= maxsuper ) jsuper = EMPTY; 00240 00241 /* If jcol starts a new supernode, reclaim storage space in 00242 * lsub from the previous supernode. Note we only store 00243 * the subscript set of the first and last columns of 00244 * a supernode. (first for num values, last for pruning) 00245 */ 00246 if ( jsuper == EMPTY ) { /* starts a new supernode */ 00247 if ( (fsupc < jcolm1-1) ) { /* >= 3 columns in nsuper */ 00248 #ifdef CHK_COMPRESS 00249 printf(" Compress lsub[] at super %d-%d\n", fsupc, jcolm1); 00250 #endif 00251 ito = xlsub[fsupc+1]; 00252 xlsub[jcolm1] = ito; 00253 istop = ito + jptr - jm1ptr; 00254 xprune[jcolm1] = istop; /* Initialize xprune[jcol-1] */ 00255 xlsub[jcol] = istop; 00256 for (ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito) 00257 lsub[ito] = lsub[ifrom]; 00258 nextl = ito; /* = istop + length(jcol) */ 00259 } 00260 nsuper++; 00261 supno[jcol] = nsuper; 00262 } /* if a new supernode */ 00263 00264 } /* else: jcol > 0 */ 00265 00266 /* Tidy up the pointers before exit */ 00267 xsup[nsuper+1] = jcolp1; 00268 supno[jcolp1] = nsuper; 00269 xprune[jcol] = nextl; /* Initialize upper bound for pruning */ 00270 xlsub[jcolp1] = nextl; 00271 00272 return 0; 00273 }