deltaFlow
Qlim.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 <limits>
28#include <string>
29#include <vector>
30
31#include <fmt/core.h>
32
33#include "Qlim.H"
34#include "Data.H"
35
37 const Eigen::VectorXd& V,
38 const Eigen::VectorXd& delta,
39 Eigen::VectorXi& type_bus,
40 const Eigen::MatrixXd& G,
41 const Eigen::MatrixXd& B,
42 BusData& busData,
43 const std::vector<int>& pv_bus_id,
44 int n_bus,
45 ISolverObserver* observer
46) {
47 // Q-limits: zero means no limit, using +/-inf
48 Eigen::VectorXd Qmax = busData.Qgmax;
49 Eigen::VectorXd Qmin = busData.Qgmin;
50
51 for (int i = 0; i < n_bus; ++i) {
52 if (Qmax(i) == 0.0) Qmax(i) = std::numeric_limits<double>::infinity();
53 if (Qmin(i) == 0.0) Qmin(i) = -std::numeric_limits<double>::infinity();
54 }
55
56 // Compute reactive power Q at each bus with converged V and delta
57 Eigen::VectorXd Q = Eigen::VectorXd::Zero(n_bus);
58 for (int i = 0; i < n_bus; ++i) {
59 for (int j = 0; j < n_bus; ++j) {
60 double dij = delta(i) - delta(j);
61 Q(i) += V(i) * V(j) * (G(i, j) * std::sin(dij) - B(i, j) * std::cos(dij));
62 }
63 }
64
65 // Qg = Q_calc + Ql (all in p.u.)
66 Eigen::VectorXd Qg = Q + busData.Ql;
67
68 // Check Q-limits only for PV buses
69 bool qlim_hit = false;
70
71 for (int idx : pv_bus_id) {
72 if (Qg(idx) > Qmax(idx)) {
73 type_bus(idx) = 3; // PV to PQ
74 busData.Qg(idx) = Qmax(idx); // Fix Q at limit for next solver run
75 qlim_hit = true;
76 if (observer) {
77 std::string msg = fmt::format("Q-limit (max) hit at bus {} : Qg = {:.4f} > Qmax = {:.4f}", idx + 1, Qg(idx), Qmax(idx));
78 observer->onMessage("Qlim", msg.c_str());
79 }
80 } else if (Qg(idx) < Qmin(idx)) {
81 type_bus(idx) = 3; // PV to PQ
82 busData.Qg(idx) = Qmin(idx); // Fix Q at limit for next solver run
83 qlim_hit = true;
84 if (observer) {
85 std::string msg = fmt::format("Q-limit (min) hit at bus {} : Qg = {:.4f} < Qmin = {:.4f}", idx + 1, Qg(idx), Qmin(idx));
86 observer->onMessage("Qlim", msg.c_str());
87 }
88 }
89 }
90
91 if (!qlim_hit && observer) {
92 observer->onMessage("Qlim", "Power flow converged without hitting Q-limits.");
93 }
94
95 return qlim_hit;
96}
Data structures and utility functions for reading and displaying bus and branch data in power system ...
Reactive power limit (Q-limit) checking for PV buses.
Sink for solver progress/diagnostics (Dependency Inversion / SRP).
Definition ISolver.H:93
virtual void onMessage(const char *solverName, const char *message)=0
Called for solver-specific diagnostic/warning messages (e.g.
static bool check(const Eigen::VectorXd &V, const Eigen::VectorXd &delta, Eigen::VectorXi &type_bus, const Eigen::MatrixXd &G, const Eigen::MatrixXd &B, BusData &busData, const std::vector< int > &pv_bus_id, int n_bus, ISolverObserver *observer=nullptr)
Checks reactive power limits on PV buses after solver convergence.
Definition Qlim.C:36
Contains all relevant data for each bus in the power system.
Definition Data.H:55
Eigen::VectorXd Ql
Reactive power load [MVAr or p.u.].
Definition Data.H:65
Eigen::VectorXd Qgmax
Max reactive power generation [MVAr or p.u.].
Definition Data.H:66
Eigen::VectorXd Qgmin
Min reactive power generation [MVAr or p.u.].
Definition Data.H:67
Eigen::VectorXd Qg
Reactive power generation [MVAr or p.u.].
Definition Data.H:63