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