public override Vector UtMult(Vector x, bool UseDiagonal) { if (n == x.Size) { Vector result = new Vector(n); result.Nullify(); if (UseDiagonal) { result[0] = di[0] * x[0]; // Обработка части al, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку { for (int j = bandWidth - i; j < bandWidth; j++) result[i] += au[i][j] * x[j + i - bandWidth]; result[i] += di[i] * x[i]; } //Обработка без 0 for (int i = bandWidth; i < n; i++) { for (int j = i - bandWidth; j < i; j++) result[i] += au[i][j - i + bandWidth] * x[j]; result[i] += di[i] * x[i]; } } else { // Обработка части al, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку for (int j = bandWidth - i; j < bandWidth; j++) result[i] += au[i][j] * x[j + i - bandWidth]; //Обработка без 0 for (int i = bandWidth; i < n; i++) for (int j = i - bandWidth; j < i; j++) result[i] += au[i][j - i + bandWidth] * x[j]; } return result; } else throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при умножении верхнего(T) треугольника"); }
public override Vector TMultiply(Vector x) { Vector result = new Vector(n); result.Nullify(); if (n == x.Size) { // Верхний треугольник // Обработка части au, где есть 0 for (int i = 1; i < bandWidth; i++)// обрабатываем i строку for (int j = bandWidth - i; j < bandWidth; j++) result[i] += au[i][j] * x[j + i - bandWidth]; //Обработка без 0 for (int i = bandWidth; i < n; i++) for (int j = i - bandWidth; j < i; j++) result[i] += au[i][j - i + bandWidth] * x[j]; //Диагональ for (int i = 0; i < n; i++) result[i] += di[i] * x[i]; //Нижний треугольник for (int j = 0; j < bandWidth; j++) { for (int i = bandWidth - j; i < n; i++) result[i - bandWidth + j] += al[i][j] * x[i]; } return result; } throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при умножении(T)"); }
public override Vector UMult(Vector x, bool UseDiagonal) { if (n == x.Size) { Vector result = new Vector(n); result.Nullify(); for (int j = 0; j < bandWidth; j++) { for (int i = bandWidth - j; i < n; i++) result[i - bandWidth + j] += au[i][j] * x[i]; } if (UseDiagonal) { for (int i = 0; i < n; i++) result[i] += di[i] * x[i]; } return result; } else throw new Exception("Ленточный формат: Несовпадение размерностей матрицы и вектора при умножении верхнего треугольника"); }
public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs) { GMRESParameters GMRESParameters = solverParametrs as GMRESParameters; if (GMRESParameters != null) { Vector[] V, H; Vector residual, x, d, z, w, tmp; bool continueCalculations; double epsilon = GMRESParameters.Epsilon; int m = GMRESParameters.M; int maxIterations = GMRESParameters.MaxIterations; int n = rightPart.Size; x = initialSolution; residual = rightPart - matrix.SourceMatrix.Multiply(x); residual = matrix.SSolve(residual); double rightPartNorm = matrix.SSolve(rightPart).Norm(); double residualNorm = residual.Norm(); if (System.Double.IsInfinity(residualNorm / rightPartNorm)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES."); return x; } if (System.Double.IsNaN(residualNorm / rightPartNorm)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES."); return x; } x = matrix.QMultiply(initialSolution); V = new Vector[m]; for (int i = 0; i < m; i++) V[i] = new Vector(n); H = new Vector[m]; for (int i = 0; i < m; i++) H[i] = new Vector(m + 1); d = new Vector(m + 1); for (int k = 1; k <= maxIterations && residualNorm / rightPartNorm > epsilon; k++) { d.Nullify(); V[0] = residual * (1.0 / residualNorm); continueCalculations = true; for (int j = 1; j <= m && continueCalculations; j++) { tmp = matrix.QSolve(V[j - 1]); w = matrix.SSolve(matrix.SourceMatrix.Multiply(tmp)); for (int l = 1; l <= j; l++) { H[j - 1][l - 1] = V[l - 1] * w; w = w - V[l - 1] * H[j - 1][l - 1]; } H[j - 1][j] = w.Norm(); if (Math.Abs(H[j - 1][j]) < 1e-10) { m = j; continueCalculations = false; } else { if(j != m) V[j] = w * (1.0 / H[j - 1][j]); } } d[0] = residualNorm; z = solveMinSqrProblem(d, H, m); x = x + multiplyMatrixVector(z, V); tmp = rightPart - matrix.SourceMatrix.Multiply(matrix.QSolve(x)); residual = matrix.SSolve(tmp); residualNorm = residual.Norm(); if (System.Double.IsInfinity(residualNorm / rightPartNorm)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by GMRES."); return x; } if (System.Double.IsNaN(residualNorm / rightPartNorm)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by GMRES."); return x; } solverLogger.AddIterationInfo(k, residualNorm / rightPartNorm); } return matrix.QSolve(x); } else { logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in GMRES"); throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in GMRES"); } }
Vector multiplyMatrixVector(Vector vector, Vector[] matrix) { int n_lines = matrix[0].Size; int n_columns = matrix.Length; Vector result = new Vector(n_lines); result.Nullify(); if(vector.Size == n_columns) { for (int j = 0; j < n_columns; j++) for (int i = 0; i < n_lines; i++) result[i] += matrix[j][i] * vector[j]; } else throw new Exception("GMRES: Несовпадение длины вектора и числа столбцов матрицы"); return result; }
public override Vector UtMult(Vector x, bool UseDiagonal) { if (di.Length == x.Size) { Vector result = new Vector(di.Length); result.Nullify(); for (int j = 0; j < shift_u.Length; j++) for (int i = shift_u[j]; i < di.Length; i++) result[i] += au[i][j] * x[i - shift_u[j]]; if (UseDiagonal) for (int i = 0; i < di.Length; i++) result[i] += di[i] * x[i]; return result; } else throw new Exception("Диагональный формат: Несовпадение размерностей матрицы и вектора в умножении верхнего(T) треугольника"); }
public override Vector TMultiply(Vector x) { if (di.Length == x.Size) { Vector result = new Vector(di.Length); result.Nullify(); // Верхний треугольник for (int j = 0; j < shift_u.Length; j++) for (int i = shift_u[j]; i < di.Length; i++) result[i] += au[i][j] * x[i - shift_u[j]]; // Диагональ for (int i = 0; i < di.Length; i++) result[i] += di[i] * x[i]; // Нижний треугольник for (int j = 0; j < shift_l.Length; j++) for (int i = shift_l[j]; i < di.Length; i++) result[i - shift_l[j]] += al[j][i] * x[i]; return result; } else throw new Exception("Диагональный формат: Несовпадение размерностей матрицы и вектора в умножении (T)"); }
public override Vector Solve(IPreconditioner matrix, Vector rightPart, Vector initialSolution, ILogger logger, ISolverLogger solverLogger, ISolverParametrs solverParametrs) { BCGStabParametrs ConGradParametrs = solverParametrs as BCGStabParametrs; if (ConGradParametrs == null) { logger.Error("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in BSGStab"); throw new Exception("Incorrect " + solverParametrs.GetType().Name.ToString() + " as a SolverParametrs in BSGSTab"); } else { int oIter = 0; double nPi, oPi, alpha, w, oNev, bNev, betta; oPi = alpha = w = 1; int size = rightPart.Size; Vector x, r, rTab, s, t, z, sqt, y; Vector v = new Vector(size); Vector p = new Vector(size); v.Nullify(); p.Nullify(); x = initialSolution; r = rightPart - matrix.SourceMatrix.Multiply(x); rTab = r; bNev = rightPart.Norm(); oNev = r.Norm() / bNev; solverLogger.AddIterationInfo(oIter, oNev);//logger if (System.Double.IsInfinity(oNev)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by BSG Stab."); return x; } if (System.Double.IsNaN(oNev)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by BSG Stab."); return x; } while (oIter < ConGradParametrs.MaxIterations && oNev > ConGradParametrs.Epsilon) { nPi = rTab * r; betta = (nPi / oPi) * (alpha / w); p = r + (p - v * w) * betta; y= matrix.QSolve(matrix.SSolve(p)); v = matrix.SourceMatrix.Multiply(y); alpha = nPi / (rTab * v); x = x + y * alpha;//УТОЧНИТЬ!!!!!!!!!!!!!!! s = r - v * alpha; if (s.Norm() / bNev < ConGradParametrs.Epsilon) return x; z = matrix.QSolve(matrix.SSolve(s)); t = matrix.SourceMatrix.Multiply(z); sqt = matrix.QSolve(matrix.SSolve(t)); w = (z * sqt) / (sqt * sqt); x = x + z * w;//УТОЧНИТЬ!!!!!!!!!!!!!!!!!!! r = s - t * w; oPi = nPi; oIter++; oNev = r.Norm() / bNev; if (System.Double.IsInfinity(oNev)) { logger.Error("Residual is infinity. It is impossible to solve this SLAE by BSG Stab."); return x; } if (System.Double.IsNaN(oNev)) { logger.Error("Residual is NaN. It is impossible to solve this SLAE by BSG Stab."); return x; } solverLogger.AddIterationInfo(oIter, oNev);//logger } return x; } }