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 Allocator>
00424 template<class TransStatus, class Vector1>
00425 void IlutPreconditioning<real, cplx, Allocator>
00426 ::Solve(const TransStatus& transA, Vector1& z)
00427 {
00428 if (transA.Trans())
00429 TransSolve(z);
00430 else
00431 Solve(z);
00432 }
00433
00434
00435 template<class real, class cplx, class Storage, class Allocator>
00436 void qsplit_ilut(Vector<cplx, Storage, Allocator>& a, IVect& ind, int first,
00437 int n, int ncut, const real& abs_ncut)
00438 {
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 int last = n-1;
00450 int ncut_ = ncut-1;
00451 int first_ = first;
00452
00453 if ((ncut_ < first_) || (ncut_ > last))
00454 return;
00455
00456 cplx tmp; real abskey;
00457 int mid, itmp;
00458 bool test_loop = true;
00459
00460
00461 while (test_loop)
00462 {
00463 mid = first_;
00464 abskey = abs(a(mid));
00465 for (int j = (first_+1); j <= last; j++)
00466 {
00467 if (abs(a(j)) > abskey)
00468 {
00469 mid++;
00470
00471 tmp = a(mid);
00472 itmp = ind(mid);
00473 a(mid) = a(j);
00474 ind(mid) = ind(j);
00475 a(j) = tmp;
00476 ind(j) = itmp;
00477 }
00478 }
00479
00480
00481 tmp = a(mid);
00482 a(mid) = a(first_);
00483 a(first_) = tmp;
00484
00485 itmp = ind(mid);
00486 ind(mid) = ind(first_);
00487 ind(first_) = itmp;
00488
00489
00490 if (mid == ncut_)
00491 return;
00492
00493 if (mid > ncut_)
00494 last = mid-1;
00495 else
00496 first_ = mid+1;
00497 }
00498 }
00499
00500
00502 template<class real, class cplx, class Allocator1, class Allocator2>
00503 void GetIlut(const IlutPreconditioning<real, cplx, Allocator1>& param,
00504 Matrix<cplx, General, ArrayRowSparse, Allocator2>& A,
00505 IVect& iperm, IVect& rperm)
00506 {
00507 int size_row;
00508 int n = A.GetN();
00509 int type_factorization = param.GetFactorizationType();
00510 int lfil = param.GetFillLevel();
00511 real zero(0);
00512 real droptol = param.GetDroppingThreshold();
00513 real alpha = param.GetDiagonalCoefficient();
00514 bool variable_fill = false;
00515 bool standard_dropping = true;
00516 int additional_fill = param.GetAdditionalFillNumber();
00517 int mbloc = param.GetPivotBlockInteger();
00518 real permtol = param.GetPivotThreshold();
00519 int print_level = param.GetPrintLevel();
00520
00521 if (type_factorization == param.ILUT)
00522 standard_dropping = false;
00523 else if (type_factorization == param.ILU_D)
00524 standard_dropping = true;
00525 else if (type_factorization == param.ILUT_K)
00526 {
00527 variable_fill = true;
00528 standard_dropping = false;
00529 }
00530 else if (type_factorization == param.ILU_0)
00531 {
00532 GetIlu0(A);
00533 return;
00534 }
00535 else if (type_factorization == param.MILU_0)
00536 {
00537 GetMilu0(A);
00538 return;
00539 }
00540 else if (type_factorization == param.ILU_K)
00541 {
00542 GetIluk(lfil, A);
00543 return;
00544 }
00545
00546 cplx fact, s, t;
00547 real tnorm;
00548 int length_lower, length_upper, jpos, jrow, i_row, j_col;
00549 int i, j, k, index_lu, length;
00550
00551
00552 if (lfil < 0)
00553 {
00554 cout << "Incorrect fill level." << endl;
00555 abort();
00556 }
00557
00558 cplx czero, cone;
00559 SetComplexZero(czero);
00560 SetComplexOne(cone);
00561 typedef Vector<cplx, VectFull, Allocator2> VectCplx;
00562 VectCplx Row_Val(n);
00563 IVect Index(n), Row_Ind(n), Index_Diag(n);
00564 Row_Val.Fill(czero);
00565 Row_Ind.Fill(-1);
00566 Index_Diag.Fill(-1);
00567
00568 Index.Fill(-1);
00569
00570 bool element_dropped; cplx dropsum;
00571
00572
00573 int new_percent = 0, old_percent = 0;
00574 for (i_row = 0; i_row < n; i_row++)
00575 {
00576
00577 if (print_level > 0)
00578 {
00579 new_percent = int(double(i_row)/(n-1)*80);
00580 for (int percent = old_percent; percent < new_percent; percent++)
00581 {
00582 cout << "#"; cout.flush();
00583 }
00584
00585 old_percent = new_percent;
00586 }
00587
00588 size_row = A.GetRowSize(i_row);
00589 tnorm = zero;
00590
00591 dropsum = czero;
00592 for (k = 0 ; k < size_row; k++)
00593 if (A.Value(i_row, k) != czero)
00594 tnorm += abs(A.Value(i_row, k));
00595
00596 if (tnorm == zero)
00597 {
00598 cout << "Structurally singular matrix." << endl;
00599 cout << "Norm of row " << i_row << " is equal to 0." << endl;
00600 abort();
00601 }
00602
00603
00604 tnorm /= real(size_row);
00605 if (variable_fill)
00606 lfil = size_row + additional_fill;
00607
00608
00609 length_upper = 1;
00610 length_lower = 0;
00611 Row_Ind(i_row) = i_row;
00612 Row_Val(i_row) = czero;
00613 Index(i_row) = i_row;
00614
00615 for (j = 0; j < size_row; j++)
00616 {
00617 k = rperm(A.Index(i_row, j));
00618
00619 t = A.Value(i_row,j);
00620 if (k < i_row)
00621 {
00622 Row_Ind(length_lower) = k;
00623 Row_Val(length_lower) = t;
00624 Index(k) = length_lower;
00625 ++length_lower;
00626 }
00627 else if (k == i_row)
00628 {
00629 Row_Val(i_row) = t;
00630 }
00631 else
00632 {
00633 jpos = i_row + length_upper;
00634 Row_Ind(jpos) = k;
00635 Row_Val(jpos) = t;
00636 Index(k) = jpos;
00637 length_upper++;
00638 }
00639 }
00640
00641 j_col = 0;
00642 length = 0;
00643
00644
00645 while (j_col < length_lower)
00646 {
00647
00648
00649 jrow = Row_Ind(j_col);
00650 k = j_col;
00651
00652
00653 for (j = j_col + 1; j < length_lower; j++)
00654 {
00655 if (Row_Ind(j) < jrow)
00656 {
00657 jrow = Row_Ind(j);
00658 k = j;
00659 }
00660 }
00661
00662 if (k != j_col)
00663 {
00664
00665 j = Row_Ind(j_col);
00666 Row_Ind(j_col) = Row_Ind(k);
00667 Row_Ind(k) = j;
00668
00669 Index(jrow) = j_col;
00670 Index(j) = k;
00671
00672 s = Row_Val(j_col);
00673 Row_Val(j_col) = Row_Val(k);
00674 Row_Val(k) = s;
00675 }
00676
00677
00678 Index(jrow) = -1;
00679
00680 element_dropped = false;
00681 if (standard_dropping)
00682 if (abs(Row_Val(j_col)) <= droptol*tnorm)
00683 {
00684 dropsum += Row_Val(j_col);
00685 element_dropped = true;
00686 }
00687
00688
00689 if (!element_dropped)
00690 {
00691
00692 fact = Row_Val(j_col) * A.Value(jrow, Index_Diag(jrow));
00693
00694 if (!standard_dropping)
00695 {
00696 if (abs(fact) <= droptol)
00697 element_dropped = true;
00698 }
00699 }
00700
00701 if (!element_dropped)
00702 {
00703
00704 for (k = (Index_Diag(jrow)+1); k < A.GetRowSize(jrow); k++)
00705 {
00706 s = fact * A.Value(jrow,k);
00707 j = rperm(A.Index(jrow,k));
00708
00709 jpos = Index(j);
00710
00711 if (j >= i_row)
00712 {
00713
00714
00715 if (jpos == -1)
00716 {
00717
00718 i = i_row + length_upper;
00719 Row_Ind(i) = j;
00720 Index(j) = i;
00721 Row_Val(i) = -s;
00722 ++length_upper;
00723 }
00724 else
00725 {
00726
00727 Row_Val(jpos) -= s;
00728 }
00729 }
00730 else
00731 {
00732
00733 if (jpos == -1)
00734 {
00735
00736 Row_Ind(length_lower) = j;
00737 Index(j) = length_lower;
00738 Row_Val(length_lower) = -s;
00739 ++length_lower;
00740 }
00741 else
00742 {
00743
00744 Row_Val(jpos) -= s;
00745 }
00746 }
00747 }
00748
00749
00750
00751 Row_Val(length) = fact;
00752 Row_Ind(length) = jrow;
00753 ++length;
00754 }
00755
00756 j_col++;
00757 }
00758
00759
00760 for (k = 0; k < length_upper; k++)
00761 Index(Row_Ind(i_row+k )) = -1;
00762
00763
00764 if (!standard_dropping)
00765 {
00766 length_lower = length;
00767 length = min(length_lower,lfil);
00768
00769
00770 qsplit_ilut(Row_Val, Row_Ind, 0, length_lower, length,tnorm);
00771 }
00772
00773 size_row = length;
00774 A.ReallocateRow(i_row,size_row);
00775
00776
00777 index_lu = 0;
00778 for (k = 0 ; k < length ; k++)
00779 {
00780 A.Value(i_row,index_lu) = Row_Val(k);
00781 A.Index(i_row,index_lu) = iperm(Row_Ind(k));
00782 ++index_lu;
00783 }
00784
00785
00786 Index_Diag(i_row) = index_lu;
00787
00788
00789 length = 0;
00790 for (k = 1; k <= (length_upper-1); k++)
00791 {
00792 if (abs(Row_Val(i_row+k)) > droptol * tnorm)
00793 {
00794 ++length;
00795 Row_Val(i_row+length) = Row_Val(i_row+k);
00796 Row_Ind(i_row+length) = Row_Ind(i_row+k);
00797 }
00798 else
00799 dropsum += Row_Val(i_row+k);
00800 }
00801
00802 if (!standard_dropping)
00803 {
00804 length_upper = length + 1;
00805 length = min(length_upper,lfil);
00806
00807 qsplit_ilut(Row_Val, Row_Ind, i_row+1,
00808 i_row+length_upper, i_row+length+1, tnorm);
00809 }
00810 else
00811 length++;
00812
00813
00814 int imax = i_row;
00815 real xmax = abs(Row_Val(imax));
00816 real xmax0 = xmax;
00817 int icut = i_row + mbloc - 1 - i_row%mbloc;
00818 for ( k = i_row + 1; k <= i_row + length - 1; k++)
00819 {
00820 tnorm = abs(Row_Val(k));
00821 if ((tnorm > xmax) && (tnorm*permtol > xmax0)
00822 && (Row_Ind(k)<= icut))
00823 {
00824 imax = k;
00825 xmax = tnorm;
00826 }
00827 }
00828
00829
00830 s = Row_Val(i_row);
00831 Row_Val(i_row) = Row_Val(imax);
00832 Row_Val(imax) = s;
00833
00834
00835 j = Row_Ind(imax);
00836 i = iperm(i_row);
00837 iperm(i_row) = iperm(j);
00838 iperm(j) = i;
00839
00840
00841 rperm(iperm(i_row)) = i_row;
00842 rperm(iperm(j)) = j;
00843
00844
00845 int index_diag = index_lu;
00846 A.ResizeRow(i_row, size_row+length);
00847
00848 for (k = i_row ; k <= i_row + length - 1; k++)
00849 {
00850 A.Index(i_row,index_lu) = iperm(Row_Ind(k));
00851 A.Value(i_row,index_lu) = Row_Val(k);
00852 ++index_lu;
00853 }
00854
00855
00856 if (standard_dropping)
00857 Row_Val(i_row) += alpha*dropsum;
00858
00859 if (Row_Val(i_row) == czero)
00860 Row_Val(i_row) = (droptol + 1e-4) * tnorm;
00861
00862 A.Value(i_row, index_diag) = cone / Row_Val(i_row);
00863
00864 }
00865
00866 if (print_level > 0)
00867 cout << endl;
00868
00869 if (print_level > 0)
00870 cout << "The matrix takes " <<
00871 int((A.GetDataSize()*(sizeof(cplx)+4))/(1024*1024)) << " MB" << endl;
00872
00873 for (i = 0; i < n; i++ )
00874 for (j = 0; j < A.GetRowSize(i); j++)
00875 A.Index(i,j) = rperm(A.Index(i,j));
00876 }
00877
00878
00879 template<class cplx, class Allocator>
00880 void GetIluk(int lfil, Matrix<cplx, General, ArrayRowSparse, Allocator>& A)
00881 {
00882 int n = A.GetM();
00883 Vector<cplx, VectFull, CallocAlloc<cplx> > w;
00884 w.Reallocate(n+1);
00885 IVect jw(3*n), Index_Diag(n);
00886 Vector<IVect, VectFull, NewAlloc<IVect> > levs(n);
00887
00888 cplx czero, cone;
00889 SetComplexZero(czero);
00890 SetComplexOne(cone);
00891
00892
00893 cplx fact, s, t;
00894 int length_lower,length_upper, jpos, jrow, i_row, j_col;
00895 int i, j, k, index_lu, length;
00896 bool element_dropped;
00897
00898 int n2 = 2*n, jlev, k_, size_upper;
00899 jw.Fill(-1);
00900
00901
00902 for (i_row = 0; i_row < n; i_row++)
00903 {
00904 int size_row = A.GetRowSize(i_row);
00905
00906
00907 length_upper = 1;
00908 length_lower = 0;
00909 jw(i_row) = i_row;
00910 w(i_row) = 0.0;
00911 jw(n + i_row) = i_row;
00912
00913 for (j = 0; j < size_row; j++)
00914 {
00915 k = A.Index(i_row,j);
00916 t = A.Value(i_row,j);
00917 if (k < i_row)
00918 {
00919 jw(length_lower) = k;
00920 w(length_lower) = t;
00921 jw(n + k) = length_lower;
00922 jw(n2+length_lower) = -1;
00923 ++length_lower;
00924 }
00925 else if (k == i_row)
00926 {
00927 w(i_row) = t;
00928 jw(n2+length_lower) = -1;
00929 }
00930 else
00931 {
00932 jpos = i_row + length_upper;
00933 jw(jpos) = k;
00934 w(jpos) = t;
00935 jw(n + k) = jpos;
00936 length_upper++;
00937 }
00938 }
00939
00940 j_col = 0;
00941 length = 0;
00942
00943
00944
00945 while (j_col <length_lower)
00946 {
00947
00948
00949
00950 jrow = jw(j_col);
00951 k = j_col;
00952
00953
00954 for (j = (j_col+1) ; j < length_lower; j++)
00955 {
00956 if (jw(j) < jrow)
00957 {
00958 jrow = jw(j);
00959 k = j;
00960 }
00961 }
00962
00963 if (k != j_col)
00964 {
00965
00966 j = jw(j_col);
00967 jw(j_col) = jw(k);
00968 jw(k) = j;
00969
00970
00971 jw(n+jrow) = j_col;
00972 jw(n+j) = k;
00973
00974
00975 j = jw(n2+j_col);
00976 jw(n2+j_col) = jw(n2+k);
00977 jw(n2+k) = j;
00978
00979
00980 s = w(j_col);
00981 w(j_col) = w(k);
00982 w(k) = s;
00983 }
00984
00985
00986 jw(n + jrow) = -1;
00987
00988 element_dropped = false;
00989
00990
00991 fact = w(j_col) * A.Value(jrow,Index_Diag(jrow));
00992
00993 jlev = jw(n2+j_col) + 1;
00994 if (jlev > lfil)
00995 element_dropped = true;
00996
00997 if (!element_dropped)
00998 {
00999
01000 k_ = 0;
01001 for (k = (Index_Diag(jrow)+1); k < A.GetRowSize(jrow) ; k++)
01002 {
01003 s = fact * A.Value(jrow,k);
01004 j = A.Index(jrow,k);
01005
01006 jpos = jw(n + j);
01007 if (j >= i_row)
01008 {
01009
01010 if (jpos == -1)
01011 {
01012
01013 i = i_row + length_upper;
01014 jw(i) = j;
01015 jw(n + j) = i;
01016 w(i) = -s;
01017
01018 jw(n2+i) = jlev + levs(jrow)(k_) + 1;
01019 ++length_upper;
01020 }
01021 else
01022 {
01023
01024 w(jpos) -= s;
01025 jw(n2+jpos) = min(jw(n2+jpos),
01026 jlev + levs(jrow)(k_)+1);
01027 }
01028 }
01029 else
01030 {
01031
01032 if (jpos == -1)
01033 {
01034
01035 jw(length_lower) = j;
01036 jw(n + j) = length_lower;
01037 w(length_lower) = -s;
01038 jw(n2+length_lower) = jlev + levs(jrow)(k_) + 1;
01039 ++length_lower;
01040 }
01041 else
01042 {
01043
01044 w(jpos) -= s;
01045 jw(n2+jpos) = min(jw(n2 + jpos),
01046 jlev + levs(jrow)(k_) + 1);
01047 }
01048 }
01049
01050 k_++;
01051 }
01052
01053 }
01054
01055
01056
01057 w(j_col) = fact;
01058 jw(j_col) = jrow;
01059
01060 j_col++;
01061 }
01062
01063
01064 for (k = 0; k < length_upper; k++)
01065 jw(n + jw(i_row + k )) = -1;
01066
01067
01068 size_row = 1;
01069
01070 for (k = 0; k < length_lower; k++)
01071 if (jw(n2+k) < lfil)
01072 size_row++;
01073
01074
01075 size_upper = 0;
01076 for (k = (i_row+1) ; k <= (i_row+length_upper-1) ; k++)
01077 if (jw(n2+k) < lfil)
01078 size_upper++;
01079
01080 size_row += size_upper;
01081 A.ReallocateRow(i_row,size_row);
01082 levs(i_row).Reallocate(size_upper);
01083
01084 index_lu = 0;
01085 for (k = 0; k < length_lower; k++)
01086 {
01087 if (jw(n2+k) < lfil)
01088 {
01089 A.Value(i_row,index_lu) = w(k);
01090 A.Index(i_row,index_lu) = jw(k);
01091 ++index_lu;
01092 }
01093 }
01094
01095
01096 Index_Diag(i_row) = index_lu;
01097 A.Value(i_row,index_lu) = cone / w(i_row);
01098 A.Index(i_row,index_lu++) = i_row;
01099
01100 for (k = (i_row+1) ; k <= (i_row+length_upper-1) ; k++)
01101 {
01102 if (jw(n2+k) < lfil)
01103 {
01104 A.Index(i_row,index_lu) = jw(k);
01105 A.Value(i_row,index_lu) = w(k);
01106 levs(i_row)(index_lu-Index_Diag(i_row)-1) = jw(n2+k);
01107 ++index_lu;
01108 }
01109 }
01110 }
01111 }
01112
01113
01114 template<class cplx, class Allocator>
01115 void GetIlu0(Matrix<cplx, General, ArrayRowSparse, Allocator>& A)
01116 {
01117 int j_col, jrow, jw, n = A.GetM();
01118 IVect Index(n), ju(n);
01119
01120 cplx czero, cone;
01121 SetComplexZero(czero);
01122 SetComplexOne(cone);
01123
01124
01125 Index.Fill(-1); ju.Fill(-1);
01126 cplx tl;
01127
01128
01129 for (int i_row = 0 ; i_row < n ; i_row++)
01130 {
01131
01132 for (int j = 0 ; j < A.GetRowSize(i_row) ; j++ )
01133 {
01134 j_col = A.Index(i_row, j);
01135 if (j_col == i_row)
01136 ju(i_row) = j;
01137
01138 Index(j_col) = j;
01139 }
01140
01141 int jm = ju(i_row)-1;
01142
01143
01144 for (int j = 0; j <= jm; j++)
01145 {
01146 jrow = A.Index(i_row, j);
01147 tl = A.Value(i_row, j)*A.Value(jrow, ju(jrow));
01148 A.Value(i_row, j) = tl;
01149
01150
01151 for ( j_col = (ju(jrow)+1); j_col < A.GetRowSize(jrow); j_col++)
01152 {
01153 jw = Index(A.Index(jrow,j_col));
01154 if (jw != -1)
01155 A.Value(i_row, jw) -= tl*A.Value(jrow, j_col);
01156 }
01157 }
01158
01159
01160
01161 if (A.Value(i_row, ju(i_row)) == czero)
01162 {
01163 cout << "Factorization fails because we found a null coefficient"
01164 << " on diagonal " << i_row << endl;
01165 abort();
01166 }
01167
01168 A.Value(i_row,ju(i_row)) = cone / A.Value(i_row,ju(i_row));
01169
01170
01171 Index(i_row) = -1;
01172 for (int i = 0; i < A.GetRowSize(i_row); i++)
01173 Index(A.Index(i_row, i)) = -1;
01174 }
01175
01176 }
01177
01178
01179 template<class cplx, class Allocator>
01180 void GetMilu0(Matrix<cplx, General, ArrayRowSparse, Allocator>& A)
01181 {
01182 int j_col, jrow, jw, n = A.GetM();
01183 IVect Index(n), ju(n);
01184
01185 cplx czero, cone;
01186 SetComplexZero(czero);
01187 SetComplexOne(cone);
01188
01189
01190 Index.Fill(-1); ju.Fill(-1);
01191 cplx tl;
01192
01193
01194 for (int i_row = 0 ; i_row < n ; i_row++)
01195 {
01196
01197 for (int j = 0; j < A.GetRowSize(i_row); j++ )
01198 {
01199 j_col = A.Index(i_row, j);
01200 if (j_col == i_row)
01201 ju(i_row) = j;
01202
01203 Index(j_col) = j;
01204 }
01205
01206 int jm = ju(i_row)-1;
01207
01208
01209 cplx s(0);
01210 for (int j = 0; j <= jm; j++)
01211 {
01212 jrow = A.Index(i_row, j);
01213 tl = A.Value(i_row, j)*A.Value(jrow, ju(jrow));
01214 A.Value(i_row, j) = tl;
01215
01216
01217 for ( j_col = (ju(jrow)+1); j_col < A.GetRowSize(jrow); j_col++ )
01218 {
01219 jw = Index(A.Index(jrow, j_col));
01220 if (jw != -1)
01221 A.Value(i_row, jw) -= tl*A.Value(jrow, j_col);
01222 else
01223 s += tl*A.Value(jrow, j_col);
01224 }
01225 }
01226
01227
01228 A.Value(i_row, ju(i_row)) -= s;
01229 if (A.Value(i_row, ju(i_row)) == czero)
01230 {
01231 cout << "Factorization fails because we found a null coefficient"
01232 << " on diagonal " << i_row << endl;
01233 abort();
01234 }
01235
01236 A.Value(i_row, ju(i_row)) = cone /A.Value(i_row, ju(i_row));
01237
01238
01239 Index(i_row) = -1;
01240 for (int i = 0; i < A.GetRowSize(i_row); i++)
01241 Index(A.Index(i_row, i)) = -1;
01242 }
01243 }
01244
01245 }
01246
01247 #define SELDON_FILE_ILUT_PRECONDITIONING_CXX
01248 #endif