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
00044
00045 #include "ilu_dh.h"
00046 #include "Mem_dh.h"
00047 #include "Parser_dh.h"
00048 #include "Euclid_dh.h"
00049 #include "getRow_dh.h"
00050 #include "Factor_dh.h"
00051 #include "SubdomainGraph_dh.h"
00052
00053
00054 int symbolic_row_private (int localRow, int beg_row, int end_row,
00055 int *list, int *marker, int *tmpFill,
00056 int len, int *CVAL, double *AVAL,
00057 int *o2n_col, Euclid_dh ctx);
00058
00059 static int numeric_row_private (int localRow, int beg_row, int end_row,
00060 int len, int *CVAL, double *AVAL,
00061 REAL_DH * work, int *o2n_col, Euclid_dh ctx);
00062
00063
00064
00065 #undef __FUNC__
00066 #define __FUNC__ "iluk_mpi_bj"
00067 void
00068 iluk_mpi_bj (Euclid_dh ctx)
00069 {
00070 START_FUNC_DH int *rp, *cval, *diag;
00071 int *CVAL;
00072 int i, j, len, count, col, idx = 0;
00073 int *list, *marker, *fill, *tmpFill;
00074 int temp, m, from = ctx->from, to = ctx->to;
00075 int *n2o_row, *o2n_col;
00076 int first_row, last_row;
00077 double *AVAL;
00078 REAL_DH *work, *aval;
00079 Factor_dh F = ctx->F;
00080 SubdomainGraph_dh sg = ctx->sg;
00081
00082 if (ctx->F == NULL)
00083 {
00084 SET_V_ERROR ("ctx->F is NULL");
00085 }
00086 if (ctx->F->rp == NULL)
00087 {
00088 SET_V_ERROR ("ctx->F->rp is NULL");
00089 }
00090
00091
00092
00093
00094 m = F->m;
00095 rp = F->rp;
00096 cval = F->cval;
00097 fill = F->fill;
00098 diag = F->diag;
00099 aval = F->aval;
00100 work = ctx->work;
00101
00102 n2o_row = sg->n2o_row;
00103 o2n_col = sg->o2n_col;
00104
00105
00106 list = (int *) MALLOC_DH ((m + 1) * sizeof (int));
00107 CHECK_V_ERROR;
00108 marker = (int *) MALLOC_DH (m * sizeof (int));
00109 CHECK_V_ERROR;
00110 tmpFill = (int *) MALLOC_DH (m * sizeof (int));
00111 CHECK_V_ERROR;
00112 for (i = 0; i < m; ++i)
00113 {
00114 marker[i] = -1;
00115 work[i] = 0.0;
00116 }
00117
00118
00119
00120
00121
00122
00123 first_row = sg->beg_row[myid_dh];
00124 last_row = first_row + sg->row_count[myid_dh];
00125 for (i = from; i < to; ++i)
00126 {
00127
00128 int row = n2o_row[i];
00129 int globalRow = row + first_row;
00130
00131 EuclidGetRow (ctx->A, globalRow, &len, &CVAL, &AVAL);
00132 CHECK_V_ERROR;
00133
00134
00135 if (ctx->isScaled)
00136 {
00137 compute_scaling_private (i, len, AVAL, ctx);
00138 CHECK_V_ERROR;
00139 }
00140
00141
00142
00143
00144 count = symbolic_row_private (i, first_row, last_row,
00145 list, marker, tmpFill,
00146 len, CVAL, AVAL, o2n_col, ctx);
00147 CHECK_V_ERROR;
00148
00149
00150 if (idx + count > F->alloc)
00151 {
00152 Factor_dhReallocate (F, idx, count);
00153 CHECK_V_ERROR;
00154 SET_INFO ("REALLOCATED from lu_mpi_bj");
00155 cval = F->cval;
00156 fill = F->fill;
00157 aval = F->aval;
00158 }
00159
00160
00161 col = list[m];
00162 while (count--)
00163 {
00164 cval[idx] = col;
00165 fill[idx] = tmpFill[col];
00166 ++idx;
00167 col = list[col];
00168 }
00169
00170
00171 rp[i + 1] = idx;
00172
00173
00174 temp = rp[i];
00175 while (cval[temp] != i)
00176 ++temp;
00177 diag[i] = temp;
00178
00179
00180 numeric_row_private (i, first_row, last_row,
00181 len, CVAL, AVAL, work, o2n_col, ctx);
00182 CHECK_V_ERROR EuclidRestoreRow (ctx->A, globalRow, &len, &CVAL, &AVAL);
00183 CHECK_V_ERROR;
00184
00185
00186
00187
00188 for (j = rp[i]; j < rp[i + 1]; ++j)
00189 {
00190 col = cval[j];
00191 aval[j] = work[col];
00192 work[col] = 0.0;
00193 }
00194
00195
00196 if (!aval[diag[i]])
00197 {
00198 sprintf (msgBuf_dh, "zero diagonal in local row %i", i + 1);
00199 SET_V_ERROR (msgBuf_dh);
00200 }
00201 }
00202
00203 FREE_DH (list);
00204 CHECK_V_ERROR;
00205 FREE_DH (tmpFill);
00206 CHECK_V_ERROR;
00207 FREE_DH (marker);
00208 CHECK_V_ERROR;
00209
00210 END_FUNC_DH}
00211
00212
00213
00214
00215
00216
00217
00218
00219 #undef __FUNC__
00220 #define __FUNC__ "symbolic_row_private"
00221 int
00222 symbolic_row_private (int localRow, int beg_row, int end_row,
00223 int *list, int *marker, int *tmpFill,
00224 int len, int *CVAL, double *AVAL,
00225 int *o2n_col, Euclid_dh ctx)
00226 {
00227 START_FUNC_DH int level = ctx->level, m = ctx->F->m;
00228 int *cval = ctx->F->cval, *diag = ctx->F->diag, *rp = ctx->F->rp;
00229 int *fill = ctx->F->fill;
00230 int count = 0;
00231 int j, node, tmp, col, head;
00232 int fill1, fill2;
00233 float val;
00234 double thresh = ctx->sparseTolA;
00235 REAL_DH scale;
00236
00237 scale = ctx->scale[localRow];
00238 ctx->stats[NZA_STATS] += (double) len;
00239
00240
00241
00242
00243
00244 list[m] = m;
00245 for (j = 0; j < len; ++j)
00246 {
00247 tmp = m;
00248 col = *CVAL++;
00249 val = *AVAL++;
00250
00251
00252 if (col >= beg_row && col < end_row)
00253 {
00254 col -= beg_row;
00255 col = o2n_col[col];
00256 if (fabs (scale * val) > thresh || col == localRow)
00257 {
00258 ++count;
00259 while (col > list[tmp])
00260 tmp = list[tmp];
00261 list[col] = list[tmp];
00262 list[tmp] = col;
00263 tmpFill[col] = 0;
00264 marker[col] = localRow;
00265 }
00266 }
00267 }
00268
00269
00270 if (marker[localRow] != localRow)
00271 {
00272
00273 tmp = m;
00274 while (localRow > list[tmp])
00275 tmp = list[tmp];
00276 list[localRow] = list[tmp];
00277 list[tmp] = localRow;
00278 tmpFill[localRow] = 0;
00279 marker[localRow] = localRow;
00280 ++count;
00281 }
00282 ctx->stats[NZA_USED_STATS] += (double) count;
00283
00284
00285 head = m;
00286 if (level > 0)
00287 {
00288 while (list[head] < localRow)
00289 {
00290 node = list[head];
00291 fill1 = tmpFill[node];
00292
00293 if (fill1 < level)
00294 {
00295 for (j = diag[node] + 1; j < rp[node + 1]; ++j)
00296 {
00297 col = cval[j];
00298 fill2 = fill1 + fill[j] + 1;
00299
00300 if (fill2 <= level)
00301 {
00302
00303
00304
00305 if (marker[col] < localRow)
00306 {
00307 tmp = head;
00308 marker[col] = localRow;
00309 tmpFill[col] = fill2;
00310 while (col > list[tmp])
00311 tmp = list[tmp];
00312 list[col] = list[tmp];
00313 list[tmp] = col;
00314 ++count;
00315 }
00316
00317
00318 else
00319 {
00320 tmpFill[col] =
00321 (fill2 < tmpFill[col]) ? fill2 : tmpFill[col];
00322 }
00323 }
00324 }
00325 }
00326 head = list[head];
00327 }
00328 }
00329 END_FUNC_VAL (count)}
00330
00331
00332 #undef __FUNC__
00333 #define __FUNC__ "numeric_row_private"
00334 int
00335 numeric_row_private (int localRow, int beg_row, int end_row,
00336 int len, int *CVAL, double *AVAL,
00337 REAL_DH * work, int *o2n_col, Euclid_dh ctx)
00338 {
00339 START_FUNC_DH double pc, pv, multiplier;
00340 int j, k, col, row;
00341 int *rp = ctx->F->rp, *cval = ctx->F->cval;
00342 int *diag = ctx->F->diag;
00343 double val;
00344 REAL_DH *aval = ctx->F->aval, scale;
00345
00346 scale = ctx->scale[localRow];
00347
00348
00349
00350
00351
00352 for (j = rp[localRow]; j < rp[localRow + 1]; ++j)
00353 {
00354 col = cval[j];
00355 work[col] = 0.0;
00356 }
00357
00358
00359
00360 for (j = 0; j < len; ++j)
00361 {
00362 col = *CVAL++;
00363 val = *AVAL++;
00364
00365 if (col >= beg_row && col < end_row)
00366 {
00367 col -= beg_row;
00368 col = o2n_col[col];
00369 work[col] = val * scale;
00370 }
00371 }
00372
00373 for (j = rp[localRow]; j < diag[localRow]; ++j)
00374 {
00375 row = cval[j];
00376 pc = work[row];
00377
00378 if (pc != 0.0)
00379 {
00380 pv = aval[diag[row]];
00381 multiplier = pc / pv;
00382 work[row] = multiplier;
00383
00384 for (k = diag[row] + 1; k < rp[row + 1]; ++k)
00385 {
00386 col = cval[k];
00387 work[col] -= (multiplier * aval[k]);
00388 }
00389 }
00390 }
00391
00392
00393 #if 0
00394 if (fabs (work[i]) <= pivotTol)
00395 {
00396
00397 aval[diag[i]] = pivotFix;
00398 }
00399 #endif
00400
00401 END_FUNC_VAL (0)}