public BlockMatrix(string PATH, int SIZE_BLOCK)
        {
            //PATH + "Sizebin" - путь файла для чтения
            //FileMode - для открытия
            using (var Reader = new System.IO.BinaryReader(File.Open(PATH + "Size.bin", FileMode.Open)))
            {
                M = Reader.ReadInt32();
                N = M;
            }

            if (M % SIZE_BLOCK != 0)
            {
                throw new Exception("Block_Matrix: cant be separated on blocks");
            }

            M         /= SIZE_BLOCK;
            N         /= SIZE_BLOCK;
            Size_Block = SIZE_BLOCK;
            Block      = new Matrix[M][];

            using (var Reader = new System.IO.BinaryReader(File.Open(PATH + "Matrix.bin", FileMode.Open)))
            {
                var LU_Decomposition = new LU_Decomposition();

                for (int i = 0; i < N; i++)
                {
                    Block[i] = new Matrix[N];

                    //определение блоков в блочной матрице
                    for (int j = 0; j < M; j++)
                    {
                        Block[i][j] = new Matrix(Size_Block, Size_Block);
                    }

                    for (int ii = 0; ii < Size_Block; ii++)
                    {
                        for (int j = 0; j < M; j++)
                        {
                            for (int k = 0; k < Size_Block; k++)
                            {
                                Block[i][j].Elem[ii][k] = Reader.ReadDouble();
                            }
                        }
                    }

                    LU_Decomposition.CreateLU(Block[i][i]);

                    //копируем элементы из LU в блочную матрицу
                    for (int Row = 0; Row < Size_Block; Row++)
                    {
                        for (int Column = 0; Column < Size_Block; Column++)
                        {
                            Block[i][i].Elem[Row][Column] = LU_Decomposition.LU.Elem[Row][Column];
                        }
                    }
                }
            }
        }
        //конструктор матрицы по бинарному файлу
        public Block_Matrix(string PATH, int SIZE_BLOCK)
        {
            //чтение размера системы
            using (var Reader = new BinaryReader(File.Open(PATH + "Size.bin", FileMode.Open)))
            {
                M = Reader.ReadInt32();
                N = M;
            }
            //проверка размера
            if (M % SIZE_BLOCK != 0)
            {
                throw new Exception("Block_Matrix: error in the block size...");
            }
            //размер матрицы
            M         /= SIZE_BLOCK;
            N         /= SIZE_BLOCK;
            Size_Block = SIZE_BLOCK;
            Block      = new Matrix[M][];

            //чтение матрицы
            using (var Reader = new BinaryReader(File.Open(PATH + "Matrix.bin", FileMode.Open)))
            {
                //считываем каждое значение из файла
                try
                {
                    for (int i = 0; i < M; i++)
                    {
                        //выделили место под блочную матрицу
                        Block[i] = new Matrix[N];

                        //выделяем место под каждый блок
                        for (int j = 0; j < N; j++)
                        {
                            Block[i][j] = new Matrix(Size_Block, Size_Block);
                        }

                        //заполняем строки в блоках i-ой строки блочной матрицы
                        for (int ii = 0; ii < Size_Block; ii++)
                        {
                            for (int j = 0; j < N; j++)
                            {
                                for (int k = 0; k < Size_Block; k++)
                                {
                                    Block[i][j].Elem[ii][k] = Reader.ReadDouble();
                                }
                            }
                        }

                        //диагональный блок необходимо преобразовать в LU-разложение
                        var LU_Decomp = new LU_Decomposition(Block[i][i]);
                        Block[i][i] = LU_Decomp.LU;
                    }
                }
                catch { throw new Exception("Block_Matrix: data file is not correct..."); }
            }
        }
示例#3
0
        public Block_Matrix(string PATH, int SIZE_BLOCK, double Perturbation = 1.0)
        {
            using (var Reader = new BinaryReader(File.Open(PATH + "Size.bin", FileMode.Open)))
            {
                M = Reader.ReadInt32();
                N = M;
            }

            if (M % SIZE_BLOCK != 0)
            {
                throw new Exception("Block_Matrix: Block size error");
            }

            M         /= SIZE_BLOCK;
            N         /= SIZE_BLOCK;
            Size_Block = SIZE_BLOCK;
            Block      = new Matrix[M][];

            using (var Reader = new BinaryReader(File.Open(PATH + "Matrix.bin", FileMode.Open)))
            {
                try
                {
                    for (int i = 0; i < M; i++)
                    {
                        Block[i] = new Matrix[N];

                        for (int j = 0; j < N; j++)
                        {
                            Block[i][j] = new Matrix(Size_Block, Size_Block);
                        }

                        for (int ii = 0; ii < Size_Block; ii++)
                        {
                            for (int j = 0; j < N; j++)
                            {
                                for (int k = 0; k < Size_Block; k++)
                                {
                                    Block[i][j].Elem[ii][k] = Reader.ReadDouble();
                                    if (i == j && ii == k)
                                    {
                                        Block[i][j].Elem[ii][k] *= Perturbation;
                                    }
                                }
                            }
                        }
                        var LU_Decomp = new LU_Decomposition(Block[i][i]);
                        Block[i][i] = LU_Decomp.LU;
                    }
                }
                catch
                {
                    throw new Exception("Block_Matrix: Incorrect data file");
                }
            }
        }
        //метод блочной релаксации: реализация
        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 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 BlockVector Solve(BlockMatrix matrixA, BlockVector vectorF)
        {
            double Norma_Xnew_Xold;

            Vector V_Help, V_SUM = new Vector(vectorF.Size_Block);

            Matrix M_Help;

            //для работы с диагональным блоком
            var LU_Solver = new LU_Decomposition();

            var RES = new BlockVector();

            RES.Size_Block = vectorF.Size_Block;
            RES.Block      = new Vector[vectorF.N];
            RES.N          = vectorF.N;

            for (int i = 0; i < RES.N; i++)
            {
                //выделяем место под элемент
                RES.Block[i] = new Vector(RES.Size_Block);

                //начальное приближение x(0)
                for (int k = 0; k < RES.Size_Block; k++)
                {
                    RES.Block[i].Elem[k] = 0.0;
                }
            }

            //итерация
            do
            {
                Norma_Xnew_Xold = 0;
                for (int i = 0; i < RES.N; i++)
                {
                    //инициализация суммы
                    //инициализация F
                    for (int k = 0; k < RES.Size_Block; k++)
                    {
                        V_SUM.Elem[k] = vectorF.Block[i].Elem[k];
                    }

                    //произведение блоков на старые x

                    for (int j = 0; j < matrixA.N; j++)
                    {
                        //записывается значение ссылки, которая указывает на ij элемент
                        M_Help = matrixA.Block[i][j];
                        V_Help = RES.Block[j];

                        for (int Row = 0; Row < M_Help.M; Row++)
                        {
                            for (int Column = 0; Column < M_Help.N; Column++)
                            {
                                V_SUM.Elem[Row] -= M_Help.Elem[Row][Column] * V_Help.Elem[Column];
                            }
                        }
                    }

                    LU_Solver.LU = matrixA.Block[i][i];
                    //скобка, умноженная на обратный диагональный блок
                    V_SUM = LU_Solver.Start_Solver(LU_Solver.LU, V_SUM);

                    //формируем результат для i-ой компоненты
                    for (int k = 0; k < RES.Size_Block; k++)
                    {
                        double X_NEW = V_SUM.Elem[k];

                        //вычисляем норму
                        Norma_Xnew_Xold += Math.Pow((X_NEW - RES.Block[i].Elem[k]), 2);

                        RES.Block[i].Elem[k] = X_NEW;
                    }
                }

                Norma_Xnew_Xold = Math.Sqrt(Norma_Xnew_Xold);
                IterrationIndex++;

                //с каждой итерацией норма будет уменьшаться
                Console.WriteLine("Iter{0,-10} {1}", IterrationIndex, Norma_Xnew_Xold);
            }while (Norma_Xnew_Xold > Eps && IterrationIndex < MaxIterationCount);


            return(RES);
        }
示例#7
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);
        }
示例#8
0
        //Вычисление числа обусловленности
        public double Cond_Square_Matrix_Parallel()
        {
            if (M != N)
            {
                throw new Exception("Cond_Square_Matrix: matrix doesn't square");
            }

            //решатель СЛАУ
            var LU_Solver = new LU_Decomposition();

            LU_Solver.CreateLU(this.Transpose_Matrix());

            //число допустимых виртуальных ядер
            int Number_Threads = Environment.ProcessorCount;

            //семафор для потоков(используется список)
            var Semaphors = new List <bool>();

            //норма строк (разделяется по потокам)
            var Norma_Row_A  = new double[Number_Threads];
            var Norma_Row_A1 = new double[Number_Threads];

            //вход в параллельную секцию
            //объявление объекта типа делегат
            //для создания объекта в параметрах конструктора передаётся анонимный метод
            var Thread_Solver = new Threads_Solving(Number =>
                                                    //лямбда-выражение
            {
                //строк для отображения матрицы
                //в каждом потоке хранится своя строка матрицы
                var A1 = new Vector(M);
                double S1, S2;

                //индексы указывающие на первую и последнюю строку для потока
                int Begin = N / Number_Threads * Number;
                int End   = Begin + N / Number_Threads;

                //если деление было нецелочисленное, записываем в конец остаток
                if (Number + 1 == Number_Threads)
                {
                    End += N % Number_Threads;
                }

                //решение СЛАУ для End-Begin строк
                for (int i = Begin; i < End; i++)
                {
                    A1.Elem[i] = 1.0;
                    A1         = LU_Solver.Start_Solver(LU_Solver.LU, A1);

                    //нормы S1, S2
                    S1 = 0;
                    S2 = 0;

                    for (int j = 0; j < M; j++)
                    {
                        S1        += Math.Abs(Elem[i][j]);
                        S2        += Math.Abs(A1.Elem[j]);
                        A1.Elem[j] = 0.0;
                    }

                    //определение наибольшей из норм
                    if (Norma_Row_A[Number] < S1)
                    {
                        Norma_Row_A[Number] = S1;
                    }

                    if (Norma_Row_A1[Number] < S2)
                    {
                        Norma_Row_A1[Number] = S2;
                    }
                }

                //сигнал о завершении потока
                Semaphors[Number] = true;
            });

            //отцовский поток вызывает дочерние
            for (int I = 0; I < Number_Threads; I++)
            {
                int Number = I;
                Semaphors.Add(false);

                //пул(очередь) потоков
                ThreadPool.QueueUserWorkItem(Param => Thread_Solver(Number));
            }

            //просмотр списка семафора на наличие незавершённых потоков
            while (Semaphors.Contains(false))
            {
                ;
            }

            for (int i = 1; i < Number_Threads; i++)
            {
                if (Norma_Row_A[0] < Norma_Row_A[i])
                {
                    Norma_Row_A[0] = Norma_Row_A[i];
                }

                if (Norma_Row_A1[0] < Norma_Row_A1[i])
                {
                    Norma_Row_A1[0] = Norma_Row_A1[i];
                }
            }

            return(Norma_Row_A[0] * Norma_Row_A1[0]);
        }