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
34 return GaussSeidel::run(
35 *ctx.Y,
36 *ctx.V,
37 *ctx.delta,
38 *ctx.type_bus,
39 *ctx.P,
40 *ctx.Q,
41 ctx.N,
42 ctx.maxIter,
43 ctx.tolerance,
44 ctx.omega,
45 ctx.iterHistory,
46 ctx.observer
47 );
48}
49
51 const Eigen::MatrixXcd& Y,
52 Eigen::VectorXd& Vmag,
53 Eigen::VectorXd& delta,
54 const Eigen::VectorXi& type_bus,
55 const Eigen::VectorXd& P,
56 const Eigen::VectorXd& Q,
57 int N,
58 int maxIter,
59 double tolerance,
60 double omega,
61 std::vector<std::pair<int, double>>* iterHistory,
62 ISolverObserver* observer
63) {
64 // Store scheduled voltage magnitudes for PV buses
65 Eigen::VectorXd Vmag_sched = Vmag;
66
67 // Initialize complex voltage vector
68 Eigen::VectorXcd V(N);
69 for (int i = 0; i < N; ++i)
70 V(i) = std::polar(Vmag(i), delta(i));
71
72 int iteration = 0;
73 double error = std::numeric_limits<double>::infinity();
74
75 if (omega <= 0.0 || omega >= 2.0) {
76 if (observer) observer->onMessage("Gauss-Seidel", "Invalid input: Relaxation coefficient must be between 0 and 2. Setting Relaxation coefficient to 1.");
77 omega = 1.0;
78 }
79
80 if (observer) {
81 if (omega < 1.0) {
82 observer->onMessage("Gauss-Seidel", "Under-relaxation enabled (omega < 1), this will slow down convergence.");
83 } else if (omega == 1.0) {
84 observer->onMessage("Gauss-Seidel", "Standard Gauss-Seidel enabled (omega = 1).");
85 } else {
86 observer->onMessage("Gauss-Seidel", "Over-relaxation enabled (omega > 1), this will accelerate convergence.");
87 }
88 }
89
90 while (error >= tolerance && iteration < maxIter) {
91 Eigen::VectorXcd dV = Eigen::VectorXcd::Zero(N);
92
93 for (int n = 0; n < N; ++n) {
94 if (type_bus(n) == 1) continue; // Skip slack bus
95
96 std::complex<double> In = Y.row(n) * V;
97
98 if (type_bus(n) == 2) { // PV Bus
99 // Compute Q from current solution (no clamping)
100 double Qn = -std::imag(std::conj(V(n)) * In);
101
102 // GS update maintaining scheduled voltage magnitude
103 std::complex<double> I_excl = In - Y(n, n) * V(n);
104 std::complex<double> V_updated = ((P(n) - std::complex<double>(0, 1) * Qn) / std::conj(V(n)) - I_excl) / Y(n, n);
105 std::complex<double> V_corrected = Vmag_sched(n) * V_updated / std::abs(V_updated);
106 dV(n) = V_corrected - V(n);
107 V(n) = V_corrected;
108
109 } else if (type_bus(n) == 3) { // PQ Bus
110 std::complex<double> I_excl = In - Y(n, n) * V(n);
111 std::complex<double> V_updated = ((P(n) - std::complex<double>(0, 1) * Q(n)) / std::conj(V(n)) - I_excl) / Y(n, n);
112 std::complex<double> V_relaxed = V(n) + omega * (V_updated - V(n));
113 dV(n) = V_relaxed - V(n);
114 V(n) = V_relaxed;
115 }
116 }
117
118 error = dV.norm();
119 iteration++;
120 if (iterHistory) iterHistory->emplace_back(iteration, error);
121 if (observer) observer->onIteration("Gauss-Seidel", iteration, maxIter, error, tolerance);
122 }
123
124 if (iteration >= maxIter) {
125 if (observer) observer->onFinished("Gauss-Seidel", false, iteration, maxIter, error, tolerance);
126 return false;
127 }
128
129 // Extract converged V magnitudes and angles
130 for (int i = 0; i < N; ++i) {
131 Vmag(i) = std::abs(V(i));
132 delta(i) = std::arg(V(i));
133 }
134
135 if (observer) observer->onFinished("Gauss-Seidel", true, iteration, maxIter, error, tolerance);
136
137 return true;
138}
Declaration of the Gauss-Seidel load flow solver for power system analysis.
static bool run(const Eigen::MatrixXcd &Y, Eigen::VectorXd &V, Eigen::VectorXd &delta, const Eigen::VectorXi &type_bus, const Eigen::VectorXd &P, const Eigen::VectorXd &Q, int N, int maxIter=1024, double tolerance=1E-8, double omega=1.0, std::vector< std::pair< int, double > > *iterHistory=nullptr, ISolverObserver *observer=nullptr)
Solves the power flow equations using the Gauss-Seidel iterative method.
Definition GaussSeidel.C:50
bool solve(SolverContext &ctx) override
Run the Gauss-Seidel solver using the given context.
Definition GaussSeidel.C:33
Sink for solver progress/diagnostics (Dependency Inversion / SRP).
Definition ISolver.H:93
virtual void onIteration(const char *solverName, int iter, int maxIter, double error, double tolerance)=0
Called after every iteration with the current error/tolerance.
virtual void onFinished(const char *solverName, bool converged, int iter, int maxIter, double error, double tolerance)=0
Called once after the iteration loop ends (converged or not).
virtual void onMessage(const char *solverName, const char *message)=0
Called for solver-specific diagnostic/warning messages (e.g.
Shared input/output parameters for power-flow solvers.
Definition ISolver.H:49
const Eigen::VectorXd * Q
Scheduled reactive power injections (Qg - Ql).
Definition ISolver.H:65
double tolerance
Convergence tolerance.
Definition ISolver.H:73
Eigen::VectorXd * V
Voltage magnitudes [p.u.].
Definition ISolver.H:56
const Eigen::MatrixXcd * Y
Bus admittance matrix (used by Gauss-Seidel).
Definition ISolver.H:51
const Eigen::VectorXd * P
Scheduled active power injections (Pg - Pl).
Definition ISolver.H:64
int maxIter
Maximum number of iterations.
Definition ISolver.H:72
int N
Total number of buses.
Definition ISolver.H:68
Eigen::VectorXd * delta
Voltage angles [rad].
Definition ISolver.H:57
Eigen::VectorXi * type_bus
Bus type vector (1=Slack, 2=PV, 3=PQ).
Definition ISolver.H:60
class ISolverObserver * observer
Optional injected progress/log observer (DIP); nullptr = silent.
Definition ISolver.H:78
std::vector< std::pair< int, double > > * iterHistory
Optional iteration history sink.
Definition ISolver.H:77
double omega
Relaxation coefficient (Gauss-Seidel only).
Definition ISolver.H:74