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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "Ifpack_ConfigDefs.h"
00044 #include "Ifpack_IC_Utils.h"
00045
00046 #define SYMSTR 1
00047 #include <stdio.h>
00048
00049 #define MIN(a,b) ((a)<=(b) ? (a) : (b))
00050 #define MAX(a,b) ((a)>=(b) ? (a) : (b))
00051 #define ABS(a) ((a)>=0 ? (a) : -(a))
00052
00053 #define SHORTCUT(p, a, ja, ia) \
00054 (a) = (p)->val; \
00055 (ja) = (p)->col; \
00056 (ia) = (p)->ptr;
00057
00058 #define MATNULL(p) \
00059 (p).val = NULL; \
00060 (p).col = NULL; \
00061 (p).ptr = NULL;
00062
00063 void Ifpack_AIJMatrix_alloc(Ifpack_AIJMatrix *a, int n, int nnz)
00064 {
00065 a->val = new double[nnz];
00066 a->col = new int[nnz];
00067 a->ptr = new int[n+1];
00068 }
00069
00070 void Ifpack_AIJMatrix_dealloc(Ifpack_AIJMatrix *a)
00071 {
00072 delete [] (a->val);
00073 delete [] (a->col);
00074 delete [] (a->ptr);
00075 a->val = 0;
00076 a->col = 0;
00077 a->ptr = 0;
00078 }
00079
00080 static void qsplit(double *a, int *ind, int n, int ncut)
00081 {
00082 double tmp, abskey;
00083 int itmp, first, last, mid;
00084 int j;
00085
00086 ncut--;
00087 first = 0;
00088 last = n-1;
00089 if (ncut < first || ncut > last)
00090 return;
00091
00092
00093 while (1)
00094 {
00095 mid = first;
00096 abskey = ABS(a[mid]);
00097 for (j=first+1; j<=last; j++)
00098 {
00099 if (ABS(a[j]) > abskey)
00100 {
00101 mid = mid+1;
00102
00103 tmp = a[mid];
00104 itmp = ind[mid];
00105 a[mid] = a[j];
00106 ind[mid] = ind[j];
00107 a[j] = tmp;
00108 ind[j] = itmp;
00109 }
00110 }
00111
00112
00113 tmp = a[mid];
00114 a[mid] = a[first];
00115 a[first] = tmp;
00116 itmp = ind[mid];
00117 ind[mid] = ind[first];
00118 ind[first] = itmp;
00119
00120
00121 if (mid == ncut)
00122 return;
00123
00124 if (mid > ncut)
00125 last = mid-1;
00126 else
00127 first = mid+1;
00128 }
00129 }
00130
00131
00132
00133
00134
00135 static void update_column(
00136 int k,
00137 const int *ia, const int *ja, const double *a,
00138 const int *ifirst,
00139 const int *ifirst2,
00140 const int *list2,
00141 const double *multipliers,
00142 const double *d,
00143 int *marker,
00144 double *ta,
00145 int *itcol,
00146 int *ptalen)
00147 {
00148 int j, i, isj, iej, row;
00149 int talen, pos;
00150 double mult;
00151
00152 talen = *ptalen;
00153
00154 j = list2[k];
00155 while (j != -1)
00156 {
00157
00158
00159 isj = ifirst[j];
00160
00161
00162
00163
00164
00165
00166 if (isj != -1)
00167 {
00168
00169 mult = multipliers[ifirst2[j]] * d[j];
00170
00171
00172 iej = ia[j+1]-1;
00173
00174 for (i=isj; i<=iej; i++)
00175 {
00176 row = ja[i];
00177
00178
00179 if (row <= k)
00180 continue;
00181
00182 if ((pos = marker[row]) != -1)
00183 {
00184
00185 ta[pos] -= mult*a[i];
00186 }
00187 else
00188 {
00189
00190 itcol[talen] = row;
00191 ta[talen] = -mult*a[i];
00192 marker[row] = talen++;
00193 }
00194 }
00195 }
00196
00197 j = list2[j];
00198 }
00199
00200 *ptalen = talen;
00201 }
00202
00203
00204
00205 static void update_lists(
00206 int k,
00207 const int *ia,
00208 const int *ja,
00209 int *ifirst,
00210 int *list)
00211 {
00212 int j, isj, iej, iptr;
00213
00214 j = list[k];
00215 while (j != -1)
00216 {
00217 isj = ifirst[j];
00218 iej = ia[j+1]-1;
00219
00220 isj++;
00221
00222 if (isj != 0 && isj <= iej)
00223 {
00224
00225 ifirst[j] = isj;
00226
00227
00228 iptr = j;
00229 j = list[j];
00230 list[iptr] = list[ja[isj]];
00231 list[ja[isj]] = iptr;
00232 }
00233 else
00234 {
00235 j = list[j];
00236 }
00237 }
00238 }
00239
00240 static void update_lists_newcol(
00241 int k,
00242 int isk,
00243 int iptr,
00244 int *ifirst,
00245 int *list)
00246 {
00247 ifirst[k] = isk;
00248 list[k] = list[iptr];
00249 list[iptr] = k;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 void crout_ict(
00276 int n,
00277 #ifdef IFPACK
00278 void * A,
00279 int maxentries;
00280 int (*getcol)( void * A, int col, int ** nentries, double * val, int * ind),
00281 int (*getdiag)( void *A, double * diag),
00282 #else
00283 const Ifpack_AIJMatrix *AL,
00284 const double *Adiag,
00285 #endif
00286 double droptol,
00287 int lfil,
00288 Ifpack_AIJMatrix *L,
00289 double **pdiag)
00290 {
00291 int k, j, i, index;
00292 int count_l;
00293 double norm_l;
00294
00295
00296 double *work_l = new double[n];
00297 int *ind_l = new int[n];
00298 int len_l;
00299
00300
00301 int *list_l = new int[n];
00302 int *ifirst_l = new int[n];
00303
00304
00305 int *marker_l = ifirst_l;
00306
00307
00308 double *al; int *jal, *ial;
00309 double *l; int *jl, *il;
00310
00311 int kl = 0;
00312
00313 double *diag = new double[n];
00314 *pdiag = diag;
00315
00316 Ifpack_AIJMatrix_alloc(L, n, lfil*n);
00317
00318 SHORTCUT(AL, al, jal, ial);
00319 SHORTCUT(L, l, jl, il);
00320
00321
00322 for (i=0; i<n; i++)
00323 {
00324 list_l[i] = -1;
00325 ifirst_l[i] = -1;
00326 marker_l[i] = -1;
00327 }
00328
00329
00330 #ifdef IFPACK
00331 getdiag(A, diag);
00332 #else
00333 for (i=0; i<n; i++)
00334 diag[i] = Adiag[i];
00335 #endif
00336
00337
00338 il[0] = 0;
00339
00340
00341
00342
00343
00344 for (k=0; k<n; k++)
00345 {
00346
00347
00348
00349
00350
00351
00352 norm_l = 0.;
00353 #ifdef IFPACK
00354 getcol(A, k, len_l, work_l, ind_l);
00355 for (j=0; j<len_l; j++)
00356 {
00357 norm_l += ABS(work_l[j]);
00358 marker_l[ind_l[j]] = j;
00359 }
00360 #else
00361 len_l = 0;
00362 for (j=ial[k]; j<ial[k+1]; j++)
00363 {
00364 index = jal[j];
00365 work_l[len_l] = al[j];
00366 norm_l += ABS(al[j]);
00367 ind_l[len_l] = index;
00368 marker_l[index] = len_l++;
00369 }
00370 #endif
00371 norm_l = (len_l == 0) ? 0.0 : norm_l/((double) len_l);
00372
00373
00374
00375 update_column(k, il, jl, l, ifirst_l, ifirst_l, list_l, l,
00376 diag, marker_l, work_l, ind_l, &len_l);
00377
00378 for (j=0; j<len_l; j++)
00379 work_l[j] /= diag[k];
00380
00381 i = 0;
00382 for (j=0; j<len_l; j++)
00383 {
00384 if (ABS(work_l[j]) < droptol * norm_l)
00385 {
00386
00387 marker_l[ind_l[j]] = -1;
00388 }
00389 else
00390 {
00391 work_l[i] = work_l[j];
00392 ind_l[i] = ind_l[j];
00393 i++;
00394 }
00395 }
00396 len_l = i;
00397
00398
00399
00400
00401
00402
00403
00404
00405 count_l = MIN(len_l, lfil);
00406 qsplit(work_l, ind_l, len_l, count_l);
00407 ifpack_multilist_sort(ind_l, work_l, count_l);
00408
00409 for (j=0; j<count_l; j++)
00410 {
00411 l[kl] = work_l[j];
00412 jl[kl++] = ind_l[j];
00413 }
00414 il[k+1] = kl;
00415
00416
00417
00418
00419
00420 update_lists(k, il, jl, ifirst_l, list_l);
00421
00422 if (kl - il[k] > SYMSTR)
00423 update_lists_newcol(k, il[k], jl[il[k]], ifirst_l, list_l);
00424
00425
00426 for (j=0; j<len_l; j++)
00427 marker_l[ind_l[j]] = -1;
00428
00429
00430
00431
00432
00433 for (j=0; j<count_l; j++)
00434 {
00435 index = ind_l[j];
00436 diag[index] -= work_l[j] * work_l[j] * diag[k];
00437 }
00438 }
00439
00440 delete [] work_l;
00441 delete [] ind_l;
00442 delete [] list_l;
00443 delete [] ifirst_l;
00444 }