00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SELDON_FILE_ILUT_PRECONDITIONING_CXX
00021
00022 #include "SymmetricIlutPreconditioning.cxx"
00023
00024 namespace Seldon
00025 {
00026
00027 template<class real, class cplx, class Allocator>
00028 IlutPreconditioning<real, cplx, Allocator>::IlutPreconditioning()
00029 {
00030 print_level = 0;
00031 symmetric_algorithm = false;
00032 type_ilu = ILUT;
00033 fill_level = 1000000;
00034 additional_fill = 1000000;
00035 mbloc = 1000000;
00036 alpha = 1.0;
00037 droptol = 0.01;
00038 permtol = 0.1;
00039 }
00040
00041
00042 template<class real, class cplx, class Allocator>
00043 void IlutPreconditioning<real, cplx, Allocator>::Clear()
00044 {
00045 permutation_row.Clear();
00046 mat_sym.Clear();
00047 mat_unsym.Clear();
00048 xtmp.Clear();
00049 }
00050
00051
00052 template<class real, class cplx, class Allocator>
00053 int IlutPreconditioning<real, cplx, Allocator>::GetFactorisationType() const
00054 {
00055 return type_ilu;
00056 }
00057
00058
00059 template<class real, class cplx, class Allocator>
00060 int IlutPreconditioning<real, cplx, Allocator>::GetFillLevel() const
00061 {
00062 return fill_level;
00063 }
00064
00065
00066 template<class real, class cplx, class Allocator>
00067 int IlutPreconditioning<real, cplx, Allocator>::GetAdditionalFillNumber()
00068 const
00069 {
00070 return additional_fill;
00071 }
00072
00073
00074 template<class real, class cplx, class Allocator>
00075 int IlutPreconditioning<real, cplx, Allocator>::GetPrintLevel() const
00076 {
00077 return print_level;
00078 }
00079
00080
00081 template<class real, class cplx, class Allocator>
00082 int IlutPreconditioning<real, cplx, Allocator>::GetPivotBlockInteger() const
00083 {
00084 return mbloc;
00085 }
00086
00087
00088 template<class real, class cplx, class Allocator>
00089 void IlutPreconditioning<real, cplx, Allocator>
00090 ::SetFactorisationType(int type)
00091 {
00092 type_ilu = type;
00093 }
00094
00095
00096 template<class real, class cplx, class Allocator>
00097 void IlutPreconditioning<real, cplx, Allocator>::SetFillLevel(int level)
00098 {
00099 fill_level = level;
00100 }
00101
00102
00103 template<class real, class cplx, class Allocator>
00104 void IlutPreconditioning<real, cplx, Allocator>
00105 ::SetAdditionalFillNumber(int level)
00106 {
00107 additional_fill = level;
00108 }
00109
00110
00111 template<class real, class cplx, class Allocator>
00112 void IlutPreconditioning<real, cplx, Allocator>::SetPrintLevel(int level)
00113 {
00114 print_level = level;
00115 }
00116
00117
00118 template<class real, class cplx, class Allocator>
00119 void IlutPreconditioning<real, cplx, Allocator>::SetPivotBlockInteger(int i)
00120 {
00121 mbloc = i;
00122 }
00123
00124
00125 template<class real, class cplx, class Allocator>
00126 real IlutPreconditioning<real, cplx, Allocator>
00127 ::GetDroppingThreshold() const
00128 {
00129 return droptol;
00130 }
00131
00132
00133 template<class real, class cplx, class Allocator>
00134 real IlutPreconditioning<real, cplx, Allocator>
00135 ::GetDiagonalCoefficient() const
00136 {
00137 return alpha;
00138 }
00139
00140
00141 template<class real, class cplx, class Allocator>
00142 real IlutPreconditioning<real, cplx, Allocator>::GetPivotThreshold() const
00143 {
00144 return permtol;
00145 }
00146
00147
00148 template<class real, class cplx, class Allocator>
00149 void IlutPreconditioning<real, cplx, Allocator>
00150 ::SetDroppingThreshold(real tol)
00151 {
00152 droptol = tol;
00153 }
00154
00155
00156 template<class real, class cplx, class Allocator>
00157 void IlutPreconditioning<real, cplx, Allocator>
00158 ::SetDiagonalCoefficient(real beta)
00159 {
00160 alpha = beta;
00161 }
00162
00163
00164 template<class real, class cplx, class Allocator>
00165 void IlutPreconditioning<real, cplx, Allocator>::SetPivotThreshold(real tol)
00166 {
00167 permtol = tol;
00168 }
00169
00170
00171 template<class real, class cplx, class Allocator>
00172 void IlutPreconditioning<real, cplx, Allocator>::SetSymmetricAlgorithm()
00173 {
00174 symmetric_algorithm = true;
00175 }
00176
00177
00178 template<class real, class cplx, class Allocator>
00179 void IlutPreconditioning<real, cplx, Allocator>::SetUnsymmetricAlgorithm()
00180 {
00181 symmetric_algorithm = false;
00182 }
00183
00184
00185 template<class real, class cplx, class Allocator>
00186 template<class T0, class Storage0, class Allocator0>
00187 void IlutPreconditioning<real, cplx, Allocator>::
00188 FactorizeMatrix(const IVect& perm,
00189 Matrix<T0, General, Storage0, Allocator0>& mat,
00190 bool keep_matrix)
00191 {
00192 if (symmetric_algorithm)
00193 {
00194 cout << "Conversion to symmetric matrices not implemented." << endl;
00195 abort();
00196 }
00197 else
00198 FactorizeUnsymMatrix(perm, mat, keep_matrix);
00199 }
00200
00201
00202 template<class real, class cplx, class Allocator>
00203 template<class T0, class Storage0, class Allocator0>
00204 void IlutPreconditioning<real, cplx, Allocator>::
00205 FactorizeMatrix(const IVect& perm,
00206 Matrix<T0, Symmetric, Storage0, Allocator0>& mat,
00207 bool keep_matrix)
00208 {
00209 if (symmetric_algorithm)
00210 FactorizeSymMatrix(perm, mat, keep_matrix);
00211 else
00212 FactorizeUnsymMatrix(perm, mat, keep_matrix);
00213 }
00214
00215
00216 template<class real, class cplx, class Allocator>
00217 template<class MatrixSparse>
00218 void IlutPreconditioning<real, cplx, Allocator>::
00219 FactorizeSymMatrix(const IVect& perm, MatrixSparse& mat, bool keep_matrix)
00220 {
00221 IVect inv_permutation;
00222
00223
00224 Copy(mat, mat_sym);
00225
00226
00227 if (!keep_matrix)
00228 mat.Clear();
00229
00230
00231 int n = mat_sym.GetM();
00232 if (perm.GetM() != n)
00233 {
00234 cout << "Numbering array should have the same size as matrix.";
00235 cout << endl;
00236 abort();
00237 }
00238
00239 permutation_row.Reallocate(n);
00240 inv_permutation.Reallocate(n);
00241 inv_permutation.Fill(-1);
00242 for (int i = 0; i < n; i++)
00243 {
00244 permutation_row(i) = perm(i);
00245 inv_permutation(perm(i)) = i;
00246 }
00247
00248 for (int i = 0; i < n; i++)
00249 if (inv_permutation(i) == -1)
00250 {
00251 cout << "Error in the numbering array." << endl;
00252 abort();
00253 }
00254
00255
00256 ApplyInversePermutation(mat_sym, perm, perm);
00257
00258
00259 xtmp.Reallocate(n);
00260
00261
00262 GetIlut(*this, mat_sym);
00263 }
00264
00265
00266 template<class real, class cplx, class Allocator>
00267 template<class MatrixSparse>
00268 void IlutPreconditioning<real, cplx, Allocator>::
00269 FactorizeUnsymMatrix(const IVect& perm, MatrixSparse& mat, bool keep_matrix)
00270 {
00271 IVect inv_permutation;
00272
00273
00274 Copy(mat, mat_unsym);
00275
00276
00277 if (!keep_matrix)
00278 mat.Clear();
00279
00280
00281 int n = mat_unsym.GetM();
00282 if (perm.GetM() != n)
00283 {
00284 cout << "Numbering array should have the same size as matrix.";
00285 cout << endl;
00286 abort();
00287 }
00288
00289 permutation_row.Reallocate(n);
00290 permutation_col.Reallocate(n);
00291 inv_permutation.Reallocate(n);
00292 inv_permutation.Fill(-1);
00293 for (int i = 0; i < n; i++)
00294 {
00295 permutation_row(i) = i;
00296 permutation_col(i) = i;
00297 inv_permutation(perm(i)) = i;
00298 }
00299
00300 for (int i = 0; i < n; i++)
00301 if (inv_permutation(i) == -1)
00302 {
00303 cout << "Error in the numbering array." << endl;
00304 abort();
00305 }
00306
00307 IVect iperm = inv_permutation;
00308
00309
00310 ApplyInversePermutation(mat_unsym, perm, perm);
00311
00312
00313 xtmp.Reallocate(n);
00314
00315
00316
00317 inv_permutation.Fill();
00318 GetIlut(*this, mat_unsym, permutation_col, inv_permutation);
00319
00320
00321 IVect itmp = permutation_col;
00322 for (int i = 0; i < n; i++)
00323 permutation_col(i) = iperm(itmp(i));
00324
00325 permutation_row = perm;
00326 }
00327
00328
00329 template<class real, class cplx, class Allocator>
00330 template<class Matrix1, class Vector1>
00331 void IlutPreconditioning<real, cplx, Allocator>::
00332 Solve(const Matrix1& A, const Vector1& r, Vector1& z)
00333 {
00334 if (symmetric_algorithm)
00335 {
00336 for (int i = 0; i < r.GetM(); i++)
00337 xtmp(permutation_row(i)) = r(i);
00338
00339 SolveLU(mat_sym, xtmp);
00340
00341 for (int i = 0; i < r.GetM(); i++)
00342 z(i) = xtmp(permutation_row(i));
00343 }
00344 else
00345 {
00346 for (int i = 0; i < r.GetM(); i++)
00347 xtmp(permutation_row(i)) = r(i);
00348
00349 SolveLU(mat_unsym, xtmp);
00350
00351 for (int i = 0; i < r.GetM(); i++)
00352 z(permutation_col(i)) = xtmp(i);
00353 }
00354 }
00355
00356
00357 template<class real, class cplx, class Allocator>
00358 template<class Matrix1, class Vector1>
00359 void IlutPreconditioning<real, cplx, Allocator>::
00360 TransSolve(const Matrix1& A, const Vector1& r, Vector1& z)
00361 {
00362 if (symmetric_algorithm)
00363 Solve(A, r, z);
00364 else
00365 {
00366 for (int i = 0; i < r.GetM(); i++)
00367 xtmp(i) = r(permutation_col(i));
00368
00369 SolveLU(SeldonTrans, mat_unsym, xtmp);
00370
00371 for (int i = 0; i < r.GetM(); i++)
00372 z(i) = xtmp(permutation_row(i));
00373 }
00374 }
00375
00376
00377 template<class real, class cplx, class Allocator>
00378 template<class Vector1>
00379 void IlutPreconditioning<real, cplx, Allocator>::Solve(Vector1& z)
00380 {
00381 if (symmetric_algorithm)
00382 {
00383 for (int i = 0; i < z.GetM(); i++)
00384 xtmp(permutation_row(i)) = z(i);
00385
00386 SolveLU(mat_sym, xtmp);
00387
00388 for (int i = 0; i < z.GetM(); i++)
00389 z(i) = xtmp(permutation_row(i));
00390 }
00391 else
00392 {
00393 for (int i = 0; i < z.GetM(); i++)
00394 xtmp(permutation_row(i)) = z(i);
00395
00396 SolveLU(mat_unsym, xtmp);
00397
00398 for (int i = 0; i < z.GetM(); i++)
00399 z(permutation_col(i)) = xtmp(i);
00400 }
00401 }
00402
00403
00404 template<class real, class cplx, class Allocator>
00405 template<class Vector1>
00406 void IlutPreconditioning<real, cplx, Allocator>::TransSolve(Vector1& z)
00407 {
00408 if (symmetric_algorithm)
00409 Solve(z);
00410 else
00411 {
00412 for (int i = 0; i < z.GetM(); i++)
00413 xtmp(i) = z(permutation_col(i));
00414
00415 SolveLU(SeldonTrans, mat_unsym, xtmp);
00416
00417 for (int i = 0; i < z.GetM(); i++)
00418 z(i) = xtmp(permutation_row(i));
00419 }
00420 }
00421
00422
00423 template<class real, class cplx, class Storage, class Allocator>
00424 void qsplit_ilut(Vector<cplx, Storage, Allocator>& a, IVect& ind, int first,
00425 int n, int ncut, const real& abs_ncut)
00426 {
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 int last = n-1;
00438 int ncut_ = ncut-1;
00439 int first_ = first;
00440
00441 if ((ncut_ < first_) || (ncut_ > last))
00442 return;
00443
00444 cplx tmp; real abskey;
00445 int mid, itmp;
00446 bool test_loop = true;
00447
00448
00449 while (test_loop)
00450 {
00451 mid = first_;
00452 abskey = abs(a(mid));
00453 for (int j = (first_+1); j <= last; j++)
00454 {
00455 if (abs(a(j)) > abskey)
00456 {
00457 mid++;
00458
00459 tmp = a(mid);
00460 itmp = ind(mid);
00461 a(mid) = a(j);
00462 ind(mid) = ind(j);
00463 a(j) = tmp;
00464 ind(j) = itmp;
00465 }
00466 }
00467
00468
00469 tmp = a(mid);
00470 a(mid) = a(first_);
00471 a(first_) = tmp;
00472
00473 itmp = ind(mid);
00474 ind(mid) = ind(first_);
00475 ind(first_) = itmp;
00476
00477
00478 if (mid == ncut_)
00479 return;
00480
00481 if (mid > ncut_)
00482 last = mid-1;
00483 else
00484 first_ = mid+1;
00485 }
00486 }
00487
00488
00490 template<class real, class cplx, class Allocator1, class Allocator2>
00491 void GetIlut(const IlutPreconditioning<real, cplx, Allocator1>& param,
00492 Matrix<cplx, General, ArrayRowSparse, Allocator2>& A,
00493 IVect& iperm, IVect& rperm)
00494 {
00495 int size_row;
00496 int n = A.GetN();
00497 int type_factorisation = param.GetFactorisationType();
00498 int lfil = param.GetFillLevel();
00499 real zero(0);
00500 real droptol = param.GetDroppingThreshold();
00501 real alpha = param.GetDiagonalCoefficient();
00502 bool variable_fill = false;
00503 bool standard_dropping = true;
00504 int additional_fill = param.GetAdditionalFillNumber();
00505 int mbloc = param.GetPivotBlockInteger();
00506 real permtol = param.GetPivotThreshold();
00507 int print_level = param.GetPrintLevel();
00508
00509 if (type_factorisation == param.ILUT)
00510 standard_dropping = false;
00511 else if (type_factorisation == param.ILU_D)
00512 standard_dropping = true;
00513 else if (type_factorisation == param.ILUT_K)
00514 {
00515 variable_fill = true;
00516 standard_dropping = false;
00517 }
00518 else if (type_factorisation == param.ILU_0)
00519 {
00520 GetIlu0(A);
00521 return;
00522 }
00523 else if (type_factorisation == param.MILU_0)
00524 {
00525 GetMilu0(A);
00526 return;
00527 }
00528 else if (type_factorisation == param.ILU_K)
00529 {
00530 GetIluk(lfil, A);
00531 return;
00532 }
00533
00534 cplx fact, s, t;
00535 real tnorm;
00536 int length_lower, length_upper, jpos, jrow, i_row, j_col;
00537 int i, j, k, index_lu, length;
00538
00539
00540 if (lfil < 0)
00541 {
00542 cout << "Incorrect fill level." << endl;
00543 abort();
00544 }
00545
00546 cplx czero, cone;
00547 SetComplexZero(czero);
00548 SetComplexOne(cone);
00549 typedef Vector<cplx, VectFull, Allocator2> VectCplx;
00550 VectCplx Row_Val(n);
00551 IVect Index(n), Row_Ind(n), Index_Diag(n);
00552 Row_Val.Fill(czero);
00553 Row_Ind.Fill(-1);
00554 Index_Diag.Fill(-1);
00555
00556 Index.Fill(-1);
00557
00558 bool element_dropped; cplx dropsum;
00559
00560
00561 int new_percent = 0, old_percent = 0;
00562 for (i_row = 0; i_row < n; i_row++)
00563 {
00564
00565 if (print_level > 0)
00566 {
00567 new_percent = int(double(i_row)/(n-1)*80);
00568 for (int percent = old_percent; percent < new_percent; percent++)
00569 {
00570 cout << "#"; cout.flush();
00571 }
00572
00573 old_percent = new_percent;
00574 }
00575
00576 size_row = A.GetRowSize(i_row);
00577 tnorm = zero;
00578
00579 dropsum = czero;
00580 for (k = 0 ; k < size_row; k++)
00581 if (A.Value(i_row, k) != czero)
00582 tnorm += abs(A.Value(i_row, k));
00583
00584 if (tnorm == zero)
00585 {
00586 cout << "Structurally singular matrix." << endl;
00587 cout << "Norm of row " << i_row << " is equal to 0." << endl;
00588 abort();
00589 }
00590
00591
00592 tnorm /= real(size_row);
00593 if (variable_fill)
00594 lfil = size_row + additional_fill;
00595
00596
00597 length_upper = 1;
00598 length_lower = 0;
00599 Row_Ind(i_row) = i_row;
00600 Row_Val(i_row) = czero;
00601 Index(i_row) = i_row;
00602
00603 for (j = 0; j < size_row; j++)
00604 {
00605 k = rperm(A.Index(i_row, j));
00606
00607 t = A.Value(i_row,j);
00608 if (k < i_row)
00609 {
00610 Row_Ind(length_lower) = k;
00611 Row_Val(length_lower) = t;
00612 Index(k) = length_lower;
00613 ++length_lower;
00614 }
00615 else if (k == i_row)
00616 {
00617 Row_Val(i_row) = t;
00618 }
00619 else
00620 {
00621 jpos = i_row + length_upper;
00622 Row_Ind(jpos) = k;
00623 Row_Val(jpos) = t;
00624 Index(k) = jpos;
00625 length_upper++;
00626 }
00627 }
00628
00629 j_col = 0;
00630 length = 0;
00631
00632
00633 while (j_col < length_lower)
00634 {
00635
00636
00637 jrow = Row_Ind(j_col);
00638 k = j_col;
00639
00640
00641 for (j = j_col + 1; j < length_lower; j++)
00642 {
00643 if (Row_Ind(j) < jrow)
00644 {
00645 jrow = Row_Ind(j);
00646 k = j;
00647 }
00648 }
00649
00650 if (k != j_col)
00651 {
00652
00653 j = Row_Ind(j_col);
00654 Row_Ind(j_col) = Row_Ind(k);
00655 Row_Ind(k) = j;
00656
00657 Index(jrow) = j_col;
00658 Index(j) = k;
00659
00660 s = Row_Val(j_col);
00661 Row_Val(j_col) = Row_Val(k);
00662 Row_Val(k) = s;
00663 }
00664
00665
00666 Index(jrow) = -1;
00667
00668 element_dropped = false;
00669 if (standard_dropping)
00670 if (abs(Row_Val(j_col)) <= droptol*tnorm)
00671 {
00672 dropsum += Row_Val(j_col);
00673 element_dropped = true;
00674 }
00675
00676
00677 if (!element_dropped)
00678 {
00679
00680 fact = Row_Val(j_col) * A.Value(jrow, Index_Diag(jrow));
00681
00682 if (!standard_dropping)
00683 {
00684 if (abs(fact) <= droptol)
00685 element_dropped = true;
00686 }
00687 }
00688
00689 if (!element_dropped)
00690 {
00691
00692 for (k = (Index_Diag(jrow)+1); k < A.GetRowSize(jrow); k++)
00693 {
00694 s = fact * A.Value(jrow,k);
00695 j = rperm(A.Index(jrow,k));
00696
00697 jpos = Index(j);
00698
00699 if (j >= i_row)
00700 {
00701
00702
00703 if (jpos == -1)
00704 {
00705
00706 i = i_row + length_upper;
00707 Row_Ind(i) = j;
00708 Index(j) = i;
00709 Row_Val(i) = -s;
00710 ++length_upper;
00711 }
00712 else
00713 {
00714
00715 Row_Val(jpos) -= s;
00716 }
00717 }
00718 else
00719 {
00720
00721 if (jpos == -1)
00722 {
00723
00724 Row_Ind(length_lower) = j;
00725 Index(j) = length_lower;
00726 Row_Val(length_lower) = -s;
00727 ++length_lower;
00728 }
00729 else
00730 {
00731
00732 Row_Val(jpos) -= s;
00733 }
00734 }
00735 }
00736
00737
00738
00739 Row_Val(length) = fact;
00740 Row_Ind(length) = jrow;
00741 ++length;
00742 }
00743
00744 j_col++;
00745 }
00746
00747
00748 for (k = 0; k < length_upper; k++)
00749 Index(Row_Ind(i_row+k )) = -1;
00750
00751
00752 if (!standard_dropping)
00753 {
00754 length_lower = length;
00755 length = min(length_lower,lfil);
00756
00757
00758 qsplit_ilut(Row_Val, Row_Ind, 0, length_lower, length,tnorm);
00759 }
00760
00761 size_row = length;
00762 A.ReallocateRow(i_row,size_row);
00763
00764
00765 index_lu = 0;
00766 for (k = 0 ; k < length ; k++)
00767 {
00768 A.Value(i_row,index_lu) = Row_Val(k);
00769 A.Index(i_row,index_lu) = iperm(Row_Ind(k));
00770 ++index_lu;
00771 }
00772
00773
00774 Index_Diag(i_row) = index_lu;
00775
00776
00777 length = 0;
00778 for (k = 1; k <= (length_upper-1); k++)
00779 {
00780 if (abs(Row_Val(i_row+k)) > droptol * tnorm)
00781 {
00782 ++length;
00783 Row_Val(i_row+length) = Row_Val(i_row+k);
00784 Row_Ind(i_row+length) = Row_Ind(i_row+k);
00785 }
00786 else
00787 dropsum += Row_Val(i_row+k);
00788 }
00789
00790 if (!standard_dropping)
00791 {
00792 length_upper = length + 1;
00793 length = min(length_upper,lfil);
00794
00795 qsplit_ilut(Row_Val, Row_Ind, i_row+1,
00796 i_row+length_upper, i_row+length+1, tnorm);
00797 }
00798 else
00799 length++;
00800
00801
00802 int imax = i_row;
00803 real xmax = abs(Row_Val(imax));
00804 real xmax0 = xmax;
00805 int icut = i_row + mbloc - 1 - i_row%mbloc;
00806 for ( k = i_row + 1; k <= i_row + length - 1; k++)
00807 {
00808 tnorm = abs(Row_Val(k));
00809 if ((tnorm > xmax) && (tnorm*permtol > xmax0)
00810 && (Row_Ind(k)<= icut))
00811 {
00812 imax = k;
00813 xmax = tnorm;
00814 }
00815 }
00816
00817
00818 s = Row_Val(i_row);
00819 Row_Val(i_row) = Row_Val(imax);
00820 Row_Val(imax) = s;
00821
00822
00823 j = Row_Ind(imax);
00824 i = iperm(i_row);
00825 iperm(i_row) = iperm(j);
00826 iperm(j) = i;
00827
00828
00829 rperm(iperm(i_row)) = i_row;
00830 rperm(iperm(j)) = j;
00831
00832
00833 int index_diag = index_lu;
00834 A.ResizeRow(i_row, size_row+length);
00835
00836 for (k = i_row ; k <= i_row + length - 1; k++)
00837 {
00838 A.Index(i_row,index_lu) = iperm(Row_Ind(k));
00839 A.Value(i_row,index_lu) = Row_Val(k);
00840 ++index_lu;
00841 }
00842
00843
00844 if (standard_dropping)
00845 Row_Val(i_row) += alpha*dropsum;
00846
00847 if (Row_Val(i_row) == czero)
00848 Row_Val(i_row) = (droptol + 1e-4) * tnorm;
00849
00850 A.Value(i_row, index_diag) = cone / Row_Val(i_row);
00851
00852 }
00853
00854 if (print_level > 0)
00855 cout << endl;
00856
00857 if (print_level > 0)
00858 cout << "The matrix takes " <<
00859 int((A.GetDataSize()*(sizeof(cplx)+4))/(1024*1024)) << " MB" << endl;
00860
00861 for (i = 0; i < n; i++ )
00862 for (j = 0; j < A.GetRowSize(i); j++)
00863 A.Index(i,j) = rperm(A.Index(i,j));
00864 }
00865
00866
00867 template<class cplx, class Allocator>
00868 void GetIluk(int lfil, Matrix<cplx, General, ArrayRowSparse, Allocator>& A)
00869 {
00870 int n = A.GetM();
00871 Vector<cplx, VectFull, CallocAlloc<cplx> > w;
00872 w.Reallocate(n+1);
00873 IVect jw(3*n), Index_Diag(n);
00874 Vector<IVect, VectFull, NewAlloc<IVect> > levs(n);
00875
00876 cplx czero, cone;
00877 SetComplexZero(czero);
00878 SetComplexOne(cone);
00879
00880
00881 cplx fact, s, t;
00882 int length_lower,length_upper, jpos, jrow, i_row, j_col;
00883 int i, j, k, index_lu, length;
00884 bool element_dropped;
00885
00886 int n2 = 2*n, jlev, k_, size_upper;
00887 jw.Fill(-1);
00888
00889
00890 for (i_row = 0; i_row < n; i_row++)
00891 {
00892 int size_row = A.GetRowSize(i_row);
00893
00894
00895 length_upper = 1;
00896 length_lower = 0;
00897 jw(i_row) = i_row;
00898 w(i_row) = 0.0;
00899 jw(n + i_row) = i_row;
00900
00901 for (j = 0; j < size_row; j++)
00902 {
00903 k = A.Index(i_row,j);
00904 t = A.Value(i_row,j);
00905 if (k < i_row)
00906 {
00907 jw(length_lower) = k;
00908 w(length_lower) = t;
00909 jw(n + k) = length_lower;
00910 jw(n2+length_lower) = -1;
00911 ++length_lower;
00912 }
00913 else if (k == i_row)
00914 {
00915 w(i_row) = t;
00916 jw(n2+length_lower) = -1;
00917 }
00918 else
00919 {
00920 jpos = i_row + length_upper;
00921 jw(jpos) = k;
00922 w(jpos) = t;
00923 jw(n + k) = jpos;
00924 length_upper++;
00925 }
00926 }
00927
00928 j_col = 0;
00929 length = 0;
00930
00931
00932
00933 while (j_col <length_lower)
00934 {
00935
00936
00937
00938 jrow = jw(j_col);
00939 k = j_col;
00940
00941
00942 for (j = (j_col+1) ; j < length_lower; j++)
00943 {
00944 if (jw(j) < jrow)
00945 {
00946 jrow = jw(j);
00947 k = j;
00948 }
00949 }
00950
00951 if (k != j_col)
00952 {
00953
00954 j = jw(j_col);
00955 jw(j_col) = jw(k);
00956 jw(k) = j;
00957
00958
00959 jw(n+jrow) = j_col;
00960 jw(n+j) = k;
00961
00962
00963 j = jw(n2+j_col);
00964 jw(n2+j_col) = jw(n2+k);
00965 jw(n2+k) = j;
00966
00967
00968 s = w(j_col);
00969 w(j_col) = w(k);
00970 w(k) = s;
00971 }
00972
00973
00974 jw(n + jrow) = -1;
00975
00976 element_dropped = false;
00977
00978
00979 fact = w(j_col) * A.Value(jrow,Index_Diag(jrow));
00980
00981 jlev = jw(n2+j_col) + 1;
00982 if (jlev > lfil)
00983 element_dropped = true;
00984
00985 if (!element_dropped)
00986 {
00987
00988 k_ = 0;
00989 for (k = (Index_Diag(jrow)+1); k < A.GetRowSize(jrow) ; k++)
00990 {
00991 s = fact * A.Value(jrow,k);
00992 j = A.Index(jrow,k);
00993
00994 jpos = jw(n + j);
00995 if (j >= i_row)
00996 {
00997
00998 if (jpos == -1)
00999 {
01000
01001 i = i_row + length_upper;
01002 jw(i) = j;
01003 jw(n + j) = i;
01004 w(i) = -s;
01005
01006 jw(n2+i) = jlev + levs(jrow)(k_) + 1;
01007 ++length_upper;
01008 }
01009 else
01010 {
01011
01012 w(jpos) -= s;
01013 jw(n2+jpos) = min(jw(n2+jpos),
01014 jlev + levs(jrow)(k_)+1);
01015 }
01016 }
01017 else
01018 {
01019
01020 if (jpos == -1)
01021 {
01022
01023 jw(length_lower) = j;
01024 jw(n + j) = length_lower;
01025 w(length_lower) = -s;
01026 jw(n2+length_lower) = jlev + levs(jrow)(k_) + 1;
01027 ++length_lower;
01028 }
01029 else
01030 {
01031
01032 w(jpos) -= s;
01033 jw(n2+jpos) = min(jw(n2 + jpos),
01034 jlev + levs(jrow)(k_) + 1);
01035 }
01036 }
01037
01038 k_++;
01039 }
01040
01041 }
01042
01043
01044
01045 w(j_col) = fact;
01046 jw(j_col) = jrow;
01047
01048 j_col++;
01049 }
01050
01051
01052 for (k = 0; k < length_upper; k++)
01053 jw(n + jw(i_row + k )) = -1;
01054
01055
01056 size_row = 1;
01057
01058 for (k = 0; k < length_lower; k++)
01059 if (jw(n2+k) < lfil)
01060 size_row++;
01061
01062
01063 size_upper = 0;
01064 for (k = (i_row+1) ; k <= (i_row+length_upper-1) ; k++)
01065 if (jw(n2+k) < lfil)
01066 size_upper++;
01067
01068 size_row += size_upper;
01069 A.ReallocateRow(i_row,size_row);
01070 levs(i_row).Reallocate(size_upper);
01071
01072 index_lu = 0;
01073 for (k = 0; k < length_lower; k++)
01074 {
01075 if (jw(n2+k) < lfil)
01076 {
01077 A.Value(i_row,index_lu) = w(k);
01078 A.Index(i_row,index_lu) = jw(k);
01079 ++index_lu;
01080 }
01081 }
01082
01083
01084 Index_Diag(i_row) = index_lu;
01085 A.Value(i_row,index_lu) = cone / w(i_row);
01086 A.Index(i_row,index_lu++) = i_row;
01087
01088 for (k = (i_row+1) ; k <= (i_row+length_upper-1) ; k++)
01089 {
01090 if (jw(n2+k) < lfil)
01091 {
01092 A.Index(i_row,index_lu) = jw(k);
01093 A.Value(i_row,index_lu) = w(k);
01094 levs(i_row)(index_lu-Index_Diag(i_row)-1) = jw(n2+k);
01095 ++index_lu;
01096 }
01097 }
01098 }
01099 }
01100
01101
01102 template<class cplx, class Allocator>
01103 void GetIlu0(Matrix<cplx, General, ArrayRowSparse, Allocator>& A)
01104 {
01105 int j_col, jrow, jw, n = A.GetM();
01106 IVect Index(n), ju(n);
01107
01108 cplx czero, cone;
01109 SetComplexZero(czero);
01110 SetComplexOne(cone);
01111
01112
01113 Index.Fill(-1); ju.Fill(-1);
01114 cplx tl;
01115
01116
01117 for (int i_row = 0 ; i_row < n ; i_row++)
01118 {
01119
01120 for (int j = 0 ; j < A.GetRowSize(i_row) ; j++ )
01121 {
01122 j_col = A.Index(i_row, j);
01123 if (j_col == i_row)
01124 ju(i_row) = j;
01125
01126 Index(j_col) = j;
01127 }
01128
01129 int jm = ju(i_row)-1;
01130
01131
01132 for (int j = 0; j <= jm; j++)
01133 {
01134 jrow = A.Index(i_row, j);
01135 tl = A.Value(i_row, j)*A.Value(jrow, ju(jrow));
01136 A.Value(i_row, j) = tl;
01137
01138
01139 for ( j_col = (ju(jrow)+1); j_col < A.GetRowSize(jrow); j_col++)
01140 {
01141 jw = Index(A.Index(jrow,j_col));
01142 if (jw != -1)
01143 A.Value(i_row, jw) -= tl*A.Value(jrow, j_col);
01144 }
01145 }
01146
01147
01148
01149 if (A.Value(i_row, ju(i_row)) == czero)
01150 {
01151 cout << "Factorization fails because we found a null coefficient"
01152 << " on diagonal " << i_row << endl;
01153 abort();
01154 }
01155
01156 A.Value(i_row,ju(i_row)) = cone / A.Value(i_row,ju(i_row));
01157
01158
01159 Index(i_row) = -1;
01160 for (int i = 0; i < A.GetRowSize(i_row); i++)
01161 Index(A.Index(i_row, i)) = -1;
01162 }
01163
01164 }
01165
01166
01167 template<class cplx, class Allocator>
01168 void GetMilu0(Matrix<cplx, General, ArrayRowSparse, Allocator>& A)
01169 {
01170 int j_col, jrow, jw, n = A.GetM();
01171 IVect Index(n), ju(n);
01172
01173 cplx czero, cone;
01174 SetComplexZero(czero);
01175 SetComplexOne(cone);
01176
01177
01178 Index.Fill(-1); ju.Fill(-1);
01179 cplx tl;
01180
01181
01182 for (int i_row = 0 ; i_row < n ; i_row++)
01183 {
01184
01185 for (int j = 0; j < A.GetRowSize(i_row); j++ )
01186 {
01187 j_col = A.Index(i_row, j);
01188 if (j_col == i_row)
01189 ju(i_row) = j;
01190
01191 Index(j_col) = j;
01192 }
01193
01194 int jm = ju(i_row)-1;
01195
01196
01197 cplx s(0);
01198 for (int j = 0; j <= jm; j++)
01199 {
01200 jrow = A.Index(i_row, j);
01201 tl = A.Value(i_row, j)*A.Value(jrow, ju(jrow));
01202 A.Value(i_row, j) = tl;
01203
01204
01205 for ( j_col = (ju(jrow)+1); j_col < A.GetRowSize(jrow); j_col++ )
01206 {
01207 jw = Index(A.Index(jrow, j_col));
01208 if (jw != -1)
01209 A.Value(i_row, jw) -= tl*A.Value(jrow, j_col);
01210 else
01211 s += tl*A.Value(jrow, j_col);
01212 }
01213 }
01214
01215
01216 A.Value(i_row, ju(i_row)) -= s;
01217 if (A.Value(i_row, ju(i_row)) == czero)
01218 {
01219 cout << "Factorization fails because we found a null coefficient"
01220 << " on diagonal " << i_row << endl;
01221 abort();
01222 }
01223
01224 A.Value(i_row, ju(i_row)) = cone /A.Value(i_row, ju(i_row));
01225
01226
01227 Index(i_row) = -1;
01228 for (int i = 0; i < A.GetRowSize(i_row); i++)
01229 Index(A.Index(i_row, i)) = -1;
01230 }
01231 }
01232
01233
01235
01238 template<class real, class cplx, class Allocator,
01239 class Storage2, class Allocator2>
01240 void SolveLU(const Matrix<real, General, ArrayRowSparse, Allocator>& A,
01241 Vector<cplx, Storage2, Allocator2>& x)
01242 {
01243 int i, k, n, k_;
01244 real inv_diag;
01245 n = A.GetM();
01246
01247
01248 for (i = 0; i < n; i++)
01249 {
01250 k_ = 0; k = A.Index(i,k_);
01251 while ( k < i)
01252 {
01253 x(i) -= A.Value(i,k_)*x(k);
01254 k_++;
01255 k = A.Index(i,k_);
01256 }
01257 }
01258
01259
01260 for (i = n-1; i >= 0; i--)
01261 {
01262 k_ = 0; k = A.Index(i,k_);
01263 while ( k < i)
01264 {
01265 k_++;
01266 k = A.Index(i,k_);
01267 }
01268
01269 inv_diag = A.Value(i,k_);
01270 for ( k = (k_+1); k < A.GetRowSize(i) ; k++)
01271 x(i) -= A.Value(i,k) * x(A.Index(i,k));
01272
01273 x(i) *= inv_diag;
01274 }
01275 }
01276
01277
01278 template<class cplx, class Allocator, class Storage2, class Allocator2>
01279 void SolveLU(const class_SeldonTrans& transA,
01280 const Matrix<cplx, General, ArrayRowSparse, Allocator>& A,
01281 Vector<cplx,Storage2,Allocator2>& x)
01282 {
01283 int i, k, n, k_;
01284 n = A.GetM();
01285
01286
01287 for (i = 0 ; i < n ; i++)
01288 {
01289 k_ = 0; k = A.Index(i,k_);
01290 while ( k < i)
01291 {
01292 k_++;
01293 k = A.Index(i,k_);
01294 }
01295
01296 x(i) *= A.Value(i,k_);
01297 for ( k = (k_+1); k < A.GetRowSize(i) ; k++)
01298 {
01299 x(A.Index(i,k)) -= A.Value(i,k) * x(i);
01300 }
01301 }
01302
01303
01304 for (i = n-1 ; i>=0 ; i--)
01305 {
01306 k_ = 0; k = A.Index(i,k_);
01307 while ( k < i)
01308 {
01309 x(k) -= A.Value(i,k_)*x(i);
01310 k_++;
01311 k = A.Index(i,k_);
01312 }
01313 }
01314 }
01315
01316 }
01317
01318 #define SELDON_FILE_ILUT_PRECONDITIONING_CXX
01319 #endif