diff options
Diffstat (limited to 'Project')
-rw-r--r-- | Project/Bus.h | 12 | ||||
-rw-r--r-- | Project/ElectricCalculation.cpp | 186 | ||||
-rw-r--r-- | Project/ElectricCalculation.h | 1 | ||||
-rw-r--r-- | Project/Element.cpp | 2 | ||||
-rw-r--r-- | Project/Line.h | 3 | ||||
-rw-r--r-- | Project/PowerFlow.cpp | 379 | ||||
-rw-r--r-- | Project/PowerFlow.h | 22 | ||||
-rw-r--r-- | Project/Project.mk | 7 | ||||
-rw-r--r-- | Project/Release/Bus.cpp.o | bin | 40789 -> 40901 bytes | |||
-rw-r--r-- | Project/Release/BusForm.cpp.o | bin | 112442 -> 113299 bytes | |||
-rw-r--r-- | Project/Release/ElectricCalculation.cpp.o | bin | 29958 -> 30326 bytes | |||
-rw-r--r-- | Project/Release/Element.cpp.o | bin | 155347 -> 155347 bytes | |||
-rw-r--r-- | Project/Release/Line.cpp.o | bin | 160828 -> 161132 bytes | |||
-rw-r--r-- | Project/Release/MainFrame.cpp.o | bin | 141354 -> 141354 bytes | |||
-rw-r--r-- | Project/Release/PSP-UFU.exe | bin | 4048697 -> 4041320 bytes | |||
-rw-r--r-- | Project/Release/PowerFlow.cpp.o | bin | 42418 -> 28359 bytes | |||
-rw-r--r-- | Project/Release/Workspace.cpp.o | bin | 202691 -> 203173 bytes | |||
-rw-r--r-- | Project/Transformer.h | 4 |
18 files changed, 398 insertions, 218 deletions
diff --git a/Project/Bus.h b/Project/Bus.h index 90068d1..2776462 100644 --- a/Project/Bus.h +++ b/Project/Bus.h @@ -4,8 +4,7 @@ #include "BusForm.h" #include "Element.h" -struct BusElectricalData -{ +struct BusElectricalData { wxString name = ""; double nominalVoltage = 138.0; ElectricalUnit nominalVoltageUnit = UNIT_kV; @@ -13,11 +12,18 @@ struct BusElectricalData double controlledVoltage = 1.0; int controlledVoltageUnitChoice = 0; // 0 = p.u., 1 = same as nominalVoltageUnit (UNIT_V or UNIT_kV). bool slackBus = false; + + // Power flow (p.u.) + std::complex<double> voltage = std::complex<double>(1.0, 0.0); + + // Fault bool hasFault = false; FaultData faultType = FAULT_THREEPHASE; FaultData faultLocation = FAULT_LINE_A; double faultResistance = 0.0; double faultReactance = 0.0; + + // Stability bool plotBus = false; bool stabHasFault = false; double stabFaultTime = 0.0; @@ -31,7 +37,7 @@ class Bus : public Element public: Bus(); Bus(wxPoint2DDouble position); - Bus(wxPoint2DDouble position, wxString name); + Bus(wxPoint2DDouble position, wxString name); ~Bus(); virtual bool AddParent(Element* parent, wxPoint2DDouble position) { return true; } virtual bool Contains(wxPoint2DDouble position) const; diff --git a/Project/ElectricCalculation.cpp b/Project/ElectricCalculation.cpp index 5698905..f018f74 100644 --- a/Project/ElectricCalculation.cpp +++ b/Project/ElectricCalculation.cpp @@ -13,7 +13,7 @@ void ElectricCalculation::GetElementsFromList(std::vector<Element*> elementList) m_syncGeneratorList.clear(); m_syncMotorList.clear(); m_transformerList.clear(); - // Bad design? + // TODO: Bad design? for(auto it = elementList.begin(); it != elementList.end(); it++) { Element* element = *it; if(typeid(*element) == typeid(Bus)) @@ -79,7 +79,7 @@ bool ElectricCalculation::GetYBus(std::vector<std::vector<std::complex<double> > // Load for(auto itlo = m_loadList.begin(); itlo != m_loadList.end(); itlo++) { Load* load = *itlo; - if(bus == load->GetParentList()[0] && load->IsOnline()) { + if(bus == load->GetParentList()[0] && load->IsOnline()) { LoadElectricalData data = load->GetPUElectricalData(systemPowerBase); if(data.loadType == CONST_IMPEDANCE) yBus[busNumber][busNumber] += std::complex<double>(data.activePower, -data.reactivePower); @@ -177,3 +177,185 @@ bool ElectricCalculation::GetYBus(std::vector<std::vector<std::complex<double> > return true; } + +void ElectricCalculation::ValidateElementsPowerFlow(std::vector<std::complex<double> > voltage, + std::vector<std::complex<double> > power, + double systemPowerBase) +{ + std::vector<std::vector<int> > lineMap; + std::vector<std::vector<int> > transfomerMap; + lineMap.resize(m_lineList.size()); + transfomerMap.resize(m_transformerList.size()); + + // Bus voltage and connections maps + for(int i = 0; i < (int)m_busList.size(); i++) { + BusElectricalData data = m_busList[i]->GetEletricalData(); + data.voltage = voltage[i]; + m_busList[i]->SetElectricalData(data); + + // Get power line connection map + for(int j = 0; j < (int)m_lineList.size(); j++) { + for(int k = 0; k < (int)m_lineList[j]->GetParentList().size(); k++) { + if(bus == m_lineList[j]->GetParentList()[k]) lineMap[j].push_back(i); + } + } + + // Get transformer connection map + for(int j = 0; j < (int)m_transformerList.size(); j++) { + for(int k = 0; k < (int)m_transformerList[j]->GetParentList().size(); k++) { + if(bus == m_transformerList[j]->GetParentList()[k]) transfomerMap[j].push_back(i); + } + } + } + + // Power line + for(int i = 0; i < (int)m_lineList.size(); i++) { + if(m_lineList[i]->IsOnline()) { + LineElectricalData data = m_lineList[i]->GetEletricalData(); + std::complex<double> v1 = voltage[lineMap[i][0]]; + std::complex<double> v2 = voltage[lineMap[i][1]]; + + data.current[0] = (v1 - v2) / std::complex<double>(data.resistance, data.indReactance) + + v1 * std::complex<double>(0.0, data.capSusceptance / 2.0); + data.current[1] = (v2 - v1) / std::complex<double>(data.resistance, data.indReactance) + + v2 * std::complex<double>(0.0, data.capSusceptance / 2.0); + + data.powerFlow[0] = v1 * std::conj(data.current[0]); + data.powerFlow[1] = v2 * std::conj(data.current[1]); + + m_lineList[i]->SetElectricalData(data); + } + } + + // Transformer + for(int i = 0; i < (int)m_transformerList.size(); i++) { + if(m_transformerList[i]->IsOnline()) { + TransformerElectricalData data = m_transformerList[i]->GetElectricalData(); + std::complex<double> v1 = voltage[transfomerMap[i][0]]; // Primary voltage + std::complex<double> v2 = voltage[transfomerMap[i][1]]; // Secondary voltage + + // Transformer admitance + std::complex<double> y = 1.0 / std::complex<double>(data.resistance, data.indReactance); + + if(data.turnsRatio == 1.0 && data.phaseShift == 0.0) { + data.current[0] = (v1 - v2) * y; + data.current[1] = (v2 - v1) * y; + } else { + double radPS = wxDegToRad(data.phaseShift); + std::complex<double> a = + std::complex<double>(data.turnsRatio * std::cos(radPS), -data.turnsRatio * std::sin(radPS)); + + data.current[0] = v1 * (y / std::pow(std::abs(a), 2)) - v2 * (y / std::conj(a)); + data.current[1] = -v1 * (y / a) + v2 * y; + } + + data.powerFlow[0] = v1 * std::conj(data.current[0]); + data.powerFlow[1] = v2 * std::conj(data.current[1]); + + m_transformerList[i]->SetElectricalData(data); + } + } + + // Synchronous machines + for(int i = 0; i < (int)m_busList.size(); i++) { + Bus* bus = m_busList[i]; + BusElectricalData data = bus->GetElectricalData(); + + // Get the synchronous machines connected and calculate the load power on the bus. + std::vector<SyncGenerator*> syncGeneratorsOnBus; + std::vector<SyncMotor*> syncMotorsOnBus; + std::complex<double> loadPower(0.0, 0.0); + for(auto itsg = m_syncGeneratorList.begin(); itsg != m_syncGeneratorList.end(); itsg++) { + SyncGenerator* syncGenerator = *itsg; + if(bus == syncGenerator->GetParentList()[0]) syncGeneratorsOnBus.push_back(syncGenerator); + } + for(auto itsm = m_syncMotorList.begin(); itsm != m_syncMotorList.end(); itsm++) { + SyncMotor* syncMotor = *itsm; + if(bus == syncMotor->GetParentList()[0]) { + syncMotorsOnBus.push_back(syncMotor); + SyncMotorElectricalData childData = syncMotor->GetPUElectricalData(systemPowerBase); + loadPower += std::complex<double>(childData.activePower, 0.0); + } + } + for(auto itlo = m_loadList.begin(); itlo != m_loadList.end(); itlo++) { + Load* load = itlo; + if(bus == load->GetParentList()[0]) { + LoadElectricalData childData = load->GetPUElectricalData(systemPowerBase); + loadPower += std::complex<double>(childData.activePower, childData.reactivePower); + } + } + for(auto itim = m_indMotorList.begin(); itim != m_indMotorList.end(); itim++) { + IndMotor* indMotor = itim; + if(bus == indMotor->GetParentList()[0]) { + LoadElectricalData childData = indMotor->GetPUElectricalData(systemPowerBase); + if(childData.loadType == CONST_POWER) + loadPower += std::complex<double>(childData.activePower, childData.reactivePower); + else if(childData.loadType == CONST_IMPEDANCE) + loadPower += std::pow(std::abs(voltage[i]), 2) * + std::complex<double>(childData.activePower, childData.reactivePower); + } + } + for(auto itim = m_indMotorList.begin(); itim != m_indMotorList.end(); itim++) { + IndMotor* indMotor = itim; + if(bus == indMotor->GetParentList()[0]) { + IndMotorElectricalData childData = indMotor->GetPUElectricalData(systemPowerBase); + loadPower += std::complex<double>(childData.activePower, childData.reactivePower); + } + } + for(auto itca = m_capacitorList.begin(); itca != m_capacitorList.end(); itca++) { + Capacitor* capacitor = itca; + if(bus == capacitor->GetParentList()[0]) { + CapacitorElectricalData childData = capacitor->GetPUElectricalData(systemPowerBase); + loadPower += std::pow(std::abs(voltage[i]), 2) * std::complex<double>(0.0, -childData.reactivePower); + } + } + for(auto itin = m_capacitorList.begin(); itin != m_capacitorList.end(); itin++) { + Inductor* inductor = itin; + if(bus == inductor->GetParentList()[0]) { + InductorElectricalData childData = inductor->GetPUElectricalData(systemPowerBase); + loadPower += std::pow(std::abs(voltage[i]), 2) * std::complex<double>(0.0, childData.reactivePower); + } + } + + // Set the sync generator power + for(auto itsg = syncGeneratorsOnBus.begin(); itsg != syncGeneratorsOnBus.end(); itsg++) { + SyncGenerator* generator = *itsg; + SyncGeneratorElectricalData childData = generator->GetElectricalData(); + + if(data.slackBus) { + double activePower = + (power[i].real() + loadPower.real()) * systemPowerBase / (double)(syncGeneratorsOnBus.size()); + + switch(childData.activePowerUnit) { + case UNIT_kW: { + activePower /= 1e3; + } break; + case UNIT_MW: { + activePower /= 1e6; + } break; + default: break; + } + childData.activePower = activePower; + } + double reactivePower = (power[i].imag() + loadPower.imag()) * systemPowerBase / + (double)(syncGeneratorsOnBus.size() + syncMotorsOnBus.size()); + switch(childData.reactivePowerUnit) { + case UNIT_kVAr: { + reactivePower /= 1e3; + } break; + case UNIT_MVAr: { + reactivePower /= 1e6; + } break; + default: break; + } + childData.reactivePower = reactivePower; + + generator->SetElectricalData(childData); + } + + // continua... + // falta o compensador sincrono + // verificar se eh necessario os tipos de barra nesse metodo. + // Tavez soh pode mudar a potencia reative em maquinas conectadas em barras PV?? --> TESTAR + } +} diff --git a/Project/ElectricCalculation.h b/Project/ElectricCalculation.h index 1bb6361..16a761a 100644 --- a/Project/ElectricCalculation.h +++ b/Project/ElectricCalculation.h @@ -22,6 +22,7 @@ class ElectricCalculation ~ElectricCalculation(); virtual void GetElementsFromList(std::vector<Element*> elementList); virtual bool GetYBus(std::vector<std::vector<std::complex<double> > >& yBus, double systemPowerBase); + virtual void ValidateElementsPowerFlow(std::vector<std::complex<double> > voltage, std::vector<std::complex<double> > power, double systemPowerBase); protected: std::vector<Bus*> m_busList; diff --git a/Project/Element.cpp b/Project/Element.cpp index 91ed61f..8ced79b 100644 --- a/Project/Element.cpp +++ b/Project/Element.cpp @@ -434,7 +434,7 @@ void Element::CalculatePowerFlowPts(std::vector<wxPoint2DDouble> edges) void Element::DrawPowerFlowPts() const { - glColor4d(1.0, 0.55, 0.0, 1.0); + glColor4d(1.0, 0.51, 0.0, 1.0); for(int i = 0; i < (int)m_powerFlowArrow.size(); i++) { DrawTriangle(m_powerFlowArrow[i]); } diff --git a/Project/Line.h b/Project/Line.h index 2310126..7e50fc7 100644 --- a/Project/Line.h +++ b/Project/Line.h @@ -20,7 +20,8 @@ struct LineElectricalData { double lineSize = 100.0; bool useLinePower = false; - // Power flow + // Power flow (p.u.) + std::complex<double> current[2] = {std::complex<double>(0.0, 0.0), std::complex<double>(0.0, 0.0)}; std::complex<double> powerFlow[2] = {std::complex<double>(0.0, 0.0), std::complex<double>(0.0, 0.0)}; // Fault diff --git a/Project/PowerFlow.cpp b/Project/PowerFlow.cpp index 69bfd66..40ee498 100644 --- a/Project/PowerFlow.cpp +++ b/Project/PowerFlow.cpp @@ -10,9 +10,9 @@ bool PowerFlow::RunGaussSeidel(double systemPowerBase, { // Calculate the Ybus. if(!GetYBus(m_yBus, systemPowerBase)) { - m_errorMsg = _("No buses found on the system."); - return false; - } + m_errorMsg = _("No buses found on the system."); + return false; + } // Number of buses on the system. int numberOfBuses = (int)m_busList.size(); @@ -23,123 +23,112 @@ bool PowerFlow::RunGaussSeidel(double systemPowerBase, int busNumber = 0; for(auto itb = m_busList.begin(); itb != m_busList.end(); itb++) { - Bus* bus = *itb; - BusElectricalData data = bus->GetEletricalData(); - - // Fill the bus type - if(data.slackBus) busType.push_back(BUS_SLACK); - // If the bus have controlled voltage, check if at least one synchronous machine is connected, then set the - // bus type. - else if(data.isVoltageControlled) - { - bool hasSyncMachine = false; - // Synchronous generator - for(auto itsg = m_syncGeneratorList.begin(); itsg != m_syncGeneratorList.end(); itsg++) { - SyncGenerator* syncGenerator = *itsg; - if(bus == syncGenerator->GetParentList()[0] && syncGenerator->IsOnline()) - hasSyncMachine = true; - } - // Synchronous motor - for(auto itsm = m_syncMotorList.begin(); itsm != m_syncMotorList.end(); itsm++) { - SyncMotor* syncMotor = *itsm; - if(bus == syncMotor->GetParentList()[0] && syncMotor->IsOnline()) hasSyncMachine = true; - } - if(hasSyncMachine) - busType.push_back(BUS_PV); - else - busType.push_back(BUS_PQ); - } - else - busType.push_back(BUS_PQ); - - // Fill the voltages array - if(data.isVoltageControlled && busType[busNumber] != BUS_PQ) { - voltage.push_back(std::complex<double>(data.controlledVoltage, 0.0)); - } - else - { - voltage.push_back(std::complex<double>(1.0, 0.0)); - } - - // Fill the power array - power.push_back(std::complex<double>(0.0, 0.0)); // Initial value - - // Synchronous generator - for(auto itsg = m_syncGeneratorList.begin(); itsg != m_syncGeneratorList.end(); itsg++) { - SyncGenerator* syncGenerator = *itsg; - if(syncGenerator->IsOnline()) { - if(bus == syncGenerator->GetParentList()[0]) { - SyncGeneratorElectricalData childData = - syncGenerator->GetPUElectricalData(systemPowerBase); - power[busNumber] += - std::complex<double>(childData.activePower, childData.reactivePower); - } - } - } - // Synchronous motor - for(auto itsm = m_syncMotorList.begin(); itsm != m_syncMotorList.end(); itsm++) { - SyncMotor* syncMotor = *itsm; - if(syncMotor->IsOnline()) { - if(bus == syncMotor->GetParentList()[0]) { - SyncMotorElectricalData childData = syncMotor->GetPUElectricalData(systemPowerBase); - power[busNumber] += - std::complex<double>(-childData.activePower, childData.reactivePower); - } - } - } - // Load - for(auto itl = m_loadList.begin(); itl != m_loadList.end(); itl++) { - Load* load = *itl; - if(load->IsOnline()) { - if(bus == load->GetParentList()[0]) { - LoadElectricalData childData = load->GetPUElectricalData(systemPowerBase); - if(childData.loadType == CONST_POWER) - power[busNumber] += - std::complex<double>(-childData.activePower, -childData.reactivePower); - } - } - } - - // Induction motor - for(auto itim = m_indMotorList.begin(); itim != m_indMotorList.end(); itim++) { - IndMotor* indMotor = *itim; - if(indMotor->IsOnline()) { - if(bus == indMotor->GetParentList()[0]) { - IndMotorElectricalData childData = indMotor->GetPUElectricalData(systemPowerBase); - power[busNumber] += - std::complex<double>(-childData.activePower, -childData.reactivePower); - } - } - } - - busNumber++; - } + Bus* bus = *itb; + BusElectricalData data = bus->GetEletricalData(); + + // Fill the bus type + if(data.slackBus) busType.push_back(BUS_SLACK); + // If the bus have controlled voltage, check if at least one synchronous machine is connected, then set the + // bus type. + else if(data.isVoltageControlled) { + bool hasSyncMachine = false; + // Synchronous generator + for(auto itsg = m_syncGeneratorList.begin(); itsg != m_syncGeneratorList.end(); itsg++) { + SyncGenerator* syncGenerator = *itsg; + if(bus == syncGenerator->GetParentList()[0] && syncGenerator->IsOnline()) hasSyncMachine = true; + } + // Synchronous motor + for(auto itsm = m_syncMotorList.begin(); itsm != m_syncMotorList.end(); itsm++) { + SyncMotor* syncMotor = *itsm; + if(bus == syncMotor->GetParentList()[0] && syncMotor->IsOnline()) hasSyncMachine = true; + } + if(hasSyncMachine) + busType.push_back(BUS_PV); + else + busType.push_back(BUS_PQ); + } else + busType.push_back(BUS_PQ); + + // Fill the voltages array + if(data.isVoltageControlled && busType[busNumber] != BUS_PQ) { + voltage.push_back(std::complex<double>(data.controlledVoltage, 0.0)); + } else { + voltage.push_back(std::complex<double>(1.0, 0.0)); + } + + // Fill the power array + power.push_back(std::complex<double>(0.0, 0.0)); // Initial value + + // Synchronous generator + for(auto itsg = m_syncGeneratorList.begin(); itsg != m_syncGeneratorList.end(); itsg++) { + SyncGenerator* syncGenerator = *itsg; + if(syncGenerator->IsOnline()) { + if(bus == syncGenerator->GetParentList()[0]) { + SyncGeneratorElectricalData childData = syncGenerator->GetPUElectricalData(systemPowerBase); + power[busNumber] += std::complex<double>(childData.activePower, childData.reactivePower); + } + } + } + // Synchronous motor + for(auto itsm = m_syncMotorList.begin(); itsm != m_syncMotorList.end(); itsm++) { + SyncMotor* syncMotor = *itsm; + if(syncMotor->IsOnline()) { + if(bus == syncMotor->GetParentList()[0]) { + SyncMotorElectricalData childData = syncMotor->GetPUElectricalData(systemPowerBase); + power[busNumber] += std::complex<double>(-childData.activePower, childData.reactivePower); + } + } + } + // Load + for(auto itl = m_loadList.begin(); itl != m_loadList.end(); itl++) { + Load* load = *itl; + if(load->IsOnline()) { + if(bus == load->GetParentList()[0]) { + LoadElectricalData childData = load->GetPUElectricalData(systemPowerBase); + if(childData.loadType == CONST_POWER) + power[busNumber] += std::complex<double>(-childData.activePower, -childData.reactivePower); + } + } + } + + // Induction motor + for(auto itim = m_indMotorList.begin(); itim != m_indMotorList.end(); itim++) { + IndMotor* indMotor = *itim; + if(indMotor->IsOnline()) { + if(bus == indMotor->GetParentList()[0]) { + IndMotorElectricalData childData = indMotor->GetPUElectricalData(systemPowerBase); + power[busNumber] += std::complex<double>(-childData.activePower, -childData.reactivePower); + } + } + } + + busNumber++; + } // Check if have slack bus and if have generation on the slack bus bool haveSlackBus = false; bool slackBusHaveGeneration = false; for(int i = 0; i < (int)busType.size(); i++) { - if(busType[i] == BUS_SLACK) { - auto itb = m_busList.begin(); - std::advance(itb, i); - Bus* bus = *itb; - - for(auto itsg = m_syncGeneratorList.begin(); itsg != m_syncGeneratorList.end(); itsg++) { - SyncGenerator* syncGenerator = *itsg; - if(syncGenerator->IsOnline() && bus == syncGenerator->GetParentList()[0]) - slackBusHaveGeneration = true; - } - haveSlackBus = true; - } - if(!haveSlackBus) { - m_errorMsg = _("There is no slack bus on the system."); - return false; - } - if(!slackBusHaveGeneration) { - m_errorMsg = _("The slack bus don't have generation."); - return false; - } - } + if(busType[i] == BUS_SLACK) { + auto itb = m_busList.begin(); + std::advance(itb, i); + Bus* bus = *itb; + + for(auto itsg = m_syncGeneratorList.begin(); itsg != m_syncGeneratorList.end(); itsg++) { + SyncGenerator* syncGenerator = *itsg; + if(syncGenerator->IsOnline() && bus == syncGenerator->GetParentList()[0]) slackBusHaveGeneration = true; + } + haveSlackBus = true; + } + if(!haveSlackBus) { + m_errorMsg = _("There is no slack bus on the system."); + return false; + } + if(!slackBusHaveGeneration) { + m_errorMsg = _("The slack bus don't have generation."); + return false; + } + } // Gauss-Seidel method std::vector<std::complex<double> > oldVoltage; // Old voltage array. @@ -148,98 +137,98 @@ bool PowerFlow::RunGaussSeidel(double systemPowerBase, int iteration = 0; // Current itaration number. while(true) { - // Reach the max number of iterations. - if(iteration >= maxIteration) { - m_errorMsg = _("The maximum number of iterations was reached."); - return false; - } - - // Update the old voltage array to current iteration values. - for(int i = 0; i < numberOfBuses; i++) oldVoltage[i] = voltage[i]; - - double iterationError = 0.0; - - for(int i = 0; i < numberOfBuses; i++) { - if(busType[i] == BUS_PQ) { - std::complex<double> yeSum(0.0, 0.0); - for(int k = 0; k < numberOfBuses; k++) { - if(i != k) { - // Sum { Y[i,k] * E[k] } | k = 1->n; k diff i - yeSum += m_yBus[i][k] * voltage[k]; - } - } - - // E[i] = (1/Y[i,i])*((P[i]-jQ[i])/E*[i] - Sum { Y[i,k] * E[k] (k diff i) }) - std::complex<double> newVolt = - (1.0 / m_yBus[i][i]) * (std::conj(power[i]) / std::conj(voltage[i]) - yeSum); - - // Apply the acceleration factor. - newVolt = std::complex<double>( - accFactor * (newVolt.real() - voltage[i].real()) + voltage[i].real(), - accFactor * (newVolt.imag() - voltage[i].imag()) + voltage[i].imag()); - - voltage[i] = newVolt; - } - if(busType[i] == BUS_PV) { - std::complex<double> yeSum(0.0, 0.0); - for(int k = 0; k < numberOfBuses; k++) { - if(i != k) { - // Sum { Y[i,k] * E[k] } | k = 1->n; k diff i - yeSum += m_yBus[i][k] * voltage[k]; - } - } - std::complex<double> yeSumT = yeSum + (m_yBus[i][i] * voltage[i]); - - // Q[i] = - Im( E*[i] * Sum { Y[i,k] * E[k] } ) - std::complex<double> qCalc = std::conj(voltage[i]) * yeSumT; - power[i] = std::complex<double>(power[i].real(), -qCalc.imag()); - - // E[i] = (1/Y[i,i])*((P[i]-jQ[i])/E*[i] - Sum { Y[i,k] * E[k] (k diff i) }) - std::complex<double> newVolt = - (1.0 / m_yBus[i][i]) * (std::conj(power[i]) / std::conj(voltage[i]) - yeSum); - - // Apply the acceleration factor. - newVolt = std::complex<double>( - accFactor * (newVolt.real() - voltage[i].real()) + voltage[i].real(), - accFactor * (newVolt.imag() - voltage[i].imag()) + voltage[i].imag()); - - // Keep the same voltage magnitude. - voltage[i] = std::complex<double>(std::abs(voltage[i]) * std::cos(std::arg(newVolt)), - std::abs(voltage[i]) * std::sin(std::arg(newVolt))); - } - - double busError = std::max(std::abs(voltage[i].real() - oldVoltage[i].real()), - std::abs(voltage[i].imag() - oldVoltage[i].imag())); - - if(busError > iterationError) iterationError = busError; - } - - if(iterationError < error) break; - - iteration++; - } + // Reach the max number of iterations. + if(iteration >= maxIteration) { + m_errorMsg = _("The maximum number of iterations was reached."); + return false; + } + + // Update the old voltage array to current iteration values. + for(int i = 0; i < numberOfBuses; i++) oldVoltage[i] = voltage[i]; + + double iterationError = 0.0; + + for(int i = 0; i < numberOfBuses; i++) { + if(busType[i] == BUS_PQ) { + std::complex<double> yeSum(0.0, 0.0); + for(int k = 0; k < numberOfBuses; k++) { + if(i != k) { + // Sum { Y[i,k] * E[k] } | k = 1->n; k diff i + yeSum += m_yBus[i][k] * voltage[k]; + } + } + + // E[i] = (1/Y[i,i])*((P[i]-jQ[i])/E*[i] - Sum { Y[i,k] * E[k] (k diff i) }) + std::complex<double> newVolt = + (1.0 / m_yBus[i][i]) * (std::conj(power[i]) / std::conj(voltage[i]) - yeSum); + + // Apply the acceleration factor. + newVolt = std::complex<double>(accFactor * (newVolt.real() - voltage[i].real()) + voltage[i].real(), + accFactor * (newVolt.imag() - voltage[i].imag()) + voltage[i].imag()); + + voltage[i] = newVolt; + } + if(busType[i] == BUS_PV) { + std::complex<double> yeSum(0.0, 0.0); + for(int k = 0; k < numberOfBuses; k++) { + if(i != k) { + // Sum { Y[i,k] * E[k] } | k = 1->n; k diff i + yeSum += m_yBus[i][k] * voltage[k]; + } + } + std::complex<double> yeSumT = yeSum + (m_yBus[i][i] * voltage[i]); + + // Q[i] = - Im( E*[i] * Sum { Y[i,k] * E[k] } ) + std::complex<double> qCalc = std::conj(voltage[i]) * yeSumT; + power[i] = std::complex<double>(power[i].real(), -qCalc.imag()); + + // E[i] = (1/Y[i,i])*((P[i]-jQ[i])/E*[i] - Sum { Y[i,k] * E[k] (k diff i) }) + std::complex<double> newVolt = + (1.0 / m_yBus[i][i]) * (std::conj(power[i]) / std::conj(voltage[i]) - yeSum); + + // Apply the acceleration factor. + newVolt = std::complex<double>(accFactor * (newVolt.real() - voltage[i].real()) + voltage[i].real(), + accFactor * (newVolt.imag() - voltage[i].imag()) + voltage[i].imag()); + + // Keep the same voltage magnitude. + voltage[i] = std::complex<double>(std::abs(voltage[i]) * std::cos(std::arg(newVolt)), + std::abs(voltage[i]) * std::sin(std::arg(newVolt))); + } + + double busError = std::max(std::abs(voltage[i].real() - oldVoltage[i].real()), + std::abs(voltage[i].imag() - oldVoltage[i].imag())); + + if(busError > iterationError) iterationError = busError; + } + + if(iterationError < error) break; + + iteration++; + } // Adjust the power array. // TODO: Only the slack bus?? for(int i = 0; i < numberOfBuses; i++) { - std::complex<double> sBus = std::complex<double>(0.0, 0.0); - for(int j = 0; j < numberOfBuses; j++) sBus += voltage[i] * std::conj(voltage[j]) * std::conj(m_yBus[i][j]); - power[i] = sBus; - } + std::complex<double> sBus = std::complex<double>(0.0, 0.0); + for(int j = 0; j < numberOfBuses; j++) sBus += voltage[i] * std::conj(voltage[j]) * std::conj(m_yBus[i][j]); + power[i] = sBus; + } - wxString str = ""; + /*wxString str = ""; for(int i = 0; i < numberOfBuses; i++) { - str += wxString::Format("%.5f/_%.2f\n", std::abs(voltage[i]), wxRadToDeg(std::arg(voltage[i]))); - } + str += wxString::Format("%.5f/_%.2f\n", std::abs(voltage[i]), wxRadToDeg(std::arg(voltage[i]))); + } wxLogMessage(str); str = ""; for(int i = 0; i < numberOfBuses; i++) { - str += wxString::Format("%.5f + j%.5f\n", power[i].real(), power[i].imag()); - } + str += wxString::Format("%.5f + j%.5f\n", power[i].real(), power[i].imag()); + } wxLogMessage(str); - wxLogMessage(wxString::Format("Num iteracoes = %d", iteration)); + wxLogMessage(wxString::Format("Num iteracoes = %d", iteration));*/ + + ValidateElementsPowerFlow(voltage, power, systemPowerBase); return true; } diff --git a/Project/PowerFlow.h b/Project/PowerFlow.h index b30b82f..ac27c7e 100644 --- a/Project/PowerFlow.h +++ b/Project/PowerFlow.h @@ -4,28 +4,26 @@ #include "ElectricCalculation.h" #include <wx/string.h> -#include <wx/intl.h>//_() -#include <wx/log.h>//temp +#include <wx/intl.h> //_() +#include <wx/log.h> //temp -enum BusType -{ - BUS_SLACK = 0, - BUS_PV, - BUS_PQ -}; +enum BusType { BUS_SLACK = 0, BUS_PV, BUS_PQ }; class PowerFlow : public ElectricCalculation { public: PowerFlow(std::vector<Element*> elementList); ~PowerFlow(); - virtual bool RunGaussSeidel(double systemPowerBase = 100e6, int maxIteration = 5000, double error = 1e-6, double initAngle = 0.0, double accFactor = 1.0); - - virtual wxString GetErrorMessage() { return m_errorMsg; } + virtual bool RunGaussSeidel(double systemPowerBase = 100e6, + int maxIteration = 5000, + double error = 1e-6, + double initAngle = 0.0, + double accFactor = 1.0); + virtual wxString GetErrorMessage() { return m_errorMsg; } protected: std::vector<std::vector<std::complex<double> > > m_yBus; - wxString m_errorMsg = ""; + wxString m_errorMsg = ""; }; #endif // POWERFLOW_H diff --git a/Project/Project.mk b/Project/Project.mk index 91fd3d2..dce9c8b 100644 --- a/Project/Project.mk +++ b/Project/Project.mk @@ -13,8 +13,8 @@ CurrentFileName := CurrentFilePath := CurrentFileFullPath := User :=Thales -Date :=02/11/2016 -CodeLitePath :="C:/Program Files (x86)/CodeLite" +Date :=03/11/2016 +CodeLitePath :="C:/Program Files/CodeLite" LinkerName :=C:/TDM-GCC-64/bin/g++.exe SharedObjectLinkerName :=C:/TDM-GCC-64/bin/g++.exe -shared -fPIC ObjectSuffix :=.o @@ -61,8 +61,7 @@ AS := C:/TDM-GCC-64/bin/as.exe ## ## User defined environment variables ## -CodeLiteDir:=C:\Program Files (x86)\CodeLite -UNIT_TEST_PP_SRC_DIR:=C:\UnitTest++-1.3 +CodeLiteDir:=C:\Program Files\CodeLite WXWIN:=C:\wxWidgets-3.1.0 WXCFG:=gcc_dll\mswu Objects0=$(IntermediateDirectory)/main.cpp$(ObjectSuffix) $(IntermediateDirectory)/win_resources.rc$(ObjectSuffix) $(IntermediateDirectory)/ArtMetro.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrame.cpp$(ObjectSuffix) $(IntermediateDirectory)/Workspace.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrameBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/WorkspaceBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/BusFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrameBase.cpp$(ObjectSuffix) \ diff --git a/Project/Release/Bus.cpp.o b/Project/Release/Bus.cpp.o Binary files differindex ddced0e..819b36a 100644 --- a/Project/Release/Bus.cpp.o +++ b/Project/Release/Bus.cpp.o diff --git a/Project/Release/BusForm.cpp.o b/Project/Release/BusForm.cpp.o Binary files differindex 15a25e0..78956f9 100644 --- a/Project/Release/BusForm.cpp.o +++ b/Project/Release/BusForm.cpp.o diff --git a/Project/Release/ElectricCalculation.cpp.o b/Project/Release/ElectricCalculation.cpp.o Binary files differindex 7d07747..74bf55a 100644 --- a/Project/Release/ElectricCalculation.cpp.o +++ b/Project/Release/ElectricCalculation.cpp.o diff --git a/Project/Release/Element.cpp.o b/Project/Release/Element.cpp.o Binary files differindex 6833467..b4b995e 100644 --- a/Project/Release/Element.cpp.o +++ b/Project/Release/Element.cpp.o diff --git a/Project/Release/Line.cpp.o b/Project/Release/Line.cpp.o Binary files differindex bd3ca4f..4c29ca5 100644 --- a/Project/Release/Line.cpp.o +++ b/Project/Release/Line.cpp.o diff --git a/Project/Release/MainFrame.cpp.o b/Project/Release/MainFrame.cpp.o Binary files differindex cc2e810..d1ed29c 100644 --- a/Project/Release/MainFrame.cpp.o +++ b/Project/Release/MainFrame.cpp.o diff --git a/Project/Release/PSP-UFU.exe b/Project/Release/PSP-UFU.exe Binary files differindex d985df0..d79044d 100644 --- a/Project/Release/PSP-UFU.exe +++ b/Project/Release/PSP-UFU.exe diff --git a/Project/Release/PowerFlow.cpp.o b/Project/Release/PowerFlow.cpp.o Binary files differindex a90fde4..b9e6e19 100644 --- a/Project/Release/PowerFlow.cpp.o +++ b/Project/Release/PowerFlow.cpp.o diff --git a/Project/Release/Workspace.cpp.o b/Project/Release/Workspace.cpp.o Binary files differindex 3bc5af2..54e888d 100644 --- a/Project/Release/Workspace.cpp.o +++ b/Project/Release/Workspace.cpp.o diff --git a/Project/Transformer.h b/Project/Transformer.h index cf9393f..7c6f14e 100644 --- a/Project/Transformer.h +++ b/Project/Transformer.h @@ -35,6 +35,10 @@ struct TransformerElectricalData { double turnsRatio = 1.0; double phaseShift = 0.0; bool useTransformerPower = false; + + // Power flow (p.u.) + std::complex<double> current[2] = {std::complex<double>(0.0, 0.0), std::complex<double>(0.0, 0.0)}; + std::complex<double> powerFlow[2] = {std::complex<double>(0.0, 0.0), std::complex<double>(0.0, 0.0)}; // Fault double zeroResistance = 0.0; |