00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef INCOMPLETE_CHOLESKI_FACTORIZATION_HPP
00022 #define INCOMPLETE_CHOLESKI_FACTORIZATION_HPP
00023
00024 #include <TinyVector.hpp>
00025 #include <TinyMatrix.hpp>
00026 #include <Vector.hpp>
00027 #include <Preconditioner.hpp>
00028
00029 #include <ErrorHandler.hpp>
00030
00044 class IncompleteCholeskiFactorization
00045 : public Preconditioner
00046 {
00047 private:
00049 ReferenceCounting<SparseMatrix> __Lstar;
00050
00052 const SparseMatrix& A;
00053
00054 public:
00055 std::string name() const
00056 {
00057 return "incomplete Choleski factorization";
00058 }
00059
00061 void initializes();
00062
00064 void computes(const Vector<real_t>& r ,
00065 Vector<real_t>& z) const;
00066
00068 IncompleteCholeskiFactorization(const Problem& problem,
00069 const BaseMatrix& AA)
00070 : Preconditioner (problem,
00071 incompleteCholeskiFactorization),
00072 A(static_cast<const SparseMatrix&>(AA))
00073 {
00074 if(AA.type() != BaseMatrix::sparseMatrix) {
00075 throw ErrorHandler(__FILE__, __LINE__,
00076 "cannot use incomplete Choleski Preconditioner:\n"
00077 "\tINCOMPATIBLE matrix type!",
00078 ErrorHandler::normal);
00079 }
00080 __Lstar = new SparseMatrix();
00081 (*__Lstar).copyProfile(static_cast<const SparseMatrix&>(AA));
00082 }
00083
00084
00086 ~IncompleteCholeskiFactorization()
00087 {
00088 ;
00089 }
00090 };
00091
00093
00094 void IncompleteCholeskiFactorization::
00095 computes(const Vector<real_t>& r ,
00096 Vector<real_t>& z) const
00097 {
00098 const SparseMatrix& Lstar = *__Lstar;
00099 ASSERT ((Lstar.size() == r.size())&&(Lstar.size() == z.size()));
00100
00101 z = r;
00102
00104 for(size_t i=0; i<z.size(); ++i) {
00105 real_t sum = z[i];
00106
00107 const SparseLine& line = Lstar.line(i);
00108
00109 size_t j = 0;
00110 while (line[j].column()<(int)i) {
00111 sum -= line[j].value() * z[line[j].column()];
00112 ++j;
00113 }
00114 z[i] = sum/line[j].value();
00115 }
00116
00118 for (int i=z.size()-1; i>=0; --i) {
00119 const SparseLine& line = Lstar.line(i);
00120
00121 size_t j = 0;
00122 while (line[j].column()<i)
00123 ++j;
00124
00125 int ii = j;
00126 j++;
00127
00128 while ((j<line.size())&&(line[j].column() != -1)) {
00129 z[i] -= line[j].value()*z[line[j].column()];
00130 ++j;
00131 }
00132 z[i] /= line[ii].value();
00133 }
00134 }
00135
00137 void IncompleteCholeskiFactorization::initializes()
00138 {
00139 SparseMatrix& Lstar = *__Lstar;
00140 const SparseMatrix& LstarRO = Lstar;
00141
00142 for (size_t i=0; i < A.size(); ++i) {
00143 const SparseLine& Lline = Lstar.line(i);
00144 const SparseLine& Aline = A.line(i);
00145 size_t j = 0;
00146
00147 real_t sumLik = 0;
00148
00149 while ((Lline[j].column()<(int)i)&&(Lline[j].column()!=-1)) {
00150 sumLik += Lline[j].value() * Lline[j].value();
00151 j++;
00152 }
00153
00154
00155 const real_t& Lii
00156 = Lstar(i,i)
00157 = std::sqrt(real_t(std::abs(A(i,i) - sumLik)));
00158
00159 if (Lstar(i,i) == 0.)
00160 Lstar(i,i) = 1.;
00161
00162 j++;
00163
00164 while(j<Aline.size()) {
00165 const size_t& I = i;
00166 const int& J = Aline[j].column();
00167 if(J == -1)
00168 break;
00169
00170 real_t sumLkmLim = 0;
00171
00172 size_t k=0;
00173 while (Aline[k].column()<(int)i) {
00174 const size_t& K = Aline[k].column();
00175 sumLkmLim
00176 += LstarRO(J,K) * Lline[k].value();
00177 k++;
00178 }
00179
00180 Lstar(I,J)
00181 = Lstar(J,I)
00182 = (A(I,J) - sumLkmLim) / Lii;
00183
00184 ++j;
00185 }
00186 }
00187 }
00188
00189 #endif // INCOMPLETE_CHOLESKI_FACTORIZATION_HPP