//блочный метод Якоби
        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);
        }
Exemple #3
0
        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);
        }