summaryrefslogtreecommitdiffstats
path: root/Project/ElectricCalculation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Project/ElectricCalculation.cpp')
-rw-r--r--Project/ElectricCalculation.cpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/Project/ElectricCalculation.cpp b/Project/ElectricCalculation.cpp
new file mode 100644
index 0000000..389af4a
--- /dev/null
+++ b/Project/ElectricCalculation.cpp
@@ -0,0 +1,189 @@
+#include "ElectricCalculation.h"
+#include "Element.h"
+#include "Bus.h"
+#include "Capacitor.h"
+#include "IndMotor.h"
+#include "Inductor.h"
+#include "Line.h"
+#include "Load.h"
+#include "SyncGenerator.h"
+#include "SyncMotor.h"
+#include "Transformer.h"
+
+ElectricCalculation::ElectricCalculation() {}
+ElectricCalculation::~ElectricCalculation() {}
+void ElectricCalculation::GetElementsFromList(std::vector<Element*> elementList)
+{
+ m_busList.clear();
+ m_capacitorList.clear();
+ m_indMotorList.clear();
+ m_inductorList.clear();
+ m_lineList.clear();
+ m_loadList.clear();
+ m_syncGeneratorList.clear();
+ m_syncMotorList.clear();
+ m_transformerList.clear();
+ // Bad design?
+ for(auto it = elementList.begin(); it != elementList.end(); it++) {
+ Element* element = *it;
+ if(typeid(*element) == typeid(Bus))
+ m_busList.push_back((Bus*)element);
+ else if(typeid(*element) == typeid(Capacitor))
+ m_capacitorList.push_back((Capacitor*)element);
+ else if(typeid(*element) == typeid(IndMotor))
+ m_indMotorList.push_back((IndMotor*)element);
+ else if(typeid(*element) == typeid(Inductor))
+ m_inductorList.push_back((Inductor*)element);
+ else if(typeid(*element) == typeid(Line))
+ m_lineList.push_back((Line*)element);
+ else if(typeid(*element) == typeid(Load))
+ m_loadList.push_back((Load*)element);
+ else if(typeid(*element) == typeid(SyncGenerator))
+ m_syncGeneratorList.push_back((SyncGenerator*)element);
+ else if(typeid(*element) == typeid(SyncMotor))
+ m_syncMotorList.push_back((SyncMotor*)element);
+ else if(typeid(*element) == typeid(Transformer))
+ m_transformerList.push_back((Transformer*)element);
+ }
+}
+
+bool ElectricCalculation::GetYBus(std::vector<std::vector<std::complex<double> > >& yBus, double systemPowerBase)
+{
+ if(m_busList.size() == 0) return false;
+
+ // Clear and fill with zeros the Ybus
+ yBus.clear();
+ for(int i = 0; i < (int)m_busList.size(); i++) {
+ std::vector<std::complex<double> > line;
+ for(int j = 0; j < (int)m_busList.size(); j++) {
+ line.push_back(std::complex<double>(0.0, 0.0));
+ }
+ yBus.push_back(line);
+ }
+
+ // Build connection map
+ std::vector<std::vector<int> > lineMap;
+ std::vector<std::vector<int> > transfomerMap;
+ lineMap.resize(m_lineList.size());
+ transfomerMap.resize(m_transformerList.size());
+
+ // Get the connection map for
+ int busNumber = 0;
+ for(auto itb = m_busList.begin(); itb != m_busList.end(); itb++) {
+ Bus* bus = *itb;
+
+ // Get power line connection map
+ for(int i = 0; i < (int)m_lineList.size(); i++) {
+ for(int j = 0; j < (int)m_lineList[i]->GetParentList().size(); j++) {
+ if(bus == m_lineList[i]->GetParentList()[j]) lineMap[i].push_back(busNumber);
+ }
+ }
+
+ // Get transformer connection map
+ for(int i = 0; i < (int)m_transformerList.size(); i++) {
+ for(int j = 0; j < (int)m_transformerList[i]->GetParentList().size(); j++) {
+ if(bus == m_transformerList[i]->GetParentList()[j]) transfomerMap[i].push_back(busNumber);
+ }
+ }
+
+ // Load
+ for(auto itlo = m_loadList.begin(); itlo != m_loadList.end(); itlo++) {
+ Load* load = *itlo;
+ if(bus == load->GetParentList()[0]) {
+ LoadElectricalData data = load->GetPUElectricalData(systemPowerBase);
+ if(data.loadType == CONST_IMPEDANCE)
+ yBus[busNumber][busNumber] += std::complex<double>(data.activePower, -data.reactivePower);
+ }
+ }
+
+ // Capacitor
+ for(auto itca = m_capacitorList.begin(); itca != m_capacitorList.end(); itca++) {
+ Capacitor* capacitor = *itca;
+ if(bus == capacitor->GetParentList()[0]) {
+ CapacitorElectricalData data = capacitor->GetPUElectricalData(systemPowerBase);
+ yBus[busNumber][busNumber] += std::complex<double>(0.0, data.reactivePower);
+ }
+ }
+
+ // Inductor
+ for(auto itin = m_inductorList.begin(); itin != m_inductorList.end(); itin++) {
+ Inductor* inductor = *itin;
+ if(bus == inductor->GetParentList()[0]) {
+ InductorElectricalData data = inductor->GetPUElectricalData(systemPowerBase);
+ yBus[busNumber][busNumber] += std::complex<double>(0.0, -data.reactivePower);
+ }
+ }
+
+ busNumber++;
+ }
+
+ // Power line
+ int lineNumber = 0;
+ for(auto itl = m_lineList.begin(); itl != m_lineList.end(); itl++) {
+ Line* line = *itl;
+ LineElectricalData data = line->GetElectricalData();
+ if(line->IsOnline()) {
+ yBus[lineMap[lineNumber][0]][lineMap[lineNumber][1]] -=
+ 1.0 / std::complex<double>(data.resistance, data.indReactance);
+ yBus[lineMap[lineNumber][1]][lineMap[lineNumber][0]] -=
+ 1.0 / std::complex<double>(data.resistance, data.indReactance);
+
+ yBus[lineMap[lineNumber][0]][lineMap[lineNumber][0]] +=
+ 1.0 / std::complex<double>(data.resistance, data.indReactance);
+ yBus[lineMap[lineNumber][1]][lineMap[lineNumber][1]] +=
+ 1.0 / std::complex<double>(data.resistance, data.indReactance);
+
+ yBus[lineMap[lineNumber][0]][lineMap[lineNumber][0]] +=
+ std::complex<double>(0.0, data.capSusceptance / 2.0);
+ yBus[lineMap[lineNumber][1]][lineMap[lineNumber][1]] +=
+ std::complex<double>(0.0, data.capSusceptance / 2.0);
+ }
+ lineNumber++;
+ }
+
+ int transformerNumber = 0;
+ for(auto itt = m_transformerList.begin(); itt != m_transformerList.end(); ++itt) {
+ Transformer* transformer = *itt;
+ TransformerElectricalData data = transformer->GetElectricalData();
+
+ if(transformer->IsOnline()) {
+ // If the transformer have nominal turns ratio (1.0) and no phase shifting, it will be modelled as series
+ // impedance.
+ if(data.turnsRatio == 1.0 && data.phaseShift == 0.0) {
+ yBus[transfomerMap[transformerNumber][0]][transfomerMap[transformerNumber][1]] +=
+ -1.0 / std::complex<double>(data.resistance, data.indReactance);
+ yBus[transfomerMap[transformerNumber][1]][transfomerMap[transformerNumber][0]] +=
+ -1.0 / std::complex<double>(data.resistance, data.indReactance);
+
+ yBus[transfomerMap[transformerNumber][0]][transfomerMap[transformerNumber][0]] +=
+ 1.0 / std::complex<double>(data.resistance, data.indReactance);
+ yBus[transfomerMap[transformerNumber][1]][transfomerMap[transformerNumber][1]] +=
+ 1.0 / std::complex<double>(data.resistance, data.indReactance);
+ }
+ // If the transformer have no-nominal turn ratio and/or phase shifting, it will be modelled in a different
+ // way (see references).
+ //[Ref. 1: Elementos de analise de sistemas de potencia - Stevenson - pg. 232]
+ //[Ref. 2: http://www.ee.washington.edu/research/real/Library/Reports/Tap_Adjustments_in_AC_Load_Flows.pdf]
+ //[Ref. 3: http://www.columbia.edu/~dano/courses/power/notes/power/andersson1.pdf]
+ else {
+ // Complex turns ratio
+ double radPhaseShift = wxDegToRad(data.phaseShift);
+ std::complex<double> a = std::complex<double>(data.turnsRatio * std::cos(radPhaseShift),
+ -data.turnsRatio * std::sin(radPhaseShift));
+
+ // Transformer admitance
+ std::complex<double> y = 1.0 / std::complex<double>(data.resistance, data.indReactance);
+
+ yBus[transfomerMap[transformerNumber][0]][transfomerMap[transformerNumber][0]] +=
+ y / std::pow(std::abs(a), 2.0);
+ yBus[transfomerMap[transformerNumber][0]][transfomerMap[transformerNumber][1]] += -(y / std::conj(a));
+ yBus[transfomerMap[transformerNumber][1]][transfomerMap[transformerNumber][0]] += -(y / a);
+ yBus[transfomerMap[transformerNumber][1]][transfomerMap[transformerNumber][1]] += y;
+ }
+ }
+
+ transformerNumber++;
+ }
+
+ return true;
+}