20 #ifndef SELDON_FILE_SYMMETRIC_ILUT_PRECONDITIONING_CXX
26 template<
class cplx,
class Allocator1,
class Allocator2>
32 int lfil = param.GetFillLevel();
33 typename ClassComplexType<cplx>::Treal zero = 0.0;
34 typename ClassComplexType<cplx>::Treal droptol = param.GetDroppingThreshold();
35 typename ClassComplexType<cplx>::Treal alpha = param.GetDiagonalCoefficient();
36 bool variable_fill =
false;
37 bool standard_dropping =
true;
38 int type_factorization = param.GetFactorisationType();
39 int additional_fill = param.GetAdditionalFillNumber();
40 int print_level = param.GetPrintLevel();
41 if (type_factorization == param.ILUT)
42 standard_dropping =
false;
43 else if (type_factorization == param.ILU_D)
44 standard_dropping =
true;
45 else if (type_factorization == param.ILUT_K)
48 standard_dropping =
false;
50 else if (type_factorization == param.ILU_0)
55 else if (type_factorization == param.MILU_0)
60 else if (type_factorization == param.ILU_K)
62 GetIluk(lfil, print_level, A);
67 typename ClassComplexType<cplx>::Treal tnorm, one(1);
68 int length_lower, length_upper, jpos, jrow;
69 int i_row, j_col, index_lu, length;
75 IVect Index(n), Row_Ind(n);
76 Row_Val.Fill(0); Row_Ind.Fill(-1);
80 bool element_dropped; cplx dropsum, czero;
81 SetComplexZero(czero);
91 int new_percent = 0, old_percent = 0;
92 for (i_row = 0; i_row < n; i_row++)
97 new_percent = int(
double(i_row)/(n-1)*80);
98 for (
int percent = old_percent; percent < new_percent; percent++)
100 cout <<
"#"; cout.flush();
103 old_percent = new_percent;
107 size_row = B.GetRowSize(i_row);
110 for (k = 0 ; k < size_row; k++)
111 tnorm += abs(B.Value(i_row, k));
115 cout <<
"Structurally singular matrix." << endl;
116 cout <<
"Norm of row " << i_row <<
" is equal to 0." << endl;
121 tnorm /=
typename ClassComplexType<cplx>::Treal(size_row);
123 lfil = size_row + additional_fill;
129 Row_Ind(i_row) = i_row;
130 Row_Val(i_row) = czero;
131 Index(i_row) = i_row;
133 for (j = 0; j < size_row; j++)
135 k = B.Index(i_row,j);
136 t = B.Value(i_row,j);
139 Row_Ind(length_lower) = k;
140 Row_Val(length_lower) = t;
141 Index(k) = length_lower;
150 jpos = i_row + length_upper;
165 while (j_col <length_lower)
169 jrow = Row_Ind(j_col);
173 for (j = (j_col+1) ; j < length_lower; j++)
175 if (Row_Ind(j) < jrow)
188 Row_Ind(j_col) = Row_Ind(k);
195 Row_Val(j_col) = Row_Val(k);
202 element_dropped =
false;
203 if (standard_dropping)
204 if (abs(Row_Val(j_col)) <= droptol*tnorm)
206 dropsum += Row_Val(j_col);
207 element_dropped =
true;
211 if (!element_dropped)
213 fact = Row_Val(j_col) * A.Value(jrow, 0);
215 if (!standard_dropping)
217 if (abs(fact) <= droptol)
218 element_dropped =
true;
222 if (!element_dropped)
225 for (k = 1; k < A.GetRowSize(jrow); k++)
227 s = fact * A.Value(jrow,k);
239 i = i_row + length_upper;
257 Row_Ind(length_lower) = j;
258 Index(j) = length_lower;
259 Row_Val(length_lower) = -s;
272 Row_Val(length) = fact;
273 Row_Ind(length) = jrow;
281 for (k = 0; k < length_upper; k++)
282 Index(Row_Ind(i_row + k)) = -1;
286 for (k = 1; k <= (length_upper-1); k++)
288 if (abs(Row_Val(i_row+k)) > droptol * tnorm)
291 Row_Val(i_row+length) = Row_Val(i_row+k);
292 Row_Ind(i_row+length) = Row_Ind(i_row+k);
295 dropsum += Row_Val(i_row+k);
299 if (!standard_dropping)
301 length_upper = length + 1;
302 length = min(length_upper, lfil);
304 qsplit_ilut(Row_Val, Row_Ind, i_row+1,
305 i_row+length_upper, i_row+length+1, tnorm);
311 A.ReallocateRow(i_row, length);
314 Sort(i_row+1, i_row + length - 1, Row_Ind, Row_Val);
315 for (k = (i_row+1) ; k <= (i_row+length-1) ; k++)
317 A.Index(i_row,index_lu) = Row_Ind(k);
318 A.Value(i_row,index_lu) = Row_Val(k);
323 if (standard_dropping)
324 Row_Val(i_row) += alpha*dropsum;
326 if (Row_Val(i_row) == czero)
327 Row_Val(i_row) = (droptol + 1e-4) * tnorm;
329 A.Value(i_row,0) = one / Row_Val(i_row);
337 for (
int i = 0; i < n; i++)
338 for (
int j = 1; j < A.GetRowSize(i); j++)
339 A.Value(i,j) *= A.Value(i,0);
342 cout <<
"The matrix takes " <<
343 int((A.GetDataSize()*(
sizeof(cplx)+4))/(1024*1024)) <<
" MB" << endl;
354 template<
class cplx,
class Allocator>
355 void GetIluk(
int lfil,
int print_level,
360 int length_lower, length_upper, jpos, jrow;
361 int i_row, j_col, index_lu, length;
363 typename ClassComplexType<cplx>::Treal tnorm, one(1);
367 cout <<
"Incorrect fill level." << endl;
373 IVect Index(n), Row_Ind(n), Row_Level(n);
374 Row_Val.Fill(0); Row_Ind.Fill(-1);
378 bool element_dropped;
389 int new_percent = 0, old_percent = 0;
390 for (i_row = 0; i_row < n; i_row++)
395 new_percent = int(
double(i_row)/(n-1)*80);
396 for (
int percent = old_percent; percent < new_percent; percent++)
398 cout <<
"#"; cout.flush();
401 old_percent = new_percent;
405 int size_row = B.GetRowSize(i_row);
407 for (k = 0 ; k < size_row; k++)
408 tnorm += abs(B.Value(i_row, k));
412 cout <<
"Structurally singular matrix." << endl;
413 cout <<
"Norm of row " << i_row <<
" is equal to 0." << endl;
432 Row_Ind(i_row) = i_row;
433 Row_Val(i_row) = 0.0;
434 Index(i_row) = i_row;
436 for (j = 0; j < size_row; j++)
438 k = B.Index(i_row, j);
439 t = B.Value(i_row, j);
443 Row_Ind(length_lower) = k;
444 Row_Val(length_lower) = t;
445 Index(k) = length_lower;
446 Row_Level(length_lower) = -1;
453 Row_Level(i_row) = -1;
458 jpos = i_row + length_upper;
461 Row_Level(jpos) = -1;
474 while (j_col < length_lower)
478 jrow = Row_Ind(j_col);
482 for (j = (j_col+1) ; j < length_lower; j++)
484 if (Row_Ind(j) < jrow)
497 Row_Ind(j_col) = Row_Ind(k);
503 j = Row_Level(j_col);
504 Row_Level(j_col) = Row_Level(k);
508 Row_Val(j_col) = Row_Val(k);
515 element_dropped =
false;
516 fact = Row_Val(j_col) * A.Value(jrow, 0);
518 int jlev = Row_Level(j_col) + 1;
520 element_dropped =
true;
522 if (!element_dropped)
525 for (k = 1; k < A.GetRowSize(jrow); k++)
527 s = fact * A.Value(jrow, k);
528 j = A.Index(jrow, k);
537 i = i_row + length_upper;
541 Row_Level(i) = jlev + levs(jrow)(k) + 1;
548 Row_Level(jpos) = min(Row_Level(jpos),
549 jlev + levs(jrow)(k)+1);
558 Row_Ind(length_lower) = j;
559 Index(j) = length_lower;
560 Row_Val(length_lower) = -s;
561 Row_Level(length_lower) = jlev + levs(jrow)(k) + 1;
568 Row_Level(jpos) = min(Row_Level(jpos),
569 jlev + levs(jrow)(k)+1);
576 Row_Val(length) = fact;
577 Row_Ind(length) = jrow;
585 for (k = 0; k < length_upper; k++)
586 Index(Row_Ind(i_row+k )) = -1;
590 for (k = 1; k <= (length_upper-1); k++)
591 if (Row_Level(i_row+k) < lfil)
595 Sort(i_row+1, i_row+length_upper-1, Row_Ind, Row_Val, Row_Level);
599 A.ReallocateRow(i_row, length);
600 levs(i_row).Reallocate(length);
603 A.Index(i_row, 0) = i_row;
604 A.Value(i_row, 0) = one / Row_Val(i_row);
609 for (k = (i_row+1) ; k <= (i_row+length_upper-1) ; k++)
610 if (Row_Level(k) < lfil)
612 A.Index(i_row, index_lu) = Row_Ind(k);
613 A.Value(i_row, index_lu) = Row_Val(k);
614 levs(i_row)(index_lu) = Row_Level(k);
624 for (
int i = 0; i < n; i++)
625 for (
int j = 1; j < A.GetRowSize(i); j++)
626 A.Value(i,j) *= A.Value(i,0);
629 cout <<
"The matrix takes " <<
630 int((A.GetDataSize()*(
sizeof(cplx)+4))/(1024*1024)) <<
" MB" << endl;
635 template<
class cplx,
class Allocator>
636 void GetIlu0(Matrix<cplx, Symmetric, ArrayRowSymSparse, Allocator>& A)
639 cplx one, invDiag, fact, zero;
641 SetComplexZero(zero);
645 for (
int i = 0; i < n; i++)
647 if (A.GetRowSize(i) == 0)
649 cout <<
"Empty row " << i << endl;
650 cout <<
"Factorisation cannot be completed" << endl;
654 if (A.Index(i, 0) != i)
656 cout <<
"No diagonal element on row " << i << endl;
657 cout <<
"ILU(0) needs one" << endl;
661 if (A.Value(i, 0) == zero)
663 cout <<
"Factorization fails because we found a null coefficient"
664 <<
" on diagonal " << i << endl;
670 for (
int jloc = 1; jloc < A.GetRowSize(i); jloc++)
671 Index(A.Index(i, jloc)) = jloc;
673 invDiag = one / A.Value(i, 0);
675 for (
int jloc = 1; jloc < A.GetRowSize(i); jloc++)
677 int j = A.Index(i, jloc);
680 fact = A.Value(i, jloc) * invDiag;
682 for (
int kloc = 0; kloc < A.GetRowSize(j); kloc++)
686 int k = A.Index(j, kloc);
688 A.Value(j, kloc) -= fact * A.Value(i, Index(k));
693 A.Value(i, 0) = invDiag;
696 for (
int jloc = 1; jloc < A.GetRowSize(i); jloc++)
697 Index(A.Index(i, jloc)) = -1;
702 for (
int i = 0; i < n; i++)
703 for (
int j = 1; j < A.GetRowSize(i); j++)
704 A.Value(i, j) *= A.Value(i, 0);
708 template<
class cplx,
class Allocator>
709 void GetMilu0(Matrix<cplx, Symmetric, ArrayRowSymSparse, Allocator>& A)
712 cplx one, invDiag, fact, zero;
714 SetComplexZero(zero);
715 Vector<cplx> SumRow(n);
718 for (
int i = 0; i < n; i++)
720 if (A.GetRowSize(i) == 0)
722 cout <<
"Empty row " << i << endl;
723 cout <<
"Factorisation cannot be completed" << endl;
727 if (A.Index(i, 0) != i)
729 cout <<
"No diagonal element on row " << i << endl;
730 cout <<
"ILU(0) needs one" << endl;
735 A.Value(i, 0) += SumRow(i);
736 if (A.Value(i, 0) == zero)
738 cout <<
"Factorization fails because we found a null coefficient"
739 <<
" on diagonal " << i << endl;
743 invDiag = one / A.Value(i, 0);
745 for (
int jloc = 1; jloc < A.GetRowSize(i); jloc++)
747 int j = A.Index(i, jloc);
750 fact = A.Value(i, jloc) * invDiag;
753 while ((k2 < A.GetRowSize(i)) && (A.Index(i, k2) < j))
756 for (
int kloc = 0; kloc < A.GetRowSize(j); kloc++)
758 int k = A.Index(j, kloc);
762 while ((k2 < A.GetRowSize(i)) && (A.Index(i, k2) < k))
763 SumRow(j) -= fact * A.Value(i, k2++);
765 if ((k2 < A.GetRowSize(i)) && (A.Index(i, k2) == k))
766 A.Value(j, kloc) -= fact * A.Value(i, k2++);
769 while (k2 < A.GetRowSize(i))
770 SumRow(j) -= fact * A.Value(i, k2++);
774 A.Value(i, 0) = invDiag;
778 for (
int i = 0; i < n; i++)
779 for (
int j = 1; j < A.GetRowSize(i); j++)
780 A.Value(i, j) *= A.Value(i, 0);
786 #define SELDON_FILE_SYMMETRIC_ILUT_PRECONDITIONING_CXX