Power System Platform  2026w11a-beta
Loading...
Searching...
No Matches
PowerQuality Class Reference

Responsible for the power quality calculations. More...

#include <PowerQuality.h>

Inheritance diagram for PowerQuality:
Collaboration diagram for PowerQuality:

Classes

struct  HarmonicYbus
 

Public Member Functions

 PowerQuality (std::vector< Element * > elementList)
 
virtual wxString GetErrorMessage ()
 
virtual void CalculateHarmonicYbusList (double systemPowerBase=100e6, HarmLoadConnection loadConnection=HarmLoadConnection::PARALLEL)
 
virtual void CalculateHarmonicYbus (std::vector< std::vector< std::complex< double > > > &yBus, double systemPowerBase, double order, bool ignoreTransformerConnection=false, HarmLoadConnection loadConnection=HarmLoadConnection::PARALLEL)
 
virtual bool CalculateDistortions (double systemPowerBase=100e6, HarmLoadConnection loadConnection=HarmLoadConnection::PARALLEL)
 
virtual bool CalculateFrequencyResponse (double systemFreq=60.0, double initFreq=0.0, double endFreq=1500.0, double stepFreq=1.0, int injBusNumber=0, double systemPowerBase=100e6, HarmLoadConnection loadConnection=HarmLoadConnection::PARALLEL)
 
virtual std::vector< double > GetHarmonicOrdersList ()
 
virtual std::vector< double > GetFrequencies ()
 
- Public Member Functions inherited from ElectricCalculation
 ElectricCalculation ()
 Constructor.
 
 ~ElectricCalculation ()
 Destructor.
 
virtual void GetElementsFromList (std::vector< Element * > elementList)
 Separate the power elements from a generic list.
 
virtual bool GetYBus (std::vector< std::vector< std::complex< double > > > &yBus, double systemPowerBase, YBusSequence sequence=POSITIVE_SEQ, bool includeSyncMachines=false, bool allLoadsAsImpedances=false, bool usePowerFlowVoltagesOnImpedances=false)
 Get the admittance matrix from the list of elements (use GetElementsFromList first).
 
virtual bool InvertMatrix (std::vector< std::vector< std::complex< double > > > matrix, std::vector< std::vector< std::complex< double > > > &inverse)
 Invert a matrix.
 
virtual void UpdateElementsPowerFlow (std::vector< std::complex< double > > voltage, std::vector< std::complex< double > > power, std::vector< BusType > busType, std::vector< ReactiveLimits > reactiveLimit, double systemPowerBase)
 Update the elements after the power flow calculation.
 
void ABCtoDQ0 (std::complex< double > complexValue, double angle, double &dValue, double &qValue)
 Convert a complex phasor in ABC representation to DQ components.
 
void DQ0toABC (double dValue, double qValue, double angle, std::complex< double > &complexValue)
 Convert DQ components to a complex phasor in ABC representation.
 
std::vector< std::complex< double > > GaussianElimination (std::vector< std::vector< std::complex< double > > > matrix, std::vector< std::complex< double > > array)
 Solve a linear system using Gaussian elimination (complex version).
 
std::vector< double > GaussianElimination (std::vector< std::vector< double > > matrix, std::vector< double > array)
 Solve a linear system using Gaussian elimination (real version).
 
Machines::SyncMachineModel GetMachineModel (SyncGenerator *generator)
 Get the synchronous machine model used by the generator based on user-defined parameters.
 
std::vector< std::complex< double > > ComplexMatrixTimesVector (std::vector< std::vector< std::complex< double > > > matrix, std::vector< std::complex< double > > vector)
 Multiply a complex matrix by a complex vector.
 
void GetLUDecomposition (std::vector< std::vector< std::complex< double > > > matrix, std::vector< std::vector< std::complex< double > > > &matrixL, std::vector< std::vector< std::complex< double > > > &matrixU)
 Compute the LU decomposition of a matrix.
 
std::vector< std::complex< double > > LUEvaluate (std::vector< std::vector< std::complex< double > > > u, std::vector< std::vector< std::complex< double > > > l, std::vector< std::complex< double > > b)
 Solve a linear system using LU decomposition.
 
bool GetParentBus (Element *childElement, Bus *&parentBus)
 Get the parent bus of a given shunt element.
 
bool GetParentBus (Element *childElement, Bus *&parentBus1, Bus *&parentBus2)
 Get the parent buses of a two-terminal element (branch).
 
bool CalculateEMTElementsAdmittance (const double &basePower, wxString &errorMsg)
 Calculate the admittance of EMT elements.
 
bool CalculateEMTElementsPower (const double &basePower, wxString &errorMsg, bool updateCurrent=true)
 Calculate the power of EMT elements.
 
double CalculateEMTPowerError (const std::vector< std::complex< double > > &voltage, std::vector< std::complex< double > > &power, const double &basePower, wxString &errorMsg)
 Calculate the power mismatch error for EMT simulation.
 
const std::vector< PowerElement * > GetPowerElementList () const
 Get the power elements of the system (use GetElementsFromList first).
 
const std::vector< Bus * > GetBusList () const
 Get the buses of the system (use GetElementsFromList first).
 
const std::vector< Capacitor * > GetCapacitorList () const
 Get the capacitors of the system (use GetElementsFromList first).
 
const std::vector< IndMotor * > GetIndMotorList () const
 Get the induction motors of the system (use GetElementsFromList first).
 
const std::vector< Inductor * > GetInductorList () const
 Get the inductors of the system (use GetElementsFromList first).
 
const std::vector< Line * > GetLineList () const
 Get the lines of the system (use GetElementsFromList first).
 
const std::vector< Load * > GetLoadList () const
 Get the loads of the system (use GetElementsFromList first).
 
const std::vector< SyncGenerator * > GetSyncGeneratorList () const
 Get the synchronous generators of the system (use GetElementsFromList first).
 
const std::vector< SyncMotor * > GetSyncMotorList () const
 Get the synchronous motors of the system (use GetElementsFromList first).
 
const std::vector< Transformer * > GetTransformerList () const
 Get the transformers of the system (use GetElementsFromList first).
 
const std::vector< HarmCurrent * > GetHarmCurrentList () const
 Get the harmonic current source of the system (use GetElementsFromList first).
 
const std::vector< EMTElement * > GetEMTElementList () const
 Get the electromagnetic element list of the system (use GetElementsFromList first).
 

Protected Member Functions

std::vector< std::vector< std::complex< double > > > GetTransformerHarmAdmmitance (Transformer *transformer, double systemPowerBase, double hOrder, bool ignoreConnection=false)
 
- Protected Member Functions inherited from ElectricCalculation
void GetNextConnection (const unsigned int &checkBusNumber, const std::vector< std::vector< std::complex< double > > > &yBus, std::vector< bool > &connToSlack)
 Recursively check if a bus is electrically connected to the slack bus.
 
void DistributeReactivePower (std::vector< ReactiveMachine > &machines, double qTotal)
 Distribute reactive power among synchronous machines connected to the same bus.
 

Protected Attributes

std::vector< HarmonicYbusm_harmYbusList
 
std::vector< double > m_frequencyList
 
wxString m_errorMsg = ""
 
- Protected Attributes inherited from ElectricCalculation
std::vector< PowerElement * > m_powerElementList
 List of power elements in the system.
 
std::vector< Bus * > m_busList
 List of buses in the system.
 
std::vector< Capacitor * > m_capacitorList
 List of capacitor elements in the system.
 
std::vector< IndMotor * > m_indMotorList
 List of induction motors in the system.
 
std::vector< Inductor * > m_inductorList
 List of inductors in the system.
 
std::vector< Line * > m_lineList
 List of transmission lines in the system.
 
std::vector< Load * > m_loadList
 List of load elements in the system.
 
std::vector< SyncGenerator * > m_syncGeneratorList
 List of synchronous generators in the system.
 
std::vector< SyncMotor * > m_syncMotorList
 List of synchronous motors in the system.
 
std::vector< Transformer * > m_transformerList
 List of transformers in the system.
 
std::vector< HarmCurrent * > m_harmCurrentList
 List of harmonic current sources in the system.
 
std::vector< EMTElement * > m_emtElementList
 List of electromagnetic transient (EMT) elements in the system.
 

Detailed Description

Responsible for the power quality calculations.

Author
Thales Lima Oliveira thale.nosp@m.s@uf.nosp@m.u.br
Date
24/04/2019

Definition at line 16 of file PowerQuality.h.

Constructor & Destructor Documentation

◆ PowerQuality() [1/2]

PowerQuality::PowerQuality ( )

Definition at line 3 of file PowerQuality.cpp.

3{}

◆ PowerQuality() [2/2]

PowerQuality::PowerQuality ( std::vector< Element * >  elementList)

Definition at line 7 of file PowerQuality.cpp.

7{ GetElementsFromList(elementList); }
virtual void GetElementsFromList(std::vector< Element * > elementList)
Separate the power elements from a generic list.

◆ ~PowerQuality()

PowerQuality::~PowerQuality ( )

Definition at line 5 of file PowerQuality.cpp.

5{}

Member Function Documentation

◆ CalculateDistortions()

bool PowerQuality::CalculateDistortions ( double  systemPowerBase = 100e6,
HarmLoadConnection  loadConnection = HarmLoadConnection::PARALLEL 
)
virtual

Definition at line 160 of file PowerQuality.cpp.

161{
162 // Get harmonic orders
163 m_harmYbusList.clear();
164 std::vector<double> harmOrders = GetHarmonicOrdersList();
165
166 // Fill the Ybuses
167 for (unsigned int i = 0; i < harmOrders.size(); ++i) {
168 HarmonicYbus newYbus;
169 newYbus.order = harmOrders[i];
170 m_harmYbusList.push_back(newYbus);
171 }
172 CalculateHarmonicYbusList(systemPowerBase, loadConnection);
173
174 // Initialize current arrays with zeros
175 std::vector<std::vector<std::complex<double> > > iHarmInjList;
176 for (unsigned int i = 0; i < harmOrders.size(); i++) {
177 std::vector<std::complex<double> > line;
178 for (unsigned int j = 0; j < m_busList.size(); j++) { line.push_back(std::complex<double>(0.0, 0.0)); }
179 iHarmInjList.push_back(line);
180 }
181
182 // Fill the current array
183 for (unsigned int i = 0; i < harmOrders.size(); ++i) {
184 for (auto it = m_harmCurrentList.begin(), itEnd = m_harmCurrentList.end(); it != itEnd; ++it) {
185 HarmCurrent* harmCurrent = *it;
186 if (harmCurrent->IsOnline()) {
187 // Get only the current order in analysis
188 for (unsigned int k = 0; k < harmCurrent->GetElectricalData().harmonicOrder.size(); ++k) {
189 if (harmCurrent->GetElectricalData().harmonicOrder[k] == static_cast<int>(harmOrders[i])) {
190 Bus* parentBus = static_cast<Bus*>(harmCurrent->GetParentList()[0]);
191 auto busData = parentBus->GetElectricalData();
192 int j = busData.number;
193
194 // Bus voltage
195 double voltage = busData.nominalVoltage;
196 if (busData.nominalVoltageUnit == ElectricalUnit::UNIT_kV) voltage *= 1e3;
197
198 auto puData = harmCurrent->GetPUElectricalData(systemPowerBase, voltage);
199
200 iHarmInjList[i][j] += std::complex<double>(
201 puData.injHarmCurrent[k] * std::cos(wxDegToRad(puData.injHarmAngle[k])),
202 puData.injHarmCurrent[k] * std::sin(wxDegToRad(puData.injHarmAngle[k])));
203 }
204 }
205 }
206 }
207 // EMT elements
208 for (auto* emtElement : m_emtElementList) {
209 if (!emtElement->IsOnline()) continue; // Skip offline elements
210 if (emtElement->GetParentList().size() > 0) {
211 if (emtElement->GetParentList()[0] != nullptr) {
212 auto data = emtElement->GetEMTElementData();
213 for (auto const& [order, current] : data.currHarmonics) {
214 if (order == 1) continue; // Skip fundamental
215 else if (order == static_cast<int>(harmOrders[i])) {
216 Bus* parentBus = static_cast<Bus*>(emtElement->GetParentList()[0]);
217 auto busData = parentBus->GetElectricalData();
218 int j = busData.number;
219
220 double voltage = busData.nominalVoltage;
221 if (busData.nominalVoltageUnit == ElectricalUnit::UNIT_kV) voltage *= 1e3;
222 double baseCurrent = systemPowerBase / (std::sqrt(3.0) * voltage);
223
224 iHarmInjList[i][j] += current / baseCurrent;
225 }
226 }
227 }
228 }
229 }
230 }
231
232 // Calculate harmonic voltages
233 std::vector<std::vector<std::complex<double> > > vHarmList;
234 for (unsigned int i = 0; i < m_harmYbusList.size(); ++i) {
235 vHarmList.push_back(GaussianElimination(m_harmYbusList[i].yBus, iHarmInjList[i]));
236 }
237
238 for (auto it = m_busList.begin(), itEnd = m_busList.end(); it != itEnd; ++it) {
239 Bus* bus = *it;
240 auto data = bus->GetElectricalData();
241 data.harmonicOrder.clear();
242 data.harmonicVoltage.clear();
243 double thd = 0.0;
244 for (unsigned int i = 0; i < vHarmList.size(); ++i) {
245 thd += std::abs(vHarmList[i][data.number]) * std::abs(vHarmList[i][data.number]);
246 data.harmonicVoltage.push_back(vHarmList[i][data.number]);
247 data.harmonicOrder.push_back(static_cast<int>(harmOrders[i]));
248 }
249 // distortion = std::sqrt(distortion) / std::abs(data.voltage);
250 thd = std::sqrt(thd) * 100.0;
251 data.thd = thd;
252 bus->SetElectricalData(data);
253 }
254
255 // Calculate harmonic currents through branches:
256 // Lines
257 for (auto* line : m_lineList) {
258 if (line->IsOnline()) {
259 LineElectricalData data = line->GetPUElectricalData(systemPowerBase);
260
261 auto busData1 = static_cast<Bus*>(line->GetParentList()[0])->GetElectricalData();
262 auto busData2 = static_cast<Bus*>(line->GetParentList()[1])->GetElectricalData();
263
264 if (busData1.harmonicVoltage.size() != busData1.harmonicVoltage.size()) {
265 m_errorMsg = _("Error calculating the harmonic current in \"") + data.name + wxT("\".");
266 return false;
267 }
268
269 // Clear old currents
270 data.harmonicOrder.clear();
271 data.harmonicCurrent[0].clear();
272 data.harmonicCurrent[1].clear();
273
274 int i = 0;
275 for (auto& hVoltage : busData1.harmonicVoltage) {
276 int order = busData1.harmonicOrder[i];
277 data.harmonicOrder.push_back(order);
278
279 std::complex<double> v1 = hVoltage;
280 std::complex<double> v2 = busData2.harmonicVoltage[i];
281 std::complex<double> zs = std::complex<double>(data.resistance, data.indReactance * order);
282 std::complex<double> bsh = std::complex<double>(0.0, (data.capSusceptance * order) / 2.0);
283
284 data.harmonicCurrent[0].push_back((v1 - v2) / zs + v1 * bsh);
285 data.harmonicCurrent[1].push_back((v2 - v1) / zs + v2 * bsh);
286 i++;
287 }
288
289 line->SetElectricalData(data);
290 }
291 }
292 // Transformers
293 for (auto* transformer : m_transformerList) {
294 if (transformer->IsOnline()) {
295 TransformerElectricalData data = transformer->GetPUElectricalData(systemPowerBase);
296
297 auto busData1 = static_cast<Bus*>(transformer->GetParentList()[0])->GetElectricalData();
298 auto busData2 = static_cast<Bus*>(transformer->GetParentList()[1])->GetElectricalData();
299
300 if (busData1.harmonicVoltage.size() != busData1.harmonicVoltage.size()) {
301 m_errorMsg = _("Error calculating the harmonic current in \"") + data.name + wxT("\".");
302 return false;
303 }
304
305 // Clear old currents
306 data.harmonicOrder.clear();
307 data.harmonicCurrent[0].clear();
308 data.harmonicCurrent[1].clear();
309
310 int i = 0;
311 for (auto& hVoltage : busData1.harmonicVoltage) {
312 int order = busData1.harmonicOrder[i];
313 data.harmonicOrder.push_back(order);
314
315 std::complex<double> v1 = hVoltage;
316 std::complex<double> v2 = busData2.harmonicVoltage[i];
317
318 auto yMatrix = GetTransformerHarmAdmmitance(transformer, systemPowerBase, order);
319
320 data.harmonicCurrent[0].push_back(yMatrix[0][0] * v1 + yMatrix[0][1] * v2);
321 data.harmonicCurrent[1].push_back(yMatrix[1][0] * v1 + yMatrix[1][1] * v2);
322
323 i++;
324 }
325
326 transformer->SetElectricaData(data);
327
328 }
329 }
330
331 return true;
332}
Node for power elements. All others power elements are connected through this.
Definition Bus.h:86
std::vector< Line * > m_lineList
List of transmission lines in the system.
std::vector< Bus * > m_busList
List of buses in the system.
std::vector< Transformer * > m_transformerList
List of transformers in the system.
std::vector< EMTElement * > m_emtElementList
List of electromagnetic transient (EMT) elements in the system.
std::vector< std::complex< double > > GaussianElimination(std::vector< std::vector< std::complex< double > > > matrix, std::vector< std::complex< double > > array)
Solve a linear system using Gaussian elimination (complex version).
std::vector< HarmCurrent * > m_harmCurrentList
List of harmonic current sources in the system.
virtual std::vector< Element * > GetParentList() const
Get the parent list.
Definition Element.h:559
bool IsOnline() const
Checks if the element is online or offline.
Definition Element.h:226
Shunt Harmonic Corrent Source.
Definition HarmCurrent.h:24

◆ CalculateFrequencyResponse()

bool PowerQuality::CalculateFrequencyResponse ( double  systemFreq = 60.0,
double  initFreq = 0.0,
double  endFreq = 1500.0,
double  stepFreq = 1.0,
int  injBusNumber = 0,
double  systemPowerBase = 100e6,
HarmLoadConnection  loadConnection = HarmLoadConnection::PARALLEL 
)
virtual

Definition at line 449 of file PowerQuality.cpp.

456{
457 // Clear all previous data
458 for (unsigned int i = 0; i < m_busList.size(); i++) {
459 auto data = m_busList[i]->GetElectricalData();
460 data.absImpedanceVector.clear();
461 data.absImpedanceVector.shrink_to_fit();
462 m_busList[i]->SetElectricalData(data);
463 }
464
465 // Create and fill with zeros the YBus
466 std::vector<std::vector<std::complex<double> > > yBus;
467 for (unsigned int i = 0; i < m_busList.size(); i++) {
468 std::vector<std::complex<double> > line;
469 for (unsigned int j = 0; j < m_busList.size(); j++) { line.push_back(std::complex<double>(0.0, 0.0)); }
470 yBus.push_back(line);
471 }
472 // Create and fill with zeros the injected current vector
473 std::vector<std::complex<double> > iInj;
474 for (unsigned int i = 0; i < m_busList.size(); i++) { iInj.push_back(std::complex<double>(0.0, 0.0)); }
475 iInj[injBusNumber] = std::complex<double>(1.0, 0.0);
476
477 if (initFreq < 1e-6) initFreq = stepFreq;
478 double currentFreq = initFreq;
479 while (currentFreq <= endFreq) {
480 m_frequencyList.push_back(currentFreq);
481
482 double order = currentFreq / systemFreq;
483
484 // Fill YBus with zeros
485 for (unsigned int i = 0; i < m_busList.size(); i++) {
486 for (unsigned int j = 0; j < m_busList.size(); j++) { yBus[i][j] = std::complex<double>(0.0, 0.0); }
487 }
488
489 CalculateHarmonicYbus(yBus, systemPowerBase, order, true, loadConnection);
490
491 for (unsigned int i = 0; i < m_busList.size(); i++) {
492 auto data = m_busList[i]->GetElectricalData();
493 if (data.plotPQData) {
494 auto zh = GaussianElimination(yBus, iInj);
495
496 data.absImpedanceVector.push_back(std::abs(zh[data.number]));
497 m_busList[i]->SetElectricalData(data);
498 }
499 }
500
501 currentFreq += stepFreq;
502 }
503 return false;
504}

◆ CalculateHarmonicYbus()

void PowerQuality::CalculateHarmonicYbus ( std::vector< std::vector< std::complex< double > > > &  yBus,
double  systemPowerBase,
double  order,
bool  ignoreTransformerConnection = false,
HarmLoadConnection  loadConnection = HarmLoadConnection::PARALLEL 
)
virtual

Definition at line 31 of file PowerQuality.cpp.

36{
37 // Load
38 for (auto it = m_loadList.begin(), itEnd = m_loadList.end(); it != itEnd; ++it) {
39 Load* load = *it;
40 if (load->IsOnline() && loadConnection != HarmLoadConnection::DISCONNECTED) {
41 auto busData = static_cast<Bus*>(load->GetParentList()[0])->GetElectricalData();
42 if (busData.isConnected) {
43 int n = busData.number;
44 LoadElectricalData data = load->GetPUElectricalData(systemPowerBase);
45
46 std::complex<double> v = static_cast<Bus*>(load->GetParentList()[0])->GetElectricalData().voltage;
47
48 //tex:
49 // $$\bar{Z}=\frac{V^2}{P-jQ}=R+jX_L \rightarrow \bar{Z}_h=R+jX_L \cdot h$$
50 std::complex<double> zLoad = (std::abs(v) * std::abs(v)) / std::complex<double>(data.activePower, -data.reactivePower);
51 zLoad = std::complex<double>(zLoad.real(), zLoad.imag() * order);
52 if (std::abs(zLoad.real()) < 1e-6) zLoad = std::complex<double>(1e-6, zLoad.imag());
53 if (std::abs(zLoad.imag()) < 1e-6) zLoad = std::complex<double>(zLoad.real(), 1e-6);
54 std::complex<double> yLoad = 0.0;
55
56 //tex:
57 //Parallel:
58 //$$\bar{Y}=\frac{1}{R}+\frac{1}{jX_L}$$
59 //Series:
60 //$$\bar{Y}=\frac{1}{R+jX_L}$$
61 if (loadConnection == HarmLoadConnection::PARALLEL)
62 yLoad = std::complex<double>(1.0, 0.0) / std::complex<double>(zLoad.real(), 0.0) + std::complex<double>(1.0, 0.0) / std::complex<double>(0.0, zLoad.imag());
63 else if (loadConnection == HarmLoadConnection::SERIES)
64 yLoad = std::complex<double>(1.0, 0.0) / zLoad;
65
66 /*std::complex<double> yLoad = std::complex<double>(data.activePower, -data.reactivePower / order);
67 std::complex<double> v = static_cast<Bus*>(load->GetParentList()[0])->GetElectricalData().voltage;
68 yLoad /= (std::abs(v) * std::abs(v));*/
69
70 yBus[n][n] += yLoad;
71 }
72 }
73 }
74
75 // Capacitor
76 for (auto it = m_capacitorList.begin(), itEnd = m_capacitorList.end(); it != itEnd; ++it) {
77 Capacitor* capacitor = *it;
78 if (capacitor->IsOnline()) {
79 auto busData = static_cast<Bus*>(capacitor->GetParentList()[0])->GetElectricalData();
80 if (busData.isConnected) {
81 int n = busData.number;
82 CapacitorElectricalData data = capacitor->GetPUElectricalData(systemPowerBase);
83 yBus[n][n] += std::complex<double>(0.0, data.reactivePower) * order;
84 }
85 }
86 }
87
88 // Inductor
89 for (auto it = m_inductorList.begin(), itEnd = m_inductorList.end(); it != itEnd; ++it) {
90 Inductor* inductor = *it;
91 if (inductor->IsOnline()) {
92 auto busData = static_cast<Bus*>(inductor->GetParentList()[0])->GetElectricalData();
93 if (busData.isConnected) {
94 int n = busData.number;
95 InductorElectricalData data = inductor->GetPUElectricalData(systemPowerBase);
96 yBus[n][n] += std::complex<double>(0.0, -data.reactivePower) / order;
97 }
98 }
99 }
100
101 // Power line
102 for (auto it = m_lineList.begin(), itEnd = m_lineList.end(); it != itEnd; ++it) {
103 Line* line = *it;
104 if (line->IsOnline()) {
105 LineElectricalData data = line->GetPUElectricalData(systemPowerBase);
106
107 int n1 = static_cast<Bus*>(line->GetParentList()[0])->GetElectricalData().number;
108 int n2 = static_cast<Bus*>(line->GetParentList()[1])->GetElectricalData().number;
109
110 yBus[n1][n2] -= 1.0 / std::complex<double>(data.resistance, data.indReactance * order);
111 yBus[n2][n1] -= 1.0 / std::complex<double>(data.resistance, data.indReactance * order);
112
113 yBus[n1][n1] += 1.0 / std::complex<double>(data.resistance, data.indReactance * order);
114 yBus[n2][n2] += 1.0 / std::complex<double>(data.resistance, data.indReactance * order);
115
116 yBus[n1][n1] += std::complex<double>(0.0, (data.capSusceptance * order) / 2.0);
117 yBus[n2][n2] += std::complex<double>(0.0, (data.capSusceptance * order) / 2.0);
118 }
119 }
120
121 // Transformer
122 for (auto it = m_transformerList.begin(), itEnd = m_transformerList.end(); it != itEnd; ++it) {
123 Transformer* transformer = *it;
124
125 if (transformer->IsOnline()) {
126 TransformerElectricalData data = transformer->GetPUElectricalData(systemPowerBase);
127
128 int n1 = static_cast<Bus*>(transformer->GetParentList()[0])->GetElectricalData().number;
129 int n2 = static_cast<Bus*>(transformer->GetParentList()[1])->GetElectricalData().number;
130
131 auto yMatrix = GetTransformerHarmAdmmitance(transformer, systemPowerBase, order, ignoreTransformerConnection);
132
133 yBus[n1][n2] += yMatrix[0][1];
134 yBus[n2][n1] += yMatrix[1][0];
135 yBus[n1][n1] += yMatrix[0][0];
136 yBus[n2][n2] += yMatrix[1][1];
137 }
138 }
139
140 // Synchronous generator
141 for (auto it = m_syncGeneratorList.begin(), itEnd = m_syncGeneratorList.end(); it != itEnd; ++it) {
142 SyncGenerator* syncGenerator = *it;
143 if (syncGenerator->IsOnline()) {
144 int n = static_cast<Bus*>(syncGenerator->GetParentList()[0])->GetElectricalData().number;
145 SyncGeneratorElectricalData data = syncGenerator->GetPUElectricalData(systemPowerBase);
146 yBus[n][n] += 1.0 / std::complex<double>(data.positiveResistance, data.positiveReactance * order);
147 }
148 }
149 // Synchronous motor
150 for (auto it = m_syncMotorList.begin(), itEnd = m_syncMotorList.end(); it != itEnd; ++it) {
151 SyncMotor* syncMotor = *it;
152 if (syncMotor->IsOnline()) {
153 int n = static_cast<Bus*>(syncMotor->GetParentList()[0])->GetElectricalData().number;
154 SyncMotorElectricalData data = syncMotor->GetPUElectricalData(systemPowerBase);
155 yBus[n][n] += 1.0 / std::complex<double>(data.positiveResistance, data.positiveReactance * order);
156 }
157 }
158}
Shunt capactior power element.
Definition Capacitor.h:39
std::vector< Load * > m_loadList
List of load elements in the system.
std::vector< Capacitor * > m_capacitorList
List of capacitor elements in the system.
std::vector< SyncGenerator * > m_syncGeneratorList
List of synchronous generators in the system.
std::vector< SyncMotor * > m_syncMotorList
List of synchronous motors in the system.
std::vector< Inductor * > m_inductorList
List of inductors in the system.
Inductor shunt power element.
Definition Inductor.h:39
Power line element.
Definition Line.h:64
Loas shunt power element.
Definition Load.h:74
Synchronous generator power element.
Synchronous motor (synchronous compensator) power element.
Definition SyncMotor.h:135
Two-winding transformer power element.
Definition Transformer.h:84

◆ CalculateHarmonicYbusList()

void PowerQuality::CalculateHarmonicYbusList ( double  systemPowerBase = 100e6,
HarmLoadConnection  loadConnection = HarmLoadConnection::PARALLEL 
)
virtual

Definition at line 9 of file PowerQuality.cpp.

10{
11 // Clear and fill with zeros all the harmonic Ybuses
12 for (auto it = m_harmYbusList.begin(), itEnd = m_harmYbusList.end(); it != itEnd; ++it) {
13 HarmonicYbus harmYBus = *it;
14 harmYBus.yBus.clear();
15 for (unsigned int i = 0; i < m_busList.size(); i++) {
16 std::vector<std::complex<double> > line;
17 for (unsigned int j = 0; j < m_busList.size(); j++) { line.push_back(std::complex<double>(0.0, 0.0)); }
18 harmYBus.yBus.push_back(line);
19 }
20 *it = harmYBus;
21 }
22
23 // Fill all Ybuses
24 for (auto itYbus = m_harmYbusList.begin(), itYbusEnd = m_harmYbusList.end(); itYbus != itYbusEnd; ++itYbus) {
25 HarmonicYbus harmYBus = *itYbus;
26 CalculateHarmonicYbus(harmYBus.yBus, systemPowerBase, harmYBus.order, false, loadConnection);
27 *itYbus = harmYBus;
28 }
29}

◆ GetErrorMessage()

virtual wxString PowerQuality::GetErrorMessage ( )
inlinevirtual

Definition at line 28 of file PowerQuality.h.

28{ return m_errorMsg; }

◆ GetFrequencies()

virtual std::vector< double > PowerQuality::GetFrequencies ( )
inlinevirtual

Definition at line 46 of file PowerQuality.h.

46{ return m_frequencyList; }

◆ GetHarmonicOrdersList()

std::vector< double > PowerQuality::GetHarmonicOrdersList ( )
virtual

Definition at line 334 of file PowerQuality.cpp.

335{
336 std::vector<int> harmOrders;
337 auto harmCurrentList = GetHarmCurrentList();
338 // Check all harmonic sources and get all harmonic orders in the system
339 for (auto it = harmCurrentList.begin(), itEnd = harmCurrentList.end(); it != itEnd; ++it) {
340 HarmCurrent* harmCurrent = *it;
341 if (harmCurrent->IsOnline()) {
342 auto data = harmCurrent->GetElectricalData();
343 for (unsigned int i = 0; i < data.harmonicOrder.size(); ++i) {
344 int order = data.harmonicOrder[i];
345 // Check if this harmonic order have been added already
346 bool newOrder = true;
347 for (unsigned int j = 0; j < harmOrders.size(); ++j) {
348 if (order == harmOrders[j]) {
349 newOrder = false;
350 break;
351 }
352 }
353 if (newOrder) harmOrders.push_back(order);
354 }
355 }
356 }
357 // Check all harmonic from EMT elements
358 for (auto* emtElement : m_emtElementList) {
359 if (!emtElement->IsOnline()) continue; // Skip offline elements
360
361 auto data = emtElement->GetEMTElementData();
362 for (auto const& [order, current] : data.currHarmonics) {
363 if (order == 1) continue; // Skip fundamental
364 bool newOrder = true;
365 for (int vecOrder : harmOrders) {
366 if (order == vecOrder) {
367 newOrder = false;
368 break;
369 }
370 }
371 if (newOrder) harmOrders.push_back(order);
372 }
373 }
374
375 std::vector<double> doubleHarmOrder;
376 for (unsigned int i = 0; i < harmOrders.size(); ++i) {
377 doubleHarmOrder.push_back(static_cast<double>(harmOrders[i]));
378 }
379 return doubleHarmOrder;
380}
const std::vector< HarmCurrent * > GetHarmCurrentList() const
Get the harmonic current source of the system (use GetElementsFromList first).

◆ GetTransformerHarmAdmmitance()

std::vector< std::vector< std::complex< double > > > PowerQuality::GetTransformerHarmAdmmitance ( Transformer transformer,
double  systemPowerBase,
double  hOrder,
bool  ignoreConnection = false 
)
protected

Definition at line 382 of file PowerQuality.cpp.

383{
384 TransformerElectricalData data = transformer->GetPUElectricalData(systemPowerBase);
385
386 std::complex<double> ys = std::complex<double>(1.0, 0.0) / std::complex<double>(data.resistance, data.indReactance * hOrder);
387 std::complex<double> zeroCpx(0.0, 0.0);
388 std::vector<std::vector< std::complex<double> > > yMatrix{ {zeroCpx, zeroCpx}, {zeroCpx, zeroCpx} };
389
390 // If the transformer have nominal turns ratio (1.0) and no phase shifting, it will be modelled as series impedance.
391 if ((data.turnsRatio == 1.0 && data.phaseShift == 0.0) || ignoreConnection) {
392 yMatrix[0][0] = ys;
393 yMatrix[1][1] = ys;
394 yMatrix[0][1] = -ys;
395 yMatrix[1][0] = -ys;
396 }
397 else {
398 // 1. If the harmonic order is negative sequence (order % 3 == 2), change the phase shift signal;
399 // 2. If the harmonic order if zero sequence (order % 3 == 0). transformer connection must be considered.
400 double radPhaseShift = wxDegToRad(data.phaseShift);
401
402 if (static_cast<int>(hOrder) % 3 != 0) { // Positive and Negative sequences
403 if (static_cast<int>(hOrder) % 3 == 2) { // Negative sequence
404 radPhaseShift *= -1.0;
405 }
406 std::complex<double> a = std::complex<double>(data.turnsRatio * std::cos(radPhaseShift),
407 -data.turnsRatio * std::sin(radPhaseShift));
408
409 yMatrix[0][0] = ys / (std::pow(std::abs(a), 2.0));
410 yMatrix[0][1] = -(ys / std::conj(a));
411 yMatrix[1][0] = -(ys / a);
412 yMatrix[1][1] = ys;
413 }
414 else { // Zero sequence
415 switch (data.connection) {
416 case GWYE_GWYE: {
417 ys = 1.0 / std::complex<double>(
418 data.zeroResistance + 3.0 * (data.primaryGrndResistance + data.secondaryGrndResistance),
419 data.zeroIndReactance +
420 3.0 * (data.primaryGrndReactance + data.secondaryGrndReactance));
421 std::complex<double> a = std::complex<double>(data.turnsRatio, 0.0);
422
423 yMatrix[0][0] = ys / (a * a);
424 yMatrix[0][1] = -(ys / a);
425 yMatrix[1][0] = -(ys / a);
426 yMatrix[1][1] = ys;
427 } break;
428 case DELTA_GWYE: {
429 ys = 1.0 / std::complex<double>(data.zeroResistance + 3.0 * (data.secondaryGrndResistance),
430 data.zeroIndReactance + 3.0 * (data.secondaryGrndReactance));
431 yMatrix[1][1] = ys;
432 break;
433 }
434 case GWYE_DELTA: {
435 ys = 1.0 / std::complex<double>(data.zeroResistance + 3.0 * (data.primaryGrndResistance),
436 data.zeroIndReactance + 3.0 * (data.primaryGrndReactance));
437 yMatrix[0][0] = ys;
438 break;
439 }
440 default:
441 break;
442 }
443 }
444 }
445
446 return yMatrix;
447}

Member Data Documentation

◆ m_errorMsg

wxString PowerQuality::m_errorMsg = ""
protected

Definition at line 53 of file PowerQuality.h.

◆ m_frequencyList

std::vector<double> PowerQuality::m_frequencyList
protected

Definition at line 52 of file PowerQuality.h.

◆ m_harmYbusList

std::vector<HarmonicYbus> PowerQuality::m_harmYbusList
protected

Definition at line 51 of file PowerQuality.h.


The documentation for this class was generated from the following files: