public DiagonalPreconditioner(CSlRMatrix A) { diag = new Vector(A.Row); for (int i = 0; i < A.Row; i++) { diag.Elem[i] = A.di[i]; } }
public static double RelativeDiscrepancy(CSlRMatrix A, Vector x, Vector f) { var q = new Vector(A.Row); A.MultMtV(x, q); for (int i = 0; i < x.Size; i++) { q.Elem[i] -= f.Elem[i]; } return(Math.Sqrt((q * q) / (f * f))); }
//------------------------------------------------------------------------------------------------- //операция неполного LU-разложения в формате CSlR public CSlRMatrix ILU_CSlR() { var matrix = new CSlRMatrix(); matrix.Column = Column; matrix.Row = Row; matrix.iptr = iptr; matrix.jptr = jptr; int nAutr = autr.Length; matrix.autr = new double[nAutr]; matrix.altr = new double[nAutr]; matrix.di = new double[Column]; for (int i = 0; i < nAutr; i++) { matrix.altr[i] = altr[i]; matrix.autr[i] = autr[i]; } for (int i = 0; i < Column; i++) { matrix.di[i] = di[i]; } for (int i = 1; i < Column; i++) { for (int j = iptr[i] - 1; j < iptr[i + 1] - 1; j++) { for (int a = iptr[i] - 1; a < j; a++) { for (int b = iptr[jptr[j] - 1] - 1; b <= iptr[jptr[j]] - 2; b++) { if (jptr[a] == jptr[b]) { matrix.altr[j] -= matrix.altr[a] * matrix.autr[b]; matrix.autr[j] -= matrix.autr[a] * matrix.altr[b]; } } } matrix.autr[j] /= matrix.di[jptr[j] - 1]; matrix.di[i] -= matrix.autr[j] * matrix.altr[j]; } } return(matrix); }
public IncompleteLUPreconditioner(CSlRMatrix A) { ILU = A.ILU_CSlR(); }
public Vector StartSolver(CSlRMatrix A, Vector F, Preconditioner.PreconditionerType prec) { switch (prec) { case ComMethods.Preconditioner.PreconditionerType.Diagonal: { Preconditioner = new DiagonalPreconditioner(A); break; } case ComMethods.Preconditioner.PreconditionerType.ILU: { Preconditioner = new IncompleteLUPreconditioner(A); break; } } int n = A.Row; var res = new Vector(n); // auxiliary vectors var r = new Vector(n); var p = new Vector(n); var vec = new Vector(n); // methods parameters double alpha, beta, sc1, sc2; bool flag = true; // residual norm double rNorm = 0; // residual: r = F - Ax A.MultMtV(res, vec); for (int i = 0; i < n; i++) { r.Elem[i] = F.Elem[i] - vec.Elem[i]; } // search vector: Mp = r Preconditioner.StartPreconditioner(r, p); // iterative process while (flag && Iter < MaxIter) { sc1 = p * r; // (M^(-1) * r; r) A.MultMtV(p, vec); // vec = A * p sc2 = vec * p; // sc2 = (A * p; p) alpha = sc1 / sc2; // linear search coefficient // result vector & residual for (int i = 0; i < n; i++) { res.Elem[i] += alpha * p.Elem[i]; r.Elem[i] -= alpha * vec.Elem[i]; } Preconditioner.StartPreconditioner(r, vec); // vec := M^(-1) * r sc2 = vec * r; // (M^(-1) * r; r) beta = sc2 / sc1; // coefficient in choosing a search direction rNorm = r.Normal(); // residual norm if (rNorm < Eps) { flag = false; } if (flag) { for (int i = 0; i < n; i++) { p.Elem[i] = vec.Elem[i] + beta * p.Elem[i]; } } Iter++; // Console.WriteLine("\n{0, -20} {1, 20:E}", Iter, rNorm); } Console.WriteLine("Iter: {0, -20} \nNorm: {1, 20:E}", Iter, rNorm); return(res); }
public Vector StartSolver(CSlRMatrix A, Vector F, Preconditioner.PreconditionerType prec) { switch (prec) { case ComMethods.Preconditioner.PreconditionerType.Diagonal: { Preconditioner = new DiagonalPreconditioner(A); break; } case ComMethods.Preconditioner.PreconditionerType.ILU: { Preconditioner = new IncompleteLUPreconditioner(A); break; } } int n = A.Row; var res = new Vector(n); // auxiliary vectors var r = new Vector(n); // ordinary residual var r_ = new Vector(n); // new residual var p = new Vector(n); var p_ = new Vector(n); var vec = new Vector(n); var vec_ = new Vector(n); var vec_help = new Vector(n); // methods parameters double alpha, beta, sc1, sc2; bool flag = true; // residual norm double rNorm = 0; // residual: r = M^-1 * (F - Ax) A.MultMtV(res, vec_help); for (int i = 0; i < n; i++) { vec_help.Elem[i] = F.Elem[i] - vec_help.Elem[i]; } Preconditioner.StartPreconditioner(vec_help, r); for (int i = 0; i < n; i++) { res.Elem[i] = 0.0; p.Elem[i] = r_.Elem[i] = p_.Elem[i] = r.Elem[i]; } while (flag && Iter < MaxIter) { sc1 = r * r_; // scalar product sc1 = (r; r_) A.MultMV(p, vec_help); // vec_help = A * p // vec = M^(-1) * A * p Preconditioner.StartPreconditioner(vec_help, vec); sc2 = vec * p_; // (M^(-1) * A * p; p_) alpha = sc1 / sc2; // linear search coefficient // result vector & residual for (int i = 0; i < n; i++) { res.Elem[i] += alpha * p.Elem[i]; r.Elem[i] -= alpha * vec.Elem[i]; } // p_ into the preconditioned system Preconditioner.StartTrPreconditioner(p_, vec_help); A.MultMtV(vec_help, vec_); // vec_ = A_t * M^(-t) * p_ // new residual r_ for (int i = 0; i < n; i++) { r_.Elem[i] -= alpha * vec_.Elem[i]; } sc2 = r * r_; // (r_new; (r_)_new) beta = sc2 / sc1; // coefficient in choosing a search direction rNorm = r.Normal(); // ordinary residual norm if (rNorm < Eps) { flag = false; } // new search directions if (flag) { for (int i = 0; i < n; i++) { p.Elem[i] = r.Elem[i] + beta * p.Elem[i]; p_.Elem[i] = r_.Elem[i] + beta * p_.Elem[i]; } } Iter++; // Console.WriteLine("\n{0, -20} {1, 20:E}", Iter, rNorm); } Console.WriteLine("Iter: {0, -20} \nNorm: {0, 20:E}", Iter, rNorm); return(res); }