deltaFlow
GaussSeidel.C
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Saud Zahir
3 *
4 * This file is part of deltaFlow.
5 *
6 * deltaFlow is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * deltaFlow is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with deltaFlow. If not, see
18 * <https://www.gnu.org/licenses/>.
19 */
20
26#include <cmath>
27#include <complex>
28#include <iostream>
29#include <limits>
30
31#include "GaussSeidel.H"
32#include "Logger.H"
33#include "Progress.H"
34
36 const Eigen::MatrixXcd& Y,
37 Eigen::VectorXd& Vmag,
38 Eigen::VectorXd& delta,
39 const Eigen::VectorXi& type_bus,
40 const Eigen::VectorXd& P,
41 const Eigen::VectorXd& Q,
42 int N,
43 int maxIter,
44 double tolerance,
45 double omega,
46 std::vector<std::pair<int, double>>* iterHistory
47) {
48 // Store scheduled voltage magnitudes for PV buses
49 Eigen::VectorXd Vmag_sched = Vmag;
50
51 // Initialize complex voltage vector
52 Eigen::VectorXcd V(N);
53 for (int i = 0; i < N; ++i)
54 V(i) = std::polar(Vmag(i), delta(i));
55
56 int iteration = 0;
57 double error = std::numeric_limits<double>::infinity();
58
59 if (omega <= 0.0 || omega >= 2.0) {
60 LOG_WARN("Invalid input: Relaxation coefficient must be between 0 and 2.");
61 LOG_DEBUG("Setting Relaxation coefficient to 1.");
62 omega = 1.0;
63 }
64
65 if (omega < 1.0) {
66 LOG_CRITICAL("Under-relaxation enabled (omega < 1), this will slow down convergence.");
67 }
68 else if (omega == 1.0) {
69 LOG_DEBUG("Standard Gauss-Seidel enabled (omega = 1).");
70 }
71 else if (omega > 1.0) {
72 LOG_DEBUG("Over-relaxation enabled (omega > 1), this will accelerate convergence.");
73 }
74
75 LOG_DEBUG("Relaxation Coefficient :: {}", omega);
76
77 while (error >= tolerance && iteration < maxIter) {
78 Eigen::VectorXcd dV = Eigen::VectorXcd::Zero(N);
79
80 for (int n = 0; n < N; ++n) {
81 if (type_bus(n) == 1) continue; // Skip slack bus
82
83 std::complex<double> In = Y.row(n) * V;
84
85 if (type_bus(n) == 2) { // PV Bus
86 // Compute Q from current solution (no clamping)
87 double Qn = -std::imag(std::conj(V(n)) * In);
88
89 // GS update maintaining scheduled voltage magnitude
90 std::complex<double> I_excl = In - Y(n, n) * V(n);
91 std::complex<double> V_updated = ((P(n) - std::complex<double>(0, 1) * Qn) / std::conj(V(n)) - I_excl) / Y(n, n);
92 std::complex<double> V_corrected = Vmag_sched(n) * V_updated / std::abs(V_updated);
93 dV(n) = V_corrected - V(n);
94 V(n) = V_corrected;
95
96 } else if (type_bus(n) == 3) { // PQ Bus
97 std::complex<double> I_excl = In - Y(n, n) * V(n);
98 std::complex<double> V_updated = ((P(n) - std::complex<double>(0, 1) * Q(n)) / std::conj(V(n)) - I_excl) / Y(n, n);
99 std::complex<double> V_relaxed = V(n) + omega * (V_updated - V(n));
100 dV(n) = V_relaxed - V(n);
101 V(n) = V_relaxed;
102 }
103 }
104
105 error = dV.norm();
106 iteration++;
107 if (iterHistory) iterHistory->emplace_back(iteration, error);
108 printIterationProgress("Gauss-Seidel", iteration, maxIter, error, tolerance);
109 }
110
111 if (iteration >= maxIter) {
112 printConvergenceStatus("Gauss-Seidel", false, iteration, maxIter, error, tolerance);
113 LOG_WARN("Gauss-Seidel did not converge within max iterations ({}).", maxIter);
114 LOG_DEBUG("Final error norm was {:.6e}, tolerance is {:.6e}.", error, tolerance);
115 return false;
116 }
117
118 // Extract converged V magnitudes and angles
119 for (int i = 0; i < N; ++i) {
120 Vmag(i) = std::abs(V(i));
121 delta(i) = std::arg(V(i));
122 }
123
124 printConvergenceStatus("Gauss-Seidel", true, iteration, maxIter, error, tolerance);
125 LOG_DEBUG("Gauss-Seidel converged in {} iterations with error norm {:.6e}.", iteration, error);
126
127 return true;
128}
@ GaussSeidel
Gauss-Seidel iterative method.
Declaration of the Gauss-Seidel load flow solver for power system analysis.
Logger utilities for deltaFlow, providing logging macros and a singleton Logger class.
#define LOG_WARN(msg,...)
Macro for logging a warning-level message.
Definition Logger.H:87
#define LOG_DEBUG(msg,...)
Macro for logging a debug-level message.
Definition Logger.H:85
#define LOG_CRITICAL(msg,...)
Macro for logging a critical-level message.
Definition Logger.H:89
Progress bar for iterative solvers.
void printIterationProgress(const std::string &solver, int iter, int maxIter, double error, double tol, int barWidth=50)
Print an iteration progress line for a solver.
Definition Progress.H:50
void printConvergenceStatus(const std::string &solver, bool converged, int iter, int maxIter, double error, double tol, int barWidth=50)
Print the final convergence status line.
Definition Progress.H:100