00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "ifp_ifpack.h"
00030 #include "ifp_SparseUtil.h"
00031 #include "stdio.h"
00032 using namespace std;
00033
00034
00035
00036
00037
00038 void shell_sort(
00039 const int n,
00040 int x[])
00041 {
00042 int m, max, j, k, itemp;
00043
00044 m = n/2;
00045
00046 while (m > 0) {
00047 max = n - m;
00048 for (j=0; j<max; j++)
00049 {
00050 for (k=j; k>=0; k-=m)
00051 {
00052 if (x[k+m] >= x[k])
00053 break;
00054 itemp = x[k+m];
00055 x[k+m] = x[k];
00056 x[k] = itemp;
00057 }
00058 }
00059 m = m/2;
00060 }
00061 }
00062
00063
00064
00065 void allocate_ilu(
00066 const int levfill,
00067 const int n,
00068 int *nzl, int *nzu,
00069 const int ia[], const int ja[],
00070 int *ial[], int *jal[],
00071 int *iau[], int *jau[],
00072 int growthl, int growthu)
00073 {
00074 int i, j, nzla, nzua;
00075 int maxl, maxu;
00076
00077 maxu = n*(n+1)/2;
00078 maxl = n*n - maxu;
00079
00080
00081
00082 nzla = 0;
00083 nzua = 0;
00084 for (i=0; i<n; i++)
00085 {
00086 for (j=ia[i]; j<ia[i+1]; j++)
00087 {
00088 if (ja[j] < i)
00089 nzla++;
00090 else
00091 nzua++;
00092 }
00093 }
00094
00095 *ial = new int[n+1];
00096 *iau = new int[n+1];
00097
00098 if (levfill == 0)
00099 {
00100 *nzl = nzla;
00101 *nzu = nzua + n;
00102 }
00103 else if (levfill == n)
00104 {
00105 *nzl = maxl;
00106 *nzu = maxu;
00107 }
00108 else
00109 {
00110 *nzl = MIN((levfill+growthl)*nzla, maxl);
00111 *nzu = MIN((levfill+growthu)*nzua + n, maxu);
00112 }
00113
00114 *jal = new int[*nzl];
00115 *jau = new int[*nzu];
00116
00117 if (levfill != 0)
00118 {
00119
00120
00121 }
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 int symbolic_ilu(
00135 const int levfill,
00136 const int n,
00137 int *nzl,
00138 int *nzu,
00139 const int ia[], const int ja[],
00140 int ial[], int jal[],
00141 int iau[], int jau[])
00142 {
00143 #if 0
00144
00145 if (levfill == 0)
00146 {
00147 int kl = 0;
00148 int ku = 0;
00149 ial[0] = 0;
00150 iau[0] = 0;
00151 for (int i=0; i<n; i++)
00152 {
00153 for (int j=ia[i]; j<ia[i+1]; j++)
00154 {
00155 if (ja[j] < i)
00156 jal[kl++] = ja[j];
00157 else
00158 jau[ku++] = ja[j];
00159 }
00160 ial[i+1] = kl;
00161 iau[i+1] = ku;
00162 shell_sort(ial[i+1]-ial[i], &jal[ial[i]]);
00163 shell_sort(iau[i+1]-iau[i], &jau[iau[i]]);
00164 }
00165 assert (kl <= *nzl);
00166 assert (ku <= *nzu);
00167 *nzl = kl;
00168 *nzu = ku;
00169 }
00170 else
00171 #endif
00172 {
00173
00174 int *lnklst = new int[n];
00175 int *curlev = new int[n];
00176 int *levels = new int[*nzu];
00177 int *iwork = new int[n];
00178
00179 int knzl = 0;
00180 int knzu = 0;
00181
00182 ial[0] = 0;
00183 iau[0] = 0;
00184
00185 for (int i=0; i<n; i++)
00186 {
00187 int first, next, j;
00188
00189
00190
00191 int len = ia[i+1] - ia[i];
00192 if (len == 0 ) cerr << " Row " << i << " is zero " << endl;
00193 next = 0;
00194 for (j=ia[i]; j<ia[i+1]; j++)
00195 iwork[next++] = ja[j];
00196 shell_sort(len, iwork);
00197
00198
00199
00200 first = iwork[0];
00201 curlev[first] = 0;
00202
00203 for (j=0; j<=len-2; j++)
00204 {
00205 lnklst[iwork[j]] = iwork[j+1];
00206 curlev[iwork[j]] = 0;
00207 }
00208
00209 lnklst[iwork[len-1]] = n;
00210 curlev[iwork[len-1]] = 0;
00211
00212
00213
00214 next = first;
00215 while (next < i)
00216 {
00217 int oldlst = next;
00218 int nxtlst = lnklst[next];
00219 int row = next;
00220 int ii;
00221
00222
00223
00224 for (ii=iau[row]+1; ii<iau[row+1]; )
00225 {
00226 if (jau[ii] < nxtlst)
00227 {
00228
00229 int newlev = curlev[row] + levels[ii] + 1;
00230 if (newlev <= levfill)
00231 {
00232 lnklst[oldlst] = jau[ii];
00233 lnklst[jau[ii]] = nxtlst;
00234 oldlst = jau[ii];
00235 curlev[jau[ii]] = newlev;
00236 }
00237 ii++;
00238 }
00239 else if (jau[ii] == nxtlst)
00240 {
00241 oldlst = nxtlst;
00242 nxtlst = lnklst[oldlst];
00243 int newlev = curlev[row] + levels[ii] + 1;
00244 curlev[jau[ii]] = MIN(curlev[jau[ii]], newlev);
00245 ii++;
00246 }
00247 else
00248 {
00249 oldlst = nxtlst;
00250 nxtlst = lnklst[oldlst];
00251 }
00252 }
00253 next = lnklst[next];
00254 }
00255
00256
00257
00258 next = first;
00259 while (next < i)
00260 {
00261 if (knzl >= *nzl)
00262 {
00263 cerr << "For row "<< i << endl;
00264 cerr << " nzl = "<< *nzl <<" knzl = "<< knzl << endl;
00265 printf("Not enough space allocated for lower symbolic factor\n");
00266 return(-1);
00267 }
00268
00269 jal[knzl++] = next;
00270 next = lnklst[next];
00271 }
00272 ial[i+1] = knzl;
00273
00274 if (next != i)
00275 {
00276 cerr << i << " U has zero on diag, forcing nonzero" << endl;
00277 if (knzu >= *nzu)
00278 {
00279 cerr << " nzl = "<< *nzu <<" knzl = "<< knzu << endl;
00280 printf("Not enough space allocated for symbolic factor\n");
00281 return(-2);
00282 }
00283 levels[knzu] = 2*n;
00284 jau[knzu++] = i;
00285 }
00286
00287 while (next < n)
00288 {
00289 if (knzu >= *nzu)
00290 {
00291 cerr << "For row "<< i << endl;
00292 cerr << " nzu = "<< *nzu <<" knzu = "<< knzu << endl;
00293 printf("Not enough space allocated for upper symbolic factor\n");
00294 return(-2);
00295
00296 }
00297 levels[knzu] = curlev[next];
00298 jau[knzu++] = next;
00299 next = lnklst[next];
00300 }
00301 iau[i+1] = knzu;
00302 }
00303
00304 delete [] lnklst;
00305 delete [] curlev;
00306 delete [] levels;
00307 delete [] iwork;
00308
00309 *nzl = knzl;
00310 *nzu = knzu;
00311
00312 #ifdef DEBUG
00313 cerr << "Actual nnz for ILU: " << *nzl + *nzu << endl;
00314 #endif
00315 }
00316 return(0);
00317 }