//блочный метод Якоби public Block_Vector Start_Solver(Block_Matrix A, Block_Vector F) { //норма разности решений на двух итерациях double Norm_Xnew_Xold; //вектор результата на текущей и следующей итерации var RES = new Block_Vector(A.N, A.Size_Block); var RES_New = new Block_Vector(A.N, A.Size_Block); //LU-решатель для обращения диагональных блоков var LU_Solver = new LU_Decomposition(); //вспомогательный вектор для вычисления скобки (F - Ax) var F_Ax = new Vector(A.Size_Block); //итерации метода Якоби do { Norm_Xnew_Xold = 0.0; //цикл по неизвестным for (int i = 0; i < RES.N; i++) { //инициализация скобки (F - Ax) F_Ax.Copy(F.Block[i]); //произведение блоков матрицы на старые X (нижний треугольник) for (int j = 0; j < i; j++) { var Current_Matrix_Block = A.Block[i][j]; var Current_Vector_Block = RES.Block[j]; for (int Row = 0; Row < Current_Matrix_Block.M; Row++) { for (int Column = 0; Column < Current_Matrix_Block.N; Column++) { F_Ax.Elem[Row] -= Current_Matrix_Block.Elem[Row][Column] * Current_Vector_Block.Elem[Column]; } } } //произведение блоков матрицы на старые X (верхний треугольник) for (int j = i + 1; j < A.N; j++) { var Current_Matrix_Block = A.Block[i][j]; var Current_Vector_Block = RES.Block[j]; for (int Row = 0; Row < Current_Matrix_Block.M; Row++) { for (int Column = 0; Column < Current_Matrix_Block.N; Column++) { F_Ax.Elem[Row] -= Current_Matrix_Block.Elem[Row][Column] * Current_Vector_Block.Elem[Column]; } } } //решение СЛАУ с диагональным блоком LU_Solver.LU = A.Block[i][i]; F_Ax = LU_Solver.Start_Solver(F_Ax); //формируем результат для i-ой компоненты и квадрат нормы разности решений for (int k = 0; k < RES.Size_Block; k++) { RES_New.Block[i].Elem[k] = F_Ax.Elem[k]; Norm_Xnew_Xold += Math.Pow(RES_New.Block[i].Elem[k] - RES.Block[i].Elem[k], 2); } } //копирование полученного результата for (int i = 0; i < RES.N; i++) { RES.Block[i].Copy(RES_New.Block[i]); } //норма разности решений Norm_Xnew_Xold = Math.Sqrt(Norm_Xnew_Xold); Iter++; Console.WriteLine("Iter {0,-10} {1}", Iter, Norm_Xnew_Xold); }while (Norm_Xnew_Xold > Eps && Iter < Max_Iter); return(RES); }
//метод блочной релаксации: реализация public Block_Vector Start_Solver(Block_Matrix A, Block_Vector F, double w) { //норма разности решений на двух итерациях double Norm_Xnew_Xold; //вектор результата на текущей и следующей итерации var RES = new Block_Vector(A.N, A.Size_Block); var RES_New = new Block_Vector(A.N, A.Size_Block); //LU-решатель для обращения диагональных блоков var LU_Solver = new LU_Decomposition(); //вспомогательный вектор для вычисления скобки (F - Ax) var F_Ax = new Vector(A.Size_Block); //итерации метода блочной релаксации do { Norm_Xnew_Xold = 0.0; //цикл по неизвестным for (int i = 0; i < RES.N; i++) { //инициализация суммы for (int k = 0; k < RES.Size_Block; k++) { F_Ax.Elem[k] = F.Block[i].Elem[k]; } //произведение блоков матрицы на новые X for (int j = 0; j < i; j++) { var Current_Matrix_Block = A.Block[i][j]; var Current_Vector_Block = RES.Block[j]; for (int Row = 0; Row < Current_Matrix_Block.M; Row++) { for (int Column = 0; Column < Current_Matrix_Block.N; Column++) { F_Ax.Elem[Row] -= Current_Matrix_Block.Elem[Row][Column] * Current_Vector_Block.Elem[Column]; } } } //произведение блоков матрицы на предыдущие X for (int j = i + 1; j < A.N; j++) { var Current_Matrix_Block = A.Block[i][j]; var Current_Vector_Block = RES.Block[j]; for (int Row = 0; Row < Current_Matrix_Block.M; Row++) { for (int Column = 0; Column < Current_Matrix_Block.N; Column++) { F_Ax.Elem[Row] -= Current_Matrix_Block.Elem[Row][Column] * Current_Vector_Block.Elem[Column]; } } } //решение СЛАУ с диагональной матрицей LU_Solver.LU = A.Block[i][i]; F_Ax = LU_Solver.Start_Solver(F_Ax); //формируем результат для i-ой компоненты for (int k = 0; k < RES.Size_Block; k++) { double X_NEW = (1 - w) * RES.Block[i].Elem[k] + w * F_Ax.Elem[k]; Norm_Xnew_Xold += Math.Pow(X_NEW - RES.Block[i].Elem[k], 2); RES.Block[i].Elem[k] = X_NEW; } } //норма разности решений Norm_Xnew_Xold = Math.Sqrt(Norm_Xnew_Xold); Iter++; Console.WriteLine("Iter {0,-10} {1}", Iter, Norm_Xnew_Xold); }while (Norm_Xnew_Xold > Eps && Iter < Max_Iter); return(RES); }
public Block_Vector Start_Solver(Block_Matrix A, Block_Vector F, double w) //Блочный { double Norm_Xnew_Xold; var RES = new Block_Vector(A.N, A.Size_Block); for (int i = 0; i < RES.N; i++) { for (int k = 0; k < RES.Size_Block; k++) { RES.Block[i].Elem[k] = 1.0; } } var LU_Solver = new LU_Decomposition(); var F_Ax = new Vector(A.Size_Block); do { Norm_Xnew_Xold = 0.0; for (int i = 0; i < RES.N; i++) { for (int k = 0; k < RES.Size_Block; k++) { F_Ax.Elem[k] = F.Block[i].Elem[k]; } for (int j = 0; j < i; j++) { var Current_Matrix_Block = A.Block[i][j]; var Current_Vector_Block = RES.Block[j]; for (int Row = 0; Row < Current_Matrix_Block.M; Row++) { for (int Col = 0; Col < Current_Matrix_Block.N; Col++) { F_Ax.Elem[Row] -= Current_Matrix_Block.Elem[Row][Col] * Current_Vector_Block.Elem[Col]; } } } for (int j = i + 1; j < A.N; j++) { var Current_Matrix_Block = A.Block[i][j]; var Current_Vector_Block = RES.Block[j]; for (int Row = 0; Row < Current_Matrix_Block.M; Row++) { for (int Col = 0; Col < Current_Matrix_Block.N; Col++) { F_Ax.Elem[Row] -= Current_Matrix_Block.Elem[Row][Col] * Current_Vector_Block.Elem[Col]; } } } LU_Solver.LU = A.Block[i][i]; F_Ax = LU_Solver.Start_Solver(F_Ax); for (int k = 0; k < RES.Size_Block; k++) { double X_NEW = (1 - w) * RES.Block[i].Elem[k] + w * F_Ax.Elem[k]; Norm_Xnew_Xold += Math.Pow(X_NEW - RES.Block[i].Elem[k], 2); RES.Block[i].Elem[k] = X_NEW; } } Norm_Xnew_Xold = Math.Sqrt(Norm_Xnew_Xold); Iter++; Console.WriteLine("Iter {0,-10} {1}", Iter, Norm_Xnew_Xold); }while (Norm_Xnew_Xold > Eps && Iter < Max_Iter); return(RES); }