00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SELDON_FILE_SYMMETRIC_ILUT_PRECONDITIONING_CXX
00021
00022 namespace Seldon
00023 {
00024
00026 template<class real, class cplx, class Allocator1, class Allocator2>
00027 void GetIlut(const IlutPreconditioning<real, cplx, Allocator1>& param,
00028 Matrix<cplx, Symmetric, ArrayRowSymSparse, Allocator2>& A)
00029 {
00030 int size_row;
00031 int n = A.GetN();
00032 int lfil = param.GetFillLevel();
00033 real zero = 0.0;
00034 real droptol = param.GetDroppingThreshold();
00035 real alpha = param.GetDiagonalCoefficient();
00036 bool variable_fill = false;
00037 bool standard_dropping = true;
00038 int type_factorisation = param.GetFactorisationType();
00039 int additional_fill = param.GetAdditionalFillNumber();
00040 int print_level = param.GetPrintLevel();
00041 if (type_factorisation == param.ILUT)
00042 standard_dropping = false;
00043 else if (type_factorisation == param.ILU_D)
00044 standard_dropping = true;
00045 else if (type_factorisation == param.ILUT_K)
00046 {
00047 variable_fill = true;
00048 standard_dropping = false;
00049 }
00050 else if (type_factorisation == param.ILU_0)
00051 {
00052 GetIlu0(A);
00053 return;
00054 }
00055 else if (type_factorisation == param.MILU_0)
00056 {
00057 GetMilu0(A);
00058 return;
00059 }
00060 else if (type_factorisation == param.ILU_K)
00061 {
00062 GetIluk(lfil, A);
00063 return;
00064 }
00065
00066 cplx fact, s, t; real tnorm;
00067 int length_lower, length_upper, jpos, jrow;
00068 int i_row, j_col, index_lu, length;
00069 int i, j, k;
00070
00071 if (lfil < 0)
00072 {
00073 cout << "Incorrect fill level." << endl;
00074 abort();
00075 }
00076
00077 typedef Vector<cplx, VectFull, Allocator2> VectCplx;
00078 VectCplx Row_Val(n);
00079 IVect Index(n), Row_Ind(n);
00080 Row_Val.Zero(); Row_Ind.Fill(-1);
00081
00082 Index.Fill(-1);
00083
00084 bool element_dropped; cplx dropsum;
00085
00086
00087 Matrix<cplx, General, ArrayRowSparse, Allocator2> B;
00088 Seldon::Copy(A, B);
00089
00090 A.Clear();
00091 A.Reallocate(n, n);
00092
00093
00094 int new_percent = 0, old_percent = 0;
00095 for (i_row = 0; i_row < n; i_row++)
00096 {
00097
00098 if (print_level > 0)
00099 {
00100 new_percent = int(real(i_row)/(n-1)*80);
00101 for (int percent = old_percent; percent < new_percent; percent++)
00102 {
00103 cout << "#"; cout.flush();
00104 }
00105
00106 old_percent = new_percent;
00107 }
00108
00109
00110 size_row = B.GetRowSize(i_row);
00111 tnorm = zero;
00112 dropsum = zero;
00113 for (k = 0 ; k < size_row; k++)
00114 tnorm += abs(B.Value(i_row, k));
00115
00116 if (tnorm == zero)
00117 {
00118 cout << "Structurally singular matrix." << endl;
00119 cout << "Norm of row " << i_row << " is equal to 0." << endl;
00120 abort();
00121 }
00122
00123
00124 tnorm /= real(size_row);
00125 if (variable_fill)
00126 lfil = size_row + additional_fill;
00127
00128
00129
00130 length_upper = 1;
00131 length_lower = 0;
00132 Row_Ind(i_row) = i_row;
00133 Row_Val(i_row) = 0.0;
00134 Index(i_row) = i_row;
00135
00136 for (j = 0; j < size_row; j++)
00137 {
00138 k = B.Index(i_row,j);
00139 t = B.Value(i_row,j);
00140 if (k < i_row)
00141 {
00142 Row_Ind(length_lower) = k;
00143 Row_Val(length_lower) = t;
00144 Index(k) = length_lower;
00145 ++length_lower;
00146 }
00147 else if (k == i_row)
00148 {
00149 Row_Val(i_row) = t;
00150 }
00151 else
00152 {
00153 jpos = i_row + length_upper;
00154 Row_Ind(jpos) = k;
00155 Row_Val(jpos) = t;
00156 Index(k) = jpos;
00157 length_upper++;
00158 }
00159 }
00160
00161
00162 B.ClearRow(i_row);
00163
00164 j_col = 0;
00165 length = 0;
00166
00167
00168
00169 while (j_col <length_lower)
00170 {
00171
00172
00173 jrow = Row_Ind(j_col);
00174 k = j_col;
00175
00176
00177 for (j = (j_col+1) ; j < length_lower; j++)
00178 {
00179 if (Row_Ind(j) < jrow)
00180 {
00181 jrow = Row_Ind(j);
00182 k = j;
00183 }
00184 }
00185
00186
00187
00188 if (k != j_col)
00189 {
00190
00191 j = Row_Ind(j_col);
00192 Row_Ind(j_col) = Row_Ind(k);
00193 Row_Ind(k) = j;
00194
00195 Index(jrow) = j_col;
00196 Index(j) = k;
00197
00198 s = Row_Val(j_col);
00199 Row_Val(j_col) = Row_Val(k);
00200 Row_Val(k) = s;
00201 }
00202
00203
00204 Index(jrow) = -1;
00205
00206 element_dropped = false;
00207 if (standard_dropping)
00208 if (abs(Row_Val(j_col)) <= droptol*tnorm)
00209 {
00210 dropsum += Row_Val(j_col);
00211 element_dropped = true;
00212 }
00213
00214
00215 if (!element_dropped)
00216 {
00217 fact = Row_Val(j_col) * A.Value(jrow, 0);
00218
00219 if (!standard_dropping)
00220 {
00221 if (abs(fact) <= droptol)
00222 element_dropped = true;
00223 }
00224 }
00225
00226 if (!element_dropped)
00227 {
00228
00229 for (k = 1; k < A.GetRowSize(jrow); k++)
00230 {
00231 s = fact * A.Value(jrow,k);
00232 j = A.Index(jrow,k);
00233
00234 jpos = Index(j);
00235 if (j >= i_row)
00236 {
00237
00238
00239 if (jpos == -1)
00240 {
00241
00242
00243 i = i_row + length_upper;
00244 Row_Ind(i) = j;
00245 Index(j) = i;
00246 Row_Val(i) = -s;
00247 ++length_upper;
00248 }
00249 else
00250 {
00251
00252 Row_Val(jpos) -= s;
00253 }
00254 }
00255 else
00256 {
00257
00258 if (jpos == -1)
00259 {
00260
00261 Row_Ind(length_lower) = j;
00262 Index(j) = length_lower;
00263 Row_Val(length_lower) = -s;
00264 ++length_lower;
00265 }
00266 else
00267 {
00268
00269 Row_Val(jpos) -= s;
00270 }
00271 }
00272 }
00273
00274
00275
00276 Row_Val(length) = fact;
00277 Row_Ind(length) = jrow;
00278 ++length;
00279 }
00280
00281 j_col++;
00282 }
00283
00284
00285 for (k = 0; k < length_upper; k++)
00286 Index(Row_Ind(i_row+k )) = -1;
00287
00288
00289
00290 length = 0;
00291 for (k = 1; k <= (length_upper-1); k++)
00292 {
00293 if (abs(Row_Val(i_row+k)) > droptol * tnorm)
00294 {
00295 ++length;
00296 Row_Val(i_row+length) = Row_Val(i_row+k);
00297 Row_Ind(i_row+length) = Row_Ind(i_row+k);
00298 }
00299 else
00300 dropsum += Row_Val(i_row+k);
00301 }
00302
00303
00304 if (!standard_dropping)
00305 {
00306 length_upper = length + 1;
00307 length = min(length_upper, lfil);
00308
00309 qsplit_ilut(Row_Val, Row_Ind, i_row+1,
00310 i_row+length_upper, i_row+length+1, tnorm);
00311 }
00312 else
00313 length++;
00314
00315
00316 A.ReallocateRow(i_row, length);
00317 index_lu = 1;
00318 for (k = (i_row+1) ; k <= (i_row+length-1) ; k++)
00319 {
00320 A.Index(i_row,index_lu) = Row_Ind(k);
00321 A.Value(i_row,index_lu) = Row_Val(k);
00322 ++index_lu;
00323 }
00324
00325
00326 if (standard_dropping)
00327 Row_Val(i_row) += alpha*dropsum;
00328
00329 if (Row_Val(i_row) == zero)
00330 Row_Val(i_row) = (droptol + 1e-4) * tnorm;
00331
00332 A.Value(i_row,0) = 1.0 / Row_Val(i_row);
00333
00334 }
00335
00336 if (print_level > 0)
00337 cout<<endl;
00338
00339
00340 for (int i = 0; i < n; i++)
00341 for (int j = 1; j < A.GetRowSize(i); j++)
00342 A.Value(i,j) *= A.Value(i,0);
00343
00344 if (print_level > 0)
00345 cout << "The matrix takes " <<
00346 int((A.GetDataSize()*(sizeof(cplx)+4))/(1024*1024)) << " MB" << endl;
00347
00348 }
00349
00350
00351 template<class cplx, class Allocator>
00352 void GetIluk(int lfil,
00353 Matrix<cplx, Symmetric, ArrayRowSymSparse, Allocator>& A)
00354 {
00355 int n = A.GetM();
00356 Vector<cplx, VectFull, CallocAlloc<cplx> > w;
00357 w.Reallocate(n+1);
00358 IVect jw(3*n);
00359 Vector<IVect, VectFull, NewAlloc<IVect> > levs(n);
00360
00361
00362 cplx fact, s, t;
00363 int length_lower, length_upper, jpos, jrow, i_row, j_col;
00364 int i, j, k, index_lu, length;
00365 bool element_dropped;
00366
00367
00368 int n2 = 2*n, jlev, k_, size_upper;
00369 jw.Fill(-1);
00370
00371
00372 Matrix<cplx, General, ArrayRowSparse, Allocator> B;
00373 Seldon::Copy(A,B);
00374
00375
00376 for (i_row = 0; i_row < n; i_row++)
00377 {
00378 int size_row = A.GetRowSize(i_row);
00379
00380
00381 length_upper = 1;
00382 length_lower = 0;
00383 jw(i_row) = i_row;
00384 w(i_row) = 0.0;
00385 jw(n + i_row) = i_row;
00386
00387 for (j = 0; j < size_row; j++)
00388 {
00389 k = B.Index(i_row,j);
00390 t = B.Value(i_row,j);
00391 if (k < i_row)
00392 {
00393 jw(length_lower) = k;
00394 w(length_lower) = t;
00395 jw(n + k) = length_lower;
00396 jw(n2+length_lower) = -1;
00397 ++length_lower;
00398 }
00399 else if (k == i_row)
00400 {
00401 w(i_row) = t;
00402 jw(n2+length_lower) = -1;
00403 }
00404 else
00405 {
00406 jpos = i_row + length_upper;
00407 jw(jpos) = k;
00408 w(jpos) = t;
00409 jw(n + k) = jpos;
00410 length_upper++;
00411 }
00412 }
00413
00414 B.ClearRow(i_row);
00415
00416 j_col = 0;
00417 length = 0;
00418
00419
00420 while (j_col <length_lower)
00421 {
00422
00423
00424
00425
00426 jrow = jw(j_col);
00427 k = j_col;
00428
00429
00430 for (j = (j_col+1) ; j < length_lower; j++)
00431 {
00432 if (jw(j) < jrow)
00433 {
00434 jrow = jw(j);
00435 k = j;
00436 }
00437 }
00438
00439 if (k!=j_col)
00440 {
00441
00442 j = jw(j_col);
00443 jw(j_col) = jw(k);
00444 jw(k) = j;
00445
00446
00447 jw(n+jrow) = j_col;
00448 jw(n+j) = k;
00449
00450
00451 j = jw(n2+j_col);
00452 jw(n2+j_col) = jw(n2+k);
00453 jw(n2+k) = j;
00454
00455
00456 s = w(j_col);
00457 w(j_col) = w(k);
00458 w(k) = s;
00459 }
00460
00461
00462
00463 jw(n + jrow) = -1;
00464
00465 element_dropped = false;
00466
00467
00468 fact = w(j_col) * A.Value(jrow,0);
00469
00470 jlev = jw(n2+j_col) + 1;
00471 if (jlev > lfil)
00472 element_dropped = true;
00473
00474 if (!element_dropped)
00475 {
00476
00477 k_ = 0;
00478 for (k = 1; k < A.GetRowSize(jrow) ; k++)
00479 {
00480 s = fact * A.Value(jrow,k);
00481 j = A.Index(jrow,k);
00482
00483 jpos = jw(n + j);
00484
00485 if (j >= i_row)
00486 {
00487
00488 if (jpos == -1)
00489 {
00490
00491 i = i_row + length_upper;
00492 jw(i) = j;
00493 jw(n + j) = i;
00494 w(i) = -s;
00495
00496 jw(n2+i) = jlev + levs(jrow)(k_) + 1;
00497 ++length_upper;
00498 }
00499 else
00500 {
00501
00502 w(jpos) -= s;
00503 jw(n2+jpos) = min(jw(n2+jpos),
00504 jlev+levs(jrow)(k_)+1);
00505 }
00506 }
00507 else
00508 {
00509
00510 if (jpos == -1)
00511 {
00512
00513 jw(length_lower) = j;
00514 jw(n + j) = length_lower;
00515 w(length_lower) = -s;
00516 jw(n2+length_lower) = jlev + levs(jrow)(k_) + 1;
00517 ++length_lower;
00518 }
00519 else
00520 {
00521
00522 w(jpos) -= s;
00523 jw(n2+jpos) = min(jw(n2+jpos),
00524 jlev+levs(jrow)(k_)+1);
00525 }
00526 }
00527 k_++;
00528 }
00529
00530 }
00531
00532
00533
00534 w(j_col) = fact;
00535 jw(j_col) = jrow;
00536
00537 j_col++;
00538 }
00539
00540
00541 for (k = 0; k < length_upper; k++)
00542 jw(n + jw(i_row + k )) = -1;
00543
00544
00545 size_row = 1;
00546
00547
00548 size_upper = 0;
00549 for (k = (i_row+1) ; k <= (i_row+length_upper-1) ; k++)
00550 if (jw(n2+k) < lfil)
00551 size_upper++;
00552
00553 size_row += size_upper;
00554 A.ReallocateRow(i_row, size_row);
00555 levs(i_row).Reallocate(size_upper);
00556
00557 index_lu = 0;
00558
00559 A.Value(i_row,index_lu) = 1.0 / w(i_row);
00560 A.Index(i_row,index_lu++) = i_row;
00561
00562
00563 for (k = (i_row+1) ; k <= (i_row+length_upper-1) ; k++)
00564 {
00565 if (jw(n2+k) < lfil)
00566 {
00567 A.Index(i_row,index_lu) = jw(k);
00568 A.Value(i_row,index_lu) = w(k);
00569 levs(i_row)(index_lu-1) = jw(n2+k);
00570 ++index_lu;
00571 }
00572 }
00573 }
00574
00575
00576 for (int i = 0; i < n; i++)
00577 for (int j = 1; j < A.GetRowSize(i); j++)
00578 A.Value(i,j) *= A.Value(i,0);
00579
00580 }
00581
00582
00583 template<class cplx, class Allocator>
00584 void GetIlu0(Matrix<cplx, Symmetric, ArrayRowSymSparse, Allocator>& A)
00585 {
00586 cout << "Not implemented." << endl;
00587 abort();
00588 }
00589
00590
00591 template<class cplx, class Allocator>
00592 void GetMilu0(Matrix<cplx, Symmetric, ArrayRowSymSparse, Allocator>& A)
00593 {
00594 cout << "Not implemented." << endl;
00595 abort();
00596 }
00597
00598
00600
00603 template<class real, class cplx, class Allocator,
00604 class Storage2, class Allocator2>
00605 void SolveLU(const Matrix<real, Symmetric, ArrayRowSymSparse, Allocator>& A,
00606 Vector<cplx, Storage2, Allocator2>& x)
00607 {
00608 int n = A.GetM(), j_row;
00609 cplx tmp;
00610
00611
00612 for (int i_col = 0; i_col < n ; i_col++)
00613 {
00614 for (int k = 1; k < A.GetRowSize(i_col) ; k++)
00615 {
00616 j_row = A.Index(i_col, k);
00617 x(j_row) -= A.Value(i_col, k)*x(i_col);
00618 }
00619 }
00620
00621
00622 for (int i_col = 0; i_col < n ; i_col++)
00623 x(i_col) *= A.Value(i_col,0);
00624
00625
00626 for (int i_col = n-1; i_col >=0 ; i_col--)
00627 {
00628 tmp = x(i_col);
00629 for (int k = 1; k < A.GetRowSize(i_col) ; k++)
00630 {
00631 j_row = A.Index(i_col,k);
00632 tmp -= A.Value(i_col,k)*x(j_row);
00633 }
00634 x(i_col) = tmp;
00635 }
00636 }
00637
00638 }
00639
00640 #define SELDON_SYMMETRIC_ILUT_PRECONDITIONING_CXX
00641 #endif