static void Main() { try { //методы на подпространствах Крылова: CSlR-формат матрицы var T3 = new Thread(() => { //разреженная матрица var A = new CSlR_Matrix("Data\\Sparse_Format\\Systems1\\NonSPD\\"); //заполнение вектора истинного решения и правой части var F = new Vector(A.N); var X_True = new Vector(A.N); int pre = 1; //заполнение вектора истинного решения и правой части for (int i = 0; i < A.N; i++) { X_True.Elem[i] = 1.0; } A.Mult_MV(X_True, F); var Solver = new BCG(30000, 1e-12); var X = Solver.Start_Solver(A, F, 2); Console.WriteLine(Tools.Relative_Error(X, X_True)); }); //время решения Console.WriteLine(Tools.Measurement_Time(T3)); } catch (Exception E) { Console.WriteLine("\n*** Error! ***"); Console.WriteLine("Method: {0}", E.TargetSite); Console.WriteLine("Message: {0}\n", E.Message); } }
public Diag_Predconditioner(CSlR_Matrix A) { Diag = new Vector(A.N); for (int i = 0; i < A.N; i++) { Diag.Elem[i] = A.di[i]; } }
public Diagonal_Preconditioner(CSlR_Matrix A) { Diag = new Vector(A.N); for (int i = 0; i < A.N; i++) { if (Math.Abs(A.di[i]) < CONST.EPS) { throw new Exception("Diagonal_Preconditioner: " + (i + 1).ToString() + " position on di = " + A.di[i].ToString()); } Diag.Elem[i] = A.di[i]; } }
//------------------------------------------------------------------------------------------------- //операция неполного ILU-разложения (Incomplete LU-decomposition) в формате CSlR public CSlR_Matrix Create_ILU_Decomposition() { var Matrix = new CSlR_Matrix(); Matrix.N = N; Matrix.iptr = iptr; Matrix.jptr = jptr; int N_autr = autr.Length; Matrix.autr = new double[N_autr]; Matrix.altr = new double[N_autr]; Matrix.di = new double[N]; for (int i = 0; i < N_autr; i++) { Matrix.altr[i] = altr[i]; Matrix.autr[i] = autr[i]; } for (int i = 0; i < N; i++) { Matrix.di[i] = di[i]; } //начинаем с i = 1, т.к. в первой строке нижнего треугольника только диагональный элемент for (int i = 1; i < N; 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]] - 1; 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 Incomplete_LU_Decomposition_CSlR(CSlR_Matrix A) { ILU = new CSlR_Matrix(); ILU.N = A.N; ILU.iptr = A.iptr; ILU.jptr = A.jptr; int N_autr = A.autr.Length; ILU.autr = new double[N_autr]; ILU.altr = new double[N_autr]; ILU.di = new double[A.N]; for (int i = 0; i < N_autr; i++) { ILU.altr[i] = A.altr[i]; ILU.autr[i] = A.autr[i]; } for (int i = 0; i < A.N; i++) { ILU.di[i] = A.di[i]; } //начинаем с i = 1, т.к. в первой строке нижнего треугольника только диагональный элемент for (int i = 1; i < A.N; i++) { for (int j = A.iptr[i] - 1; j < A.iptr[i + 1] - 1; j++) { for (int a = A.iptr[i] - 1; a < j; a++) { for (int b = A.iptr[A.jptr[j] - 1] - 1; b < A.iptr[A.jptr[j]] - 1; b++) { if (A.jptr[a] == A.jptr[b]) { ILU.altr[j] -= ILU.altr[a] * ILU.autr[b]; ILU.autr[j] -= ILU.autr[a] * ILU.altr[b]; } } } ILU.autr[j] /= ILU.di[A.jptr[j] - 1]; ILU.di[i] -= ILU.autr[j] * ILU.altr[j]; } } }
public Vector Start_Solver(CSlR_Matrix A, Vector F, Preconditioner.Type_Preconditioner PREC) { switch (PREC) { case Preconditioner.Type_Preconditioner.Diagonal_Preconditioner: { Preconditioner = new Diagonal_Preconditioner(A); break; } case Preconditioner.Type_Preconditioner.LU_Decomposition: { Preconditioner = new LU_Preconditioner(A); break; } } int n = A.N; Vector RES = new Vector(n); for (int i = 0; i < n; i++) { RES.Elem[i] = 0.0; } Vector r = new Vector(n); Vector rs = new Vector(n); Vector p = new Vector(n); Vector ps = new Vector(n); Vector vec = new Vector(n); Vector vec2 = new Vector(n); double alpha, beta, sc1, sc2; bool Flag = true; A.Mult_MV(RES, vec); for (int i = 0; i < n; i++) { r.Elem[i] = F.Elem[i] - vec.Elem[i]; } Preconditioner.Start_Preconditioner(r, ps); for (int i = 0; i < n; i++) { r.Elem[i] = ps.Elem[i]; rs.Elem[i] = ps.Elem[i]; p.Elem[i] = ps.Elem[i]; } while (Flag && Iter < Max_Iter) { sc1 = r * rs; A.Mult_MV(p, vec); Preconditioner.Start_Preconditioner(vec, vec2); sc2 = vec2 * ps; alpha = sc1 / sc2; for (int i = 0; i < n; i++) { RES.Elem[i] += alpha * p.Elem[i]; r.Elem[i] -= alpha * vec2.Elem[i]; } Preconditioner.Start_Tr_Preconditioner(ps, vec); A.Mult_MtV(vec, vec2); for (int i = 0; i < n; i++) { rs.Elem[i] -= alpha * vec2.Elem[i]; } sc2 = r * rs; beta = sc2 / sc1; double Norma_r = r.Norma(); if (Norma_r < Eps) { Flag = false; } if (Math.Abs(beta) < Double.Epsilon) { throw new Exception("BiConjurate_Gradient_Method: diverges given ~r(0)"); } for (int i = 0; i < n; i++) { p.Elem[i] = r.Elem[i] + beta * p.Elem[i]; ps.Elem[i] = rs.Elem[i] + beta * ps.Elem[i]; } Iter++; Console.WriteLine("{0,-20} {1,-20}", Iter, Norma_r); } return(RES); }
static void Main() { try { //прямые методы: Гаусс, LU-разложение, QR-разложение var T1 = new Thread(() => { int N = 5; var A = new Matrix(N, N); var X_true = new Vector(N); //заполнение СЛАУ for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { A.Elem[i][j] = 1.0 / (i + j + 2.0); } X_true.Elem[i] = 1; } //правая часть var F = A * X_true; //метод Гаусса var Solver = new Gauss_Method(); var X = Solver.Start_Solver(A, F); }); //итерационные блочные методы: Якоби, Гаусса-Зейделя и SOR var T2 = new Thread(() => { //матрица var A = new Matrix("Data\\Dense_Format\\"); //вектор правой части var F = new Vector("Data\\Dense_Format\\"); //метод SOR при w = 1.8 (максимальное число итераций = 30000, точность = 1e-12) var Solver = new SOR_Method(30000, 1e-12); var X = Solver.Start_Solver(A, F, 1.85); }); //методы на подпространствах Крылова: CSlR-формат матрицы var T3 = new Thread(() => { //разреженная СЛАУ var A = new CSlR_Matrix("Data\\Sparse_Format\\Systems2\\NonSPD\\"); var F = new Vector(A.N); var X_True = new Vector(A.N); //заполнение вектора истинного решения и правой части for (int i = 0; i < A.N; i++) { X_True.Elem[i] = 1.0; } A.Mult_MV(X_True, F); }); //время решения задачи Console.WriteLine(Tools.Measurement_Time(T3)); } catch (Exception E) { Console.WriteLine("\n*** Error! ***"); Console.WriteLine("Method: {0}", E.TargetSite); Console.WriteLine("Message: {0}\n", E.Message); } }
//конструктор LU-преобусловливателя public LU_Preconditioner(CSlR_Matrix A) { ILU = new Incomplete_LU_Decomposition_CSlR(A); }
public Vector Start_Solver(CSlR_Matrix A, Vector F, Preconditioner.Type_Preconditioner PREC) { switch (PREC) { case Preconditioner.Type_Preconditioner.Diagonal_Preconditioner: { Preconditioner = new Diagonal_Preconditioner(A); break; } case Preconditioner.Type_Preconditioner.LU_Decomposition: { Preconditioner = new LU_Preconditioner(A); break; } } int n = A.N; Vector RES = new Vector(n); for (int i = 0; i < n; i++) { RES.Elem[i] = 0.0; } Vector r = new Vector(n); Vector p = new Vector(n); Vector vec = new Vector(n); double alpha, beta, sc1, sc2; bool Flag = true; double Norma_r = 0; A.Mult_MV(RES, vec); for (int i = 0; i < n; i++) { r.Elem[i] = F.Elem[i] - vec.Elem[i]; } Preconditioner.Start_Preconditioner(r, p); while (Flag && Iter < Max_Iter) { sc1 = p * r; A.Mult_MV(p, vec); sc2 = vec * p; alpha = sc1 / sc2; for (int i = 0; i < n; i++) { RES.Elem[i] += alpha * p.Elem[i]; r.Elem[i] -= alpha * vec.Elem[i]; } Preconditioner.Start_Preconditioner(r, vec); sc2 = vec * r; beta = sc2 / sc1; Norma_r = r.Norma(); if (Norma_r < 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("{0,-20} {1,-20}", Iter, Norma_r.ToString("E")); } return(RES); }
public Vector Start_Solver(CSlR_Matrix A, Vector F, int PREC) { int n = A.N; // решение Vector RES = new Vector(n); for (int i = 0; i < n; i++) { RES.Elem[i] = 0.0; } //реализация предобусловливателя switch (PREC) { case 1: { Pr = new Diag_Predconditioner(A); break; } case 2: { Pr = new ILU_Decomposition(A); break; } //default: { Pr = new E_Predconditioner(); break; } } var r = new Vector(n); var p = new Vector(n); var vec = new Vector(n); // параметры double alpha, betta, sc1, sc2; // флаг для остановки int Flag = 0; // ||r|| double nev_r = 0; // начало CG A.Mult_MV(RES, vec); for (int i = 0; i < n; i++) { r.Elem[i] = F.Elem[i] - vec.Elem[i]; } Pr.Start_Predconditioner(r, p); // в r предобусловленная система-невязка while (Flag != 1 && Iter < Max_Iter) { sc1 = p * r; A.Mult_MV(p, vec); sc2 = vec * p; alpha = sc1 / sc2; for (int i = 0; i < n; i++) { RES.Elem[i] += alpha * p.Elem[i]; r.Elem[i] -= alpha * vec.Elem[i]; } Pr.Start_Tr_Predconditioner(r, vec); sc2 = vec * p; betta = sc2 / sc1; nev_r = r.Norm(); if (nev_r < Eps) { Flag = 1; } if (Flag == 0) { for (int i = 0; i < n; i++) { p.Elem[i] = vec.Elem[i] + betta * p.Elem[i]; } } Console.WriteLine("{0,-20} {1,-20}", Iter, nev_r.ToString("E")); Iter++; } return(RES); }
static void Main() { try { //прямые методы: Гаусс, LU-разложение, QR-разложение var T1 = new Thread(() => { //int N = 10; //var A = new Matrix(N, N); //var X_true = new Vector(N); //заполнение СЛАУ //for (int i = 0; i < N; i++) //{ // for (int j = 0; j < N; j++) // { // A.Elem[i][j] = 1.0 / (i + j + 1.0); // } // X_true.Elem[i] = 1; //} // for (int i = 0; i < N; i++) // { // for (int j = 0; j < N; j++) // { // //A.Elem[i][j] = 1.0 / (i + j + 1.0); // } // X_true.Elem[i] = 1; // } // var ElemMatrix = new double[][] // { // //new double[]{-2,-2,-1}, // //new double[]{1,0,-2}, // //new double[]{0,1,2} // new double[]{5,1,9}, // new double[]{1,4,1}, // new double[]{5,1,3} // }; // A.Elem = ElemMatrix; // //правая часть // var F = A * X_true; // //решатель // //var Solver = new Gauss_Method(); // //var Solver = new LU_Decomposition(A); // var Solver = new QR_Decomposition(A, QR_Decomposition.QR_Algorithm.Householder); // var X = Solver.Start_Solver(F); // //X.Console_Write_Vector(); // Console.WriteLine("\nError: {0}\n", Tools.Relative_Error(X, X_true)); }); //Итерационные методы var T2 = new Thread(() => { }); //итерационные методы: Якоби и SOR var T3 = new Thread(() => { int SIZE_BLOCK = 450; double m = 1e+4; double z = 1.2; for (int k = 0; k < 1; k++) { //var Solver = new Jacobi_Method(30000, 1e-12); var Solver = new SOR_Method(30000, 1e-4); //Вычисление точного решения //var A_g = new Matrix("Data\\System3\\", m); //var F_g = new Vector("Data\\System3\\"); //var GSolver = new Gauss_Method(); //var sw = new Stopwatch(); //sw.Start(); //var X_true = GSolver.Start_Solver(A_g, F_g); //sw.Stop(); //Console.WriteLine($"\nTime: {sw.Elapsed}"); //Блочная или обычная матрица/вектор //var A = new Block_Matrix("Data\\System3\\", SIZE_BLOCK, m); //var F = new Block_Vector("Data\\System3\\", SIZE_BLOCK); //var A = new Matrix("Data\\System3\\", m); //var F = new Vector("Data\\System3\\"); var A = new Matrix(3, 3); var F = new Vector(3); F.Elem[0] = 8; F.Elem[1] = 8; F.Elem[2] = 11; var ElemMatrix = new double[][] { //new double[]{-2,-2,-1}, //new double[]{1,0,-2}, //new double[]{0,1,2} new double[] { 10, 1, 0 }, new double[] { 1, 10, 0 }, new double[] { 0, 0, 10 } }; A.Elem = ElemMatrix; var sw = new Stopwatch(); sw.Start(); //var X = Solver.Start_Solver(A, F); var X = Solver.Start_Solver(A, F, 1); //var X = Solver.Start_Solver(A, F, z); sw.Stop(); Console.WriteLine($"\nTime: {sw.Elapsed}"); //var X_true_Norm = X_true.Norma(); //ДЛЯ ОБЫЧНОЙ МАТРИЦЫ //for (int j = 0; j < 900; j++) //{ // X_true.Elem[j] = X.Elem[j] - X_true.Elem[j]; //} //ДЛЯ БЛОЧНОЙ МАТРИЦЫ //int q = 0; //for (int i = 0; i < X.N; i++) //{ // for (int j = 0; j < SIZE_BLOCK; j++) // { // X_true.Elem[q] = X.Block[i].Elem[j] - X_true.Elem[q]; // q++; // } //} //Console.WriteLine("delta = " + (X_true.Norma() / X_true_Norm)); //Console.WriteLine("Cond(A) = " + A.Cond_InfinityNorm() + "\n"); //Console.WriteLine("m = " + m); //Console.WriteLine("z = " + z); Console.WriteLine("--------------------------"); //m /= 100; //z += 0.1; } }); var T4 = new Thread(() => { var A = new CSlR_Matrix("Data\\Sparse_Format\\Systems2\\nonSPD\\"); var X_true = new Vector(A.N); var F = new Vector(A.N); for (int i = 0; i < A.N; i++) { X_true.Elem[i] = 1.0; } A.Mult_MV(X_true, F); var Solver = new Conjurate_Gradient_Method(30000, 1e-12); //var Solver = new BiConjurate_Gradient_Method(30000, 1e-12); var sw = new Stopwatch(); sw.Start(); var X = Solver.Start_Solver(A, F, Preconditioner.Type_Preconditioner.LU_Decomposition); sw.Stop(); Console.WriteLine($"\nTime: {sw.Elapsed}"); Console.WriteLine("Relative_Error: {0}", Tools.Relative_Error(X, X_true)); Console.ReadLine(); for (int i = 0; i < X.N; i++) { Console.WriteLine("X[{0}] = {1}", i + 1, X.Elem[i]); } }); //время решения Console.WriteLine(Tools.Measurement_Time(T4)); } catch (Exception E) { Console.WriteLine("\n*** Error! ***"); Console.WriteLine("Method: {0}", E.TargetSite); Console.WriteLine("Message: {0}\n", E.Message); } Console.ReadLine(); }
public ILU_Decomposition(CSlR_Matrix A) { LU = A.Create_ILU_Decomposition(); }