00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef _SSOR_PRECONDITIONER_H_
00032 #define _SSOR_PRECONDITIONER_H_
00033
00034 #include "Preconditioner.h"
00035 #include "SparseRowMatrix.h"
00036 #include "RealVector.h"
00037 #include <string>
00038
00039 namespace FDDlib {
00040
00049 class SSORPreconditioner : public Preconditioner
00050 {
00051 private:
00052
00054 SparseRowMatrix<double>* SRMDp;
00055
00059 RealVector<double> invDiag_;
00060
00062 RealVector<double> diagonal_;
00063
00065 double omega_;
00066
00067
00068 public:
00070 SSORPreconditioner(double omega)
00071 {
00072 len_ = 0;
00073 omega_ = omega;
00074 SRMDp = (SparseRowMatrix<double>*) NULL;
00075 }
00076
00078 ~SSORPreconditioner()
00079 {
00080 }
00081
00085 void init(SparseRowMatrix<double>& SRMD) throw(std::string)
00086 {
00087 int i;
00088
00089 SRMDp = &SRMD;
00090 len_ = SRMD.getNumRows();
00091
00092 invDiag_.init(len_);
00093 diagonal_.init(len_);
00094
00095 for (i = 0; i < len_; i++)
00096 {
00097 if (SRMD.val(i,i) == 0) {
00098 throw std::string("SSORPreconditioner::init: zero on matrix diagonal.");
00099 }
00100 else
00101 {
00102 invDiag_(i) = 1 / SRMD.val(i,i);
00103 diagonal_(i) = SRMD.val(i,i);
00104 }
00105 }
00106
00107 }
00108
00114 template<class Vector>
00115 Vector lowerSolve(const Vector& x) const
00116 {
00117 int i, j;
00118 int cols, col;
00119 Vector r(len_);
00120 SparseRowEntry<double>* ep;
00121 double v;
00122
00123 for (i = 0; i < len_; i++)
00124 {
00125 if (i == 0)
00126 {
00127 r(i) = invDiag_(i)*x(i);
00128 }
00129 else
00130 {
00131 cols = SRMDp->getNumCols(i);
00132 ep = SRMDp->getRowEntry(i);
00133 v = 0;
00134 for (j = 0; j < cols; j++)
00135 {
00136 col = ep->column;
00137 if (col < i)
00138 {
00139 v += (ep->val)*r(col);
00140 }
00141 ep++;
00142 }
00143 v = x(i) - omega_*v;
00144 v *= invDiag_(i);
00145 r(i) = v;
00146 }
00147 }
00148
00149 return r;
00150 }
00151
00157 template<class Vector>
00158 Vector diagonalMultiply(const Vector& x) const
00159 {
00160 Vector r(len_);
00161 int i;
00162
00163 for (i = 0; i < len_; i++)
00164 {
00165 r(i) = x(i)*diagonal_(i);
00166 }
00167
00168 return r;
00169 }
00170
00176 RealVector<double> upperSolve(const RealVector<double>& x) const
00177 {
00178 int i, j;
00179 int cols, col;
00180 RealVector<double> r(len_);
00181 SparseRowEntry<double>* ep;
00182 double v;
00183
00184 for (i = len_ - 1; i >= 0; i--)
00185 {
00186 if (i == len_ - 1)
00187 {
00188 r(i) = invDiag_(i)*x(i);
00189 }
00190 else
00191 {
00192 cols = SRMDp->getNumCols(i);
00193 v = 0;
00194 ep = SRMDp->getRowEntry(i);
00195 for (j = 0; j < cols; j++)
00196 {
00197 col = ep->column;;
00198 if (col > i)
00199 {
00200 v += (ep->val)*r(col);
00201 }
00202 ep++;
00203 }
00204 v = x(i) - omega_*v;
00205 v *= invDiag_(i);
00206 r(i) = v;
00207 }
00208 }
00209
00210 return r;
00211 }
00212
00213
00219 RealVector<double> solve(const RealVector<double>& x) const
00220 {
00221 RealVector<double> u(len_);
00222 RealVector<double> l(len_);
00223 RealVector<double> d(len_);
00224
00225 l = lowerSolve(x);
00226 d = diagonalMultiply(l);
00227 u = upperSolve(d);
00228
00229 return u;
00230
00231 }
00232
00233 };
00234
00235 }
00236 #endif