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 #include "Euclid_dh.h"
00031 #include "Factor_dh.h"
00032 #include "Mat_dh.h"
00033 #include "ilu_dh.h"
00034 #include "Mem_dh.h"
00035 #include "Parser_dh.h"
00036 #include "Hash_dh.h"
00037 #include "getRow_dh.h"
00038 #include "SortedList_dh.h"
00039 #include "ExternalRows_dh.h"
00040 #include "SubdomainGraph_dh.h"
00041
00042
00043 static void iluk_symbolic_row_private (int localRow, int len, int *CVAL,
00044 double *AVAL, ExternalRows_dh extRows,
00045 SortedList_dh sList, Euclid_dh ctx,
00046 bool debug);
00047
00048 static void iluk_numeric_row_private (int new_row, ExternalRows_dh extRows,
00049 SortedList_dh slist, Euclid_dh ctx,
00050 bool debug);
00051
00052 #undef __FUNC__
00053 #define __FUNC__ "iluk_mpi_pilu"
00054 void
00055 iluk_mpi_pilu (Euclid_dh ctx)
00056 {
00057 START_FUNC_DH int from = ctx->from, to = ctx->to;
00058 int i, m;
00059 int *n2o_row;
00060 int *rp, *cval, *diag, *fill;
00061 int beg_row, beg_rowP, end_rowP;
00062 SubdomainGraph_dh sg = ctx->sg;
00063 int *CVAL, len, idx = 0, count;
00064 double *AVAL;
00065 REAL_DH *aval;
00066 Factor_dh F = ctx->F;
00067 SortedList_dh slist = ctx->slist;
00068 ExternalRows_dh extRows = ctx->extRows;
00069 bool bj, noValues, debug = false;
00070
00071
00072 if (logFile != NULL && Parser_dhHasSwitch (parser_dh, "-debug_ilu"))
00073 debug = true;
00074 noValues = Parser_dhHasSwitch (parser_dh, "-noValues");
00075 bj = ctx->F->blockJacobi;
00076
00077 m = F->m;
00078 rp = F->rp;
00079 cval = F->cval;
00080 fill = F->fill;
00081 diag = F->diag;
00082 aval = F->aval;
00083
00084
00085 n2o_row = sg->n2o_row;
00086
00087
00088 if (from != 0)
00089 idx = rp[from];
00090
00091
00092
00093
00094 beg_row = sg->beg_row[myid_dh];
00095
00096
00097
00098 beg_rowP = sg->beg_rowP[myid_dh];
00099 end_rowP = beg_rowP + sg->row_count[myid_dh];
00100
00101
00102
00103 for (i = from; i < to; ++i)
00104 {
00105
00106 int row = n2o_row[i];
00107 int globalRow = row + beg_row;
00108
00109 if (debug)
00110 {
00111 fprintf (logFile,
00112 "\nILU_pilu global: %i old_Local: %i =========================================================\n",
00113 i + 1 + beg_rowP, row + 1);
00114 }
00115
00116 EuclidGetRow (ctx->A, globalRow, &len, &CVAL, &AVAL);
00117 CHECK_V_ERROR;
00118
00119 if (debug)
00120 {
00121 int h;
00122 fprintf (logFile, "ILU_pilu EuclidGetRow:\n");
00123 for (h = 0; h < len; ++h)
00124 fprintf (logFile, " %i %g\n", 1 + CVAL[h], AVAL[h]);
00125 }
00126
00127
00128
00129 if (ctx->isScaled)
00130 {
00131 compute_scaling_private (i, len, AVAL, ctx);
00132 CHECK_V_ERROR;
00133 }
00134
00135 SortedList_dhReset (slist, i);
00136 CHECK_V_ERROR;
00137
00138
00139
00140
00141 iluk_symbolic_row_private (i, len, CVAL, AVAL,
00142 extRows, slist, ctx, debug);
00143 CHECK_V_ERROR;
00144
00145
00146 SortedList_dhEnforceConstraint (slist, sg);
00147
00148
00149 if (!noValues)
00150 {
00151 iluk_numeric_row_private (i, extRows, slist, ctx, debug);
00152 CHECK_V_ERROR;
00153 }
00154
00155 EuclidRestoreRow (ctx->A, globalRow, &len, &CVAL, &AVAL);
00156 CHECK_V_ERROR;
00157
00158
00159 count = SortedList_dhReadCount (slist);
00160 CHECK_V_ERROR;
00161
00162
00163 if (idx + count > F->alloc)
00164 {
00165 Factor_dhReallocate (F, idx, count);
00166 CHECK_V_ERROR;
00167 SET_INFO ("REALLOCATED from ilu_mpi_pilu");
00168 cval = F->cval;
00169 fill = F->fill;
00170 aval = F->aval;
00171 }
00172
00173
00174 if (bj)
00175 {
00176 int col;
00177 while (count--)
00178 {
00179 SRecord *sr = SortedList_dhGetSmallest (slist);
00180 CHECK_V_ERROR;
00181 col = sr->col;
00182 if (col >= beg_rowP && col < end_rowP)
00183 {
00184 cval[idx] = col;
00185 if (noValues)
00186 {
00187 aval[idx] = 0.0;
00188 }
00189 else
00190 {
00191 aval[idx] = sr->val;
00192 }
00193 fill[idx] = sr->level;
00194 ++idx;
00195 }
00196 }
00197 }
00198
00199 if (debug)
00200 {
00201 fprintf (logFile, "ILU_pilu ");
00202 while (count--)
00203 {
00204 SRecord *sr = SortedList_dhGetSmallest (slist);
00205 CHECK_V_ERROR;
00206 cval[idx] = sr->col;
00207 aval[idx] = sr->val;
00208 fill[idx] = sr->level;
00209 fprintf (logFile, "%i,%i,%g ; ", 1 + cval[idx], fill[idx],
00210 aval[idx]);
00211 ++idx;
00212 }
00213 fprintf (logFile, "\n");
00214 }
00215
00216 else
00217 {
00218 while (count--)
00219 {
00220 SRecord *sr = SortedList_dhGetSmallest (slist);
00221 CHECK_V_ERROR;
00222 cval[idx] = sr->col;
00223 aval[idx] = sr->val;
00224 fill[idx] = sr->level;
00225 ++idx;
00226 }
00227 }
00228
00229
00230 rp[i + 1] = idx;
00231
00232
00233 {
00234 int temp = rp[i];
00235 bool flag = true;
00236 while (temp < idx)
00237 {
00238 if (cval[temp] == i + beg_rowP)
00239 {
00240 diag[i] = temp;
00241 flag = false;
00242 break;
00243 }
00244 ++temp;
00245 }
00246 if (flag)
00247 {
00248 if (logFile != NULL)
00249 {
00250 int k;
00251 fprintf (logFile,
00252 "Failed to find diag in localRow %i (globalRow %i; ct= %i)\n ",
00253 1 + i, i + 1 + beg_rowP, rp[i + 1] - rp[i]);
00254 for (k = rp[i]; k < rp[i + 1]; ++k)
00255 {
00256 fprintf (logFile, "%i ", cval[i] + 1);
00257 }
00258 fprintf (logFile, "\n\n");
00259 }
00260 sprintf (msgBuf_dh, "failed to find diagonal for localRow: %i",
00261 1 + i);
00262 SET_V_ERROR (msgBuf_dh);
00263 }
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (!aval[diag[i]])
00274 {
00275 sprintf (msgBuf_dh, "zero diagonal in local row %i", i + 1);
00276 SET_V_ERROR (msgBuf_dh);
00277 }
00278
00279 }
00280
00281
00282 if (bj)
00283 {
00284 int nz = rp[m];
00285 for (i = 0; i < nz; ++i)
00286 cval[i] -= beg_rowP;
00287 }
00288
00289 END_FUNC_DH}
00290
00291
00292 #undef __FUNC__
00293 #define __FUNC__ "iluk_symbolic_row_private"
00294 void
00295 iluk_symbolic_row_private (int localRow, int len, int *CVAL,
00296 double *AVAL, ExternalRows_dh extRows,
00297 SortedList_dh slist, Euclid_dh ctx, bool debug)
00298 {
00299 START_FUNC_DH int level = ctx->level, m = ctx->m;
00300 int beg_row = ctx->sg->beg_row[myid_dh];
00301 int beg_rowP = ctx->sg->beg_rowP[myid_dh];
00302 int *cval = ctx->F->cval, *diag = ctx->F->diag;
00303 int *rp = ctx->F->rp, *fill = ctx->F->fill;
00304 int j, node, col;
00305 int end_rowP = beg_rowP + m;
00306 int level_1, level_2;
00307 int *cvalPtr, *fillPtr;
00308 SRecord sr, *srPtr;
00309 REAL_DH scale, *avalPtr;
00310 double thresh = ctx->sparseTolA;
00311 bool wasInserted;
00312 int count = 0;
00313
00314 scale = ctx->scale[localRow];
00315 ctx->stats[NZA_STATS] += (double) len;
00316
00317
00318 sr.level = 0;
00319 for (j = 0; j < len; ++j)
00320 {
00321 sr.col = CVAL[j];
00322 sr.val = scale * AVAL[j];
00323
00324 wasInserted = SortedList_dhPermuteAndInsert (slist, &sr, thresh);
00325 CHECK_V_ERROR;
00326 if (wasInserted)
00327 ++count;
00328
00329 if (debug)
00330 {
00331 fprintf (logFile, "ILU_pilu inserted from A: col= %i val= %g\n",
00332 1 + CVAL[j], sr.val);
00333 }
00334 }
00335
00336
00337 sr.val = 0.0;
00338 sr.col = localRow + beg_rowP;
00339 srPtr = SortedList_dhFind (slist, &sr);
00340 CHECK_V_ERROR;
00341 if (srPtr == NULL)
00342 {
00343 SortedList_dhInsert (slist, &sr);
00344 CHECK_V_ERROR;
00345 ++count;
00346 if (debug)
00347 {
00348 fprintf (logFile, "ILU_pilu inserted missing diagonal: %i\n",
00349 1 + localRow + beg_row);
00350 }
00351 }
00352 ctx->stats[NZA_USED_STATS] += (double) count;
00353
00354
00355 sr.val = 0.0;
00356 if (level > 0)
00357 {
00358 while (1)
00359 {
00360 srPtr = SortedList_dhGetSmallestLowerTri (slist);
00361 CHECK_V_ERROR;
00362 if (srPtr == NULL)
00363 break;
00364
00365 node = srPtr->col;
00366
00367 if (debug)
00368 {
00369 fprintf (logFile, "ILU_pilu sf updating from row: %i\n",
00370 1 + srPtr->col);
00371 }
00372
00373 level_1 = srPtr->level;
00374 if (level_1 < level)
00375 {
00376
00377
00378 if (node >= beg_rowP && node < end_rowP)
00379 {
00380 node -= beg_rowP;
00381 len = rp[node + 1] - diag[node] - 1;
00382 cvalPtr = cval + diag[node] + 1;
00383 fillPtr = fill + diag[node] + 1;
00384 }
00385
00386
00387 else
00388 {
00389 len = 0;
00390 ExternalRows_dhGetRow (extRows, node, &len, &cvalPtr,
00391 &fillPtr, &avalPtr);
00392 CHECK_V_ERROR;
00393 if (debug && len == 0)
00394 {
00395 fprintf (stderr,
00396 "ILU_pilu sf failed to get extern row: %i\n",
00397 1 + node);
00398 }
00399 }
00400
00401
00402
00403 for (j = 0; j < len; ++j)
00404 {
00405 col = *cvalPtr++;
00406 level_2 = 1 + level_1 + *fillPtr++;
00407 if (level_2 <= level)
00408 {
00409
00410 sr.col = col;
00411 sr.level = level_2;
00412 sr.val = 0.0;
00413 SortedList_dhInsertOrUpdate (slist, &sr);
00414 CHECK_V_ERROR;
00415 }
00416 }
00417 }
00418 }
00419 }
00420 END_FUNC_DH}
00421
00422
00423 #undef __FUNC__
00424 #define __FUNC__ "iluk_numeric_row_private"
00425 void
00426 iluk_numeric_row_private (int new_row, ExternalRows_dh extRows,
00427 SortedList_dh slist, Euclid_dh ctx, bool debug)
00428 {
00429 START_FUNC_DH int m = ctx->m;
00430 int beg_rowP = ctx->sg->beg_rowP[myid_dh];
00431 int end_rowP = beg_rowP + m;
00432 int len, row;
00433 int *rp = ctx->F->rp, *cval = ctx->F->cval, *diag = ctx->F->diag;
00434 REAL_DH *avalPtr, *aval = ctx->F->aval;
00435 int *cvalPtr;
00436 double multiplier, pc, pv;
00437 SRecord sr, *srPtr;
00438
00439
00440
00441 SortedList_dhResetGetSmallest (slist);
00442 CHECK_V_ERROR;
00443 while (1)
00444 {
00445 srPtr = SortedList_dhGetSmallestLowerTri (slist);
00446 CHECK_V_ERROR;
00447 if (srPtr == NULL)
00448 break;
00449
00450
00451
00452
00453 row = srPtr->col;
00454
00455 if (row >= beg_rowP && row < end_rowP)
00456 {
00457 int local_row = row - beg_rowP;
00458
00459 len = rp[local_row + 1] - diag[local_row];
00460 cvalPtr = cval + diag[local_row];
00461 avalPtr = aval + diag[local_row];
00462 }
00463 else
00464 {
00465 len = 0;
00466 ExternalRows_dhGetRow (extRows, row, &len, &cvalPtr,
00467 NULL, &avalPtr);
00468 CHECK_V_ERROR;
00469 if (debug && len == 0)
00470 {
00471 fprintf (stderr, "ILU_pilu failed to get extern row: %i\n",
00472 1 + row);
00473 }
00474
00475 }
00476
00477 if (len)
00478 {
00479
00480 sr.col = row;
00481 srPtr = SortedList_dhFind (slist, &sr);
00482 CHECK_V_ERROR;
00483 if (srPtr == NULL)
00484 {
00485 sprintf (msgBuf_dh,
00486 "find failed for sr.col = %i while factoring local row= %i \n",
00487 1 + sr.col, new_row + 1);
00488 SET_V_ERROR (msgBuf_dh);
00489 }
00490
00491 pc = srPtr->val;
00492
00493 if (pc != 0.0)
00494 {
00495 pv = *avalPtr++;
00496 --len;
00497 ++cvalPtr;
00498 multiplier = pc / pv;
00499 srPtr->val = multiplier;
00500
00501 if (debug)
00502 {
00503 fprintf (logFile,
00504 "ILU_pilu nf updating from row: %i; multiplier = %g\n",
00505 1 + srPtr->col, multiplier);
00506 }
00507
00508
00509 while (len--)
00510 {
00511 sr.col = *cvalPtr++;
00512 sr.val = *avalPtr++;
00513 srPtr = SortedList_dhFind (slist, &sr);
00514 CHECK_V_ERROR;
00515 if (srPtr != NULL)
00516 {
00517 srPtr->val -= (multiplier * sr.val);
00518 }
00519 }
00520 }
00521
00522 else
00523 {
00524 if (debug)
00525 {
00526 fprintf (logFile,
00527 "ILU_pilu NO UPDATE from row: %i; srPtr->val = 0.0\n",
00528 1 + srPtr->col);
00529 }
00530 }
00531
00532 }
00533 }
00534 END_FUNC_DH}