public static MatrixComplex CreateUnitMatrix(int dimension) { if (dimension < 1) { throw new ArgumentException("UnitMatrix cannot be created. Check dimension."); } else { MatrixComplex UnitMatrix = new MatrixComplex(dimension, dimension); for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { if (i == j) { UnitMatrix.matrix[i, j] = new Complex(1.0, 0.0); } else { UnitMatrix.matrix[i, j] = new Complex(0.0, 0.0); } } } return(UnitMatrix); } }
public static MatrixComplex CopyMatrix(MatrixComplex MatrixForCopy) { MatrixComplex NewMatrix = new MatrixComplex(MatrixForCopy.GetRows, MatrixForCopy.GetColumns); for (int i = 0; i < NewMatrix.GetRows; i++) { for (int j = 0; j < NewMatrix.GetColumns; j++) { NewMatrix.matrix[i, j] = new Complex(MatrixForCopy.matrix[i, j]); } } return(NewMatrix); }
public static MatrixComplex operator *(MatrixComplex mat, Complex factor) { MatrixComplex result = CopyMatrix(mat);; for (int i = 0; i < mat.GetRows; i++) { for (int j = 0; j < mat.GetColumns; j++) { result.matrix[i, j] = mat.matrix[i, j] * factor; } } return(result); }
//Деление элементов матрицы на число public static MatrixComplex operator /(MatrixComplex mat, double factor) { MatrixComplex result = new MatrixComplex(mat.GetRows, mat.GetColumns); for (int i = 0; i < mat.GetRows; i++) { for (int j = 0; j < mat.GetColumns; j++) { result.matrix[i, j] = mat.matrix[i, j] / factor; } } return(result); }
public static MatrixComplex NodesVoltageInitialAprox(Node[] nodesArray, int baseNumber) { MatrixComplex InitialAprox = new MatrixComplex(nodesArray.Length - 1, 1); int k = 0; for (int i = 0; i < nodesArray.Length; i++) { if (i == baseNumber) { continue; } InitialAprox.matrix[k, 0] = new Complex(nodesArray[i].NodeNominalVoltage, 0); k++; } return(InitialAprox); }
public static MatrixComplex GetLoadMatrix(Node[] nodesArray, int baseNumber) { //Console.Write("GetLoadMatrix..."); MatrixComplex LoadMatrix = new MatrixComplex(nodesArray.Length - 1, 1); int k = 0; for (int i = 0; i < nodesArray.Length; i++) { if (i == baseNumber) { continue; } LoadMatrix.matrix[k, 0] = nodesArray[i].NodeLoad - nodesArray[i].NodeGeneration; k++; } //Console.WriteLine("Success!"); return(LoadMatrix); }
return(JointMatrix); //Почему не на матрицу перестановок? static int FindNotZero(MatrixComplex GaussMatrix, int currentRow, int currentColumn, bool direction) { //direction = false(down); direction = true(up) bool IsFound = false; int row = currentRow; while (!IsFound) { if (GaussMatrix.matrix[row, currentColumn] == new Complex(0, 0)) { if (direction) { if (row == 0) { Console.WriteLine("Обнаружена сингулярность"); break; } else { row--; } } else { if (row == GaussMatrix.GetRows - 1) { Console.WriteLine("Обнаружена сингулярность"); break; } else { row++; } } } else { IsFound = true; } } return(row); }
public static MatrixComplex CreateDiagMatrix(MatrixComplex VectorMatrix) { if (VectorMatrix.GetRows > VectorMatrix.GetColumns) { MatrixComplex DiagMatrix = new MatrixComplex(VectorMatrix.GetRows, VectorMatrix.GetRows); for (int i = 0; i < DiagMatrix.GetRows; i++) { for (int j = 0; j < DiagMatrix.GetColumns; j++) { if (i == j) { DiagMatrix.matrix[i, j] = VectorMatrix.matrix[i, 0]; } else { DiagMatrix.matrix[i, j] = new Complex(0.0, 0.0); } } } return(DiagMatrix); } else { MatrixComplex DiagMatrix = new MatrixComplex(VectorMatrix.GetColumns, VectorMatrix.GetColumns); for (int i = 0; i < DiagMatrix.GetRows; i++) { for (int j = 0; j < DiagMatrix.GetColumns; j++) { if (i == j) { DiagMatrix.matrix[i, j] = VectorMatrix.matrix[0, i]; } else { DiagMatrix.matrix[i, j] = new Complex(0.0, 0.0); } } } return(DiagMatrix); } }
//Вычитание матриц public static MatrixComplex operator -(MatrixComplex mat1, MatrixComplex mat2) { if ((mat1.GetRows != mat2.GetRows) | (mat1.GetColumns != mat2.GetColumns)) { throw new ArgumentException("Matrices can not be deducted"); } else { MatrixComplex result = new MatrixComplex(mat1.GetRows, mat1.GetColumns); for (int i = 0; i < mat1.GetRows; i++) { for (int j = 0; j < mat1.GetColumns; j++) { result.matrix[i, j] = new Complex(0, 0); result.matrix[i, j] = mat1.matrix[i, j] - mat2.matrix[i, j]; } } return(result); } }
public static MatrixComplex CalcJacobiMatrix(MatrixComplex ConductivityMatrix, MatrixComplex baseConductivity, MatrixComplex NodesVoltage, MatrixComplex diagConjugateNodesVoltage, Complex baseVoltage) { MatrixComplex JacobiMatrix = new MatrixComplex(ConductivityMatrix.GetRows, ConductivityMatrix.GetColumns); for (int i = 0; i < JacobiMatrix.GetRows; i++) { for (int j = 0; j < JacobiMatrix.GetColumns; j++) { if (i == j) //Диагональные элементы { JacobiMatrix.matrix[i, j] = diagConjugateNodesVoltage.matrix[i, j] * ConductivityMatrix.matrix[i, j]; } else //Недиагональные элементы { JacobiMatrix.matrix[i, j] = diagConjugateNodesVoltage.matrix[i, i] * ConductivityMatrix.matrix[i, j]; } } } return(JacobiMatrix); }
public static MatrixComplex GetConductivityMatrix(Node[] nodesArray, Line[] linesArray, int numberNodes, ref MatrixComplex baseConductivity, ref int baseNumber) { //Console.Write("GetConductivityMatrix..."); MatrixComplex ConductivityMatrix = new MatrixComplex(numberNodes, numberNodes); for (int i = 0; i < numberNodes; i++) { if (nodesArray[i].NodeType == "База") { baseNumber = i; } for (int j = 0; j < numberNodes; j++) { ConductivityMatrix.matrix[i, j] = new Complex(); if (i == j) { ConductivityMatrix.matrix[i, j] = (-1) * (FindAllInclusions(nodesArray, linesArray, i)) - nodesArray[i].NodeConductivity; } else { ConductivityMatrix.matrix[i, j] = FindBranches(nodesArray, linesArray, i, j); } } } Console.WriteLine("Полная матрица проводимостей:\n" + ConductivityMatrix); int k = 0; for (int i = 0; i < numberNodes; i++) { if (i == baseNumber) { continue; } baseConductivity.matrix[k, 0] = ConductivityMatrix.matrix[i, baseNumber]; k++; } //Console.WriteLine("Success!"); return(MatrixComplex.CreateMinor(ConductivityMatrix, baseNumber, baseNumber)); }
public static void UseSolverComplex(int numberNodes, int step, int numberComutations, int baseNumber, Line[] linesArray, Node[] nodesArray, Stopwatch swWholeProgram, Stopwatch sw, LinkWithExcel link) { #region ComplexCalc sw.Start(); MatrixComplex baseConductivityC = new MatrixComplex(numberNodes - 1); MatrixComplex ConductivityMatrixC = SolverComplex.GetConductivityMatrix(nodesArray, linesArray, numberNodes, ref baseConductivityC, ref baseNumber); MatrixComplex LoadMatrixC = SolverComplex.GetLoadMatrix(nodesArray, baseNumber); MatrixComplex NodesVoltageC = SolverComplex.NodesVoltageInitialAprox(nodesArray, baseNumber); Complex baseVoltageC = new Complex(nodesArray[baseNumber].NodeNominalVoltage, 0); sw.Stop(); Console.WriteLine("Матрица проводимостей:\n" + ConductivityMatrixC); Console.WriteLine("Вектор проводимостей базисного узла\n" + baseConductivityC); Console.WriteLine("Вектор напряжений\n" + NodesVoltageC); Console.WriteLine("Напряжение базисного узла: " + baseVoltageC + "\n"); Console.WriteLine("Вектор мощностей:\n" + LoadMatrixC + "\n"); Console.WriteLine("Параметры схемы загружены за " + sw.ElapsedMilliseconds + " мс\n"); sw.Reset(); double AccuracyC = 0.1; //МВт int stepC; sw.Reset(); sw.Start(); MatrixComplex EstimatedNodesVoltageC = SolverComplex.SolveEquation(NodesVoltageC, ConductivityMatrixC, baseConductivityC, LoadMatrixC, baseVoltageC, AccuracyC, out stepC); sw.Stop(); Console.WriteLine($"Итераций расчета: {stepC}\nВремя расчета: {sw.ElapsedMilliseconds} мс\nТочность: {AccuracyC} МВт\n\n" + EstimatedNodesVoltageC); Console.WriteLine(EstimatedNodesVoltageC.matrix[0, 0].Module + "<" + EstimatedNodesVoltageC.matrix[0, 0].Angle); Console.WriteLine(EstimatedNodesVoltageC.matrix[1, 0].Module + "<" + EstimatedNodesVoltageC.matrix[1, 0].Angle); #endregion }
//Перемножение матриц public static MatrixComplex operator *(MatrixComplex mat1, MatrixComplex mat2) { if (mat1.GetColumns != mat2.GetRows) { throw new ArgumentException("Matrices can not be multiplied"); } else { MatrixComplex result = new MatrixComplex(mat1.GetRows, mat2.GetColumns); for (int i = 0; i < mat1.GetRows; i++) { for (int j = 0; j < mat2.GetColumns; j++) { result.matrix[i, j] = new Complex(0, 0); for (int k = 0; k < mat1.GetColumns; k++) { result.matrix[i, j] += mat1.matrix[i, k] * mat2.matrix[k, j]; } } } return(result); } }
public static MatrixComplex CreateInvertedMatrixGauss(MatrixComplex mat) { //Console.WriteLine("CreateInvertedMatrixGauss..."); if (mat.GetRows != mat.GetColumns) { throw new ArgumentException("MatrixComplex cannot be inverted"); } else { MatrixComplex GaussMatrix = CopyMatrix(mat);; MatrixComplex JointMatrix = CreateUnitMatrix(mat.GetRows); MatrixComplex TranspositionMatrix = CreateUnitMatrix(mat.GetRows); Complex zero = new Complex(0.0, 0.0); //Прямой ход for (int j = 0; j < GaussMatrix.GetColumns; j++) { for (int i = j; i < GaussMatrix.GetRows; i++) { if (GaussMatrix.matrix[j, j] == zero) { int newRow = FindNotZero(GaussMatrix, j, j, false); SwapRows(GaussMatrix, i, newRow); SwapRows(JointMatrix, i, newRow); SwapRows(TranspositionMatrix, i, newRow); } if (i == j) { continue; } SummRows(JointMatrix, j, i, (-1.0) * GaussMatrix.matrix[i, j] / GaussMatrix.matrix[j, j]); SummRows(GaussMatrix, j, i, (-1.0) * GaussMatrix.matrix[i, j] / GaussMatrix.matrix[j, j]); } } //Обратный ход for (int j = GaussMatrix.GetColumns - 1; j > -1; j--) { for (int i = j; i > -1; i--) { if (GaussMatrix.matrix[j, j] == zero) { int newRow = FindNotZero(GaussMatrix, j, j, true); SwapRows(GaussMatrix, i, newRow); SwapRows(JointMatrix, i, newRow); SwapRows(TranspositionMatrix, i, newRow); } if (i == j) { continue; } SummRows(JointMatrix, j, i, (-1.0) * GaussMatrix.matrix[i, j] / GaussMatrix.matrix[j, j]); SummRows(GaussMatrix, j, i, (-1.0) * GaussMatrix.matrix[i, j] / GaussMatrix.matrix[j, j]); } } for (int i = 0; i < GaussMatrix.GetRows; i++) { MultiplyRow(JointMatrix, i, GaussMatrix.matrix[i, i]); MultiplyRow(GaussMatrix, i, GaussMatrix.matrix[i, i]); } return(JointMatrix); //Почему не на матрицу перестановок?
public static MatrixComplex SolveEquation(MatrixComplex NodesVoltage, MatrixComplex ConductivityMatrixC, MatrixComplex baseConductivityC, MatrixComplex LoadMatrixC, Complex baseVoltage, double Accuracy, out int step) { int r = NodesVoltage.GetRows; int c = NodesVoltage.GetColumns; MatrixComplex diagNodesVoltage = new MatrixComplex(r, r); //Create diagonal nodes voltage matrix MatrixComplex ConjLoadMatrix = MatrixComplex.ConjugateMatrixElements(LoadMatrixC); //Create matrix with conjugated voltages MatrixComplex ConjNodesVoltage = MatrixComplex.ConjugateMatrixElements(NodesVoltage); MatrixComplex PowerMismatch = new MatrixComplex(r, c); MatrixComplex PowerMismatch2 = new MatrixComplex(r, c); bool AccuracyIsReached = false; double EuqlidianNorm = 0; double EuqlidianNormN_0; int counter = -1; step = 0; while (!AccuracyIsReached) { EuqlidianNormN_0 = EuqlidianNorm; //Метод Зейделя for (int i = 0; i < NodesVoltage.GetRows; i++) { NodesVoltage.matrix[i, 0] = ConjLoadMatrix.matrix[i, 0] / ConjNodesVoltage.matrix[i, 0] - baseConductivityC.matrix[i, 0] * baseVoltage; for (int j = 0; j < NodesVoltage.GetRows; j++) { if (j == i) { continue; } NodesVoltage.matrix[i, 0] -= NodesVoltage.matrix[j, 0] * ConductivityMatrixC.matrix[i, j]; } NodesVoltage.matrix[i, 0] = NodesVoltage.matrix[i, 0] / ConductivityMatrixC.matrix[i, i]; } ConjNodesVoltage = MatrixComplex.ConjugateMatrixElements(NodesVoltage); step++; for (int i = 0; i < NodesVoltage.GetRows; i++) { PowerMismatch.matrix[i, 0] = baseConductivityC.matrix[i, 0] * baseVoltage; for (int j = 0; j < NodesVoltage.GetRows; j++) { PowerMismatch.matrix[i, 0] += ConductivityMatrixC.matrix[i, j] * NodesVoltage.matrix[j, 0]; } PowerMismatch.matrix[i, 0] *= ConjNodesVoltage.matrix[i, 0]; PowerMismatch.matrix[i, 0] -= ConjLoadMatrix.matrix[i, 0]; } EuqlidianNorm = Math.Abs(PowerMismatch.matrix[0, 0].Real); for (int i = 1; i < r; i++) { if (EuqlidianNorm < Math.Abs(PowerMismatch.matrix[i, 0].Real)) { EuqlidianNorm = Math.Abs(PowerMismatch.matrix[i, 0].Real); } } if (EuqlidianNorm < Accuracy) { AccuracyIsReached = true; } if (EuqlidianNormN_0 < EuqlidianNorm) { counter++; } if (counter > 50) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Режим расходится, необходимо введение в допустимую область"); Console.ResetColor(); return(NodesVoltage); } if (step >= 500) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Расчет завершился, достигнуто максимальное количество итераций"); Console.ResetColor(); return(NodesVoltage); } } return(NodesVoltage); }