22#include "../controlElement/ControlElementContainer.h"
23#include "../controlElement/ControlElementSolver.h"
25#include "../../forms/SyncMachineForm.h"
27#include "../../editors/Workspace.h"
29#include "../../utils/PropertiesData.h"
31SyncGenerator::SyncGenerator() :
Machines() {
32 m_elementType = TYPE_SYNC_GENERATOR;
35SyncGenerator::SyncGenerator(wxString name) :
Machines()
37 m_elementType = TYPE_SYNC_GENERATOR;
39 m_electricalData.name = name;
42SyncGenerator::~SyncGenerator()
44 if (m_electricalData.avr)
delete m_electricalData.avr;
45 if (m_electricalData.speedGov)
delete m_electricalData.speedGov;
50void SyncGenerator::Init()
55 double pi = 3.14159265359;
57 for (
int i = 0; i <= numPtsSine; i++) {
58 double x = (2.0 * pi / double(numPtsSine)) *
double(i) - pi;
59 double y = std::sin(x);
60 m_sinePts.push_back(wxPoint2DDouble((x / pi) * mx, y * my));
75void SyncGenerator::DrawDCSymbol(wxGraphicsContext* gc)
const
78 std::vector<wxPoint2DDouble> sinePts;
79 for (
unsigned int i = 0; i < m_sinePts.size(); i++) { sinePts.push_back(m_sinePts[i] + m_position); }
80 gc->StrokeLines(sinePts.size(), &sinePts[0]);
83void SyncGenerator::DrawDCSymbol(wxDC& dc)
const
85 std::vector<wxPoint> sinePts;
86 wxPoint pos = wxPoint(wxRound(m_position.m_x), wxRound(m_position.m_y));
87 for (
unsigned int i = 0; i < m_sinePts.size(); i++) { sinePts.push_back(wxPoint(wxRound(m_sinePts[i].m_x), wxRound(m_sinePts[i].m_y)) + pos); }
88 dc.DrawLines(sinePts.size(), &sinePts[0]);
95 wxMenu* textMenu =
new wxMenu();
97 textMenu->Append(ID_TXT_NAME, _(
"Name"));
98 textMenu->Append(ID_TXT_ACTIVE_POWER, _(
"Active power"));
99 textMenu->Append(ID_TXT_REACTIVE_POWER, _(
"Reactive power"));
100 textMenu->Append(ID_TXT_FAULTCURRENT, _(
"Fault current"));
101 textMenu->SetClientData(menu.GetClientData());
102 menu.AppendSubMenu(textMenu, _(
"Add text"));
111 SyncMachineForm generatorForm(parent,
this,
static_cast<int>(ws->GetProperties()->GetGeneralPropertiesData().plotLib));
112 generatorForm.SetTitle(_(
"Generator"));
113 generatorForm.CenterOnParent();
114 if (generatorForm.ShowModal() == wxID_OK) {
123 double machineBasePower = 1.0;
124 if (data.useMachineBase) { machineBasePower = GetValueFromUnit(data.nominalPower, data.nominalPowerUnit); }
127 double activePower = GetValueFromUnit(data.activePower, data.activePowerUnit);
128 if (!m_online) activePower = 0.0;
130 if (data.useMachineBase) data.activePower = (activePower * machineBasePower) / systemPowerBase;
133 data.activePower = activePower / systemPowerBase;
138 double reactivePower = GetValueFromUnit(data.reactivePower, data.reactivePowerUnit);
139 if (!m_online) reactivePower = 0.0;
141 if (data.useMachineBase) data.reactivePower = (reactivePower * machineBasePower) / systemPowerBase;
144 data.reactivePower = reactivePower / systemPowerBase;
149 double maxReactive = GetValueFromUnit(data.maxReactive, data.maxReactiveUnit);
151 if (data.useMachineBase) data.maxReactive = (maxReactive * machineBasePower) / systemPowerBase;
154 data.maxReactive = maxReactive / systemPowerBase;
159 double minReactive = GetValueFromUnit(data.minReactive, data.minReactiveUnit);
161 if (data.useMachineBase) data.minReactive = (minReactive * machineBasePower) / systemPowerBase;
164 data.minReactive = minReactive / systemPowerBase;
168 double baseVoltage = GetValueFromUnit(data.nominalVoltage, data.nominalVoltageUnit);
169 double systemBaseImpedance = (baseVoltage * baseVoltage) / systemPowerBase;
170 double machineBaseImpedance = (baseVoltage * baseVoltage) / machineBasePower;
173 if (data.useMachineBase) {
174 data.positiveResistance = (data.positiveResistance * machineBaseImpedance) / systemBaseImpedance;
175 data.positiveReactance = (data.positiveReactance * machineBaseImpedance) / systemBaseImpedance;
176 data.negativeResistance = (data.negativeResistance * machineBaseImpedance) / systemBaseImpedance;
177 data.negativeReactance = (data.negativeReactance * machineBaseImpedance) / systemBaseImpedance;
178 data.zeroResistance = (data.zeroResistance * machineBaseImpedance) / systemBaseImpedance;
179 data.zeroReactance = (data.zeroReactance * machineBaseImpedance) / systemBaseImpedance;
180 data.groundResistance = (data.groundResistance * machineBaseImpedance) / systemBaseImpedance;
181 data.groundReactance = (data.groundReactance * machineBaseImpedance) / systemBaseImpedance;
185 data.faultCurrent[0] = std::complex<double>(0, 0);
186 data.faultCurrent[1] = std::complex<double>(0, 0);
187 data.faultCurrent[2] = std::complex<double>(0, 0);
194 std::vector<ElectricalUnit> nominalVoltageUnit)
196 if (nominalVoltage.size() > 0) {
197 m_electricalData.nominalVoltage = nominalVoltage[0];
198 m_electricalData.nominalVoltageUnit = nominalVoltageUnit[0];
206 auto data = copy->GetElectricalData();
209 if (m_electricalData.avr)
211 std::vector<std::shared_ptr<ConnectionLine>> cLineList;
212 std::vector<std::shared_ptr<ControlElement>> elementList;
214 m_electricalData.avr->GetContainerCopy(elementList, cLineList);
217 avrCopy->FillContainer(elementList, cLineList);
226 if (m_electricalData.speedGov)
228 std::vector<std::shared_ptr<ConnectionLine>> cLineList;
229 std::vector<std::shared_ptr<ControlElement>> elementList;
231 m_electricalData.speedGov->GetContainerCopy(elementList, cLineList);
234 speedGovCopy->FillContainer(elementList, cLineList);
236 data.speedGov = speedGovCopy;
239 data.speedGov =
nullptr;
241 copy->SetElectricalData(data);
248 wxString tipText = m_electricalData.name;
250 double activePower = m_electricalData.activePower;
251 if (!m_online) activePower = 0.0;
252 tipText += _(
"\nP = ") + wxString::FromDouble(activePower, 5);
253 switch (m_electricalData.activePowerUnit) {
255 tipText += _(
" p.u.");
269 double reactivePower = m_electricalData.reactivePower;
270 if (!m_online) reactivePower = 0.0;
271 tipText += _(
"\nQ = ") + wxString::FromDouble(reactivePower, 5);
272 switch (m_electricalData.reactivePowerUnit) {
274 tipText += _(
" p.u.");
277 tipText += _(
" var");
280 tipText += _(
" kvar");
283 tipText += _(
" Mvar");
295 if (!m_electricalData.plotSyncMachine)
return false;
296 plotData.SetName(m_electricalData.name);
297 plotData.SetCurveType(ElementPlotData::CurveType::CT_SYNC_GENERATOR);
299 std::vector<double> absTerminalVoltage, activePower, reactivePower;
300 for (
unsigned int i = 0; i < m_electricalData.terminalVoltageVector.size(); ++i) {
301 activePower.push_back(std::real(m_electricalData.electricalPowerVector[i]));
302 reactivePower.push_back(std::imag(m_electricalData.electricalPowerVector[i]));
304 plotData.AddData(m_electricalData.terminalVoltageVector, _(
"Terminal voltage"));
305 plotData.AddData(activePower, _(
"Active power"));
306 plotData.AddData(reactivePower, _(
"Reactive power"));
307 plotData.AddData(m_electricalData.mechanicalPowerVector, _(
"Mechanical power"));
308 plotData.AddData(m_electricalData.freqVector, _(
"Frequency"));
309 plotData.AddData(m_electricalData.fieldVoltageVector, _(
"Field voltage"));
310 plotData.AddData(m_electricalData.deltaVector, _(
"Delta"));
316rapidxml::xml_node<>* SyncGenerator::SaveElement(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* elementListNode)
318 auto elementNode = XMLParser::AppendNode(doc, elementListNode,
"SyncGenerator");
319 XMLParser::SetNodeAttribute(doc, elementNode,
"ID", m_elementID);
321 SaveCADProperties(doc, elementNode);
322 auto electricalProp = XMLParser::AppendNode(doc, elementNode,
"ElectricalProperties");
323 auto isOnline = XMLParser::AppendNode(doc, electricalProp,
"IsOnline");
324 XMLParser::SetNodeValue(doc, isOnline, m_online);
325 auto name = XMLParser::AppendNode(doc, electricalProp,
"Name");
326 XMLParser::SetNodeValue(doc, name, m_electricalData.name);
327 auto nominalPower = XMLParser::AppendNode(doc, electricalProp,
"NominalPower");
328 XMLParser::SetNodeValue(doc, nominalPower, m_electricalData.nominalPower);
329 XMLParser::SetNodeAttribute(doc, nominalPower,
"UnitID",
static_cast<int>(m_electricalData.nominalPowerUnit));
330 auto nominalVoltage = XMLParser::AppendNode(doc, electricalProp,
"NominalVoltage");
331 XMLParser::SetNodeValue(doc, nominalVoltage, m_electricalData.nominalVoltage);
332 XMLParser::SetNodeAttribute(doc, nominalVoltage,
"UnitID",
static_cast<int>(m_electricalData.nominalVoltageUnit));
333 auto activePower = XMLParser::AppendNode(doc, electricalProp,
"ActivePower");
334 XMLParser::SetNodeValue(doc, activePower, m_electricalData.activePower);
335 XMLParser::SetNodeAttribute(doc, activePower,
"UnitID",
static_cast<int>(m_electricalData.activePowerUnit));
336 auto reactivePower = XMLParser::AppendNode(doc, electricalProp,
"ReactivePower");
337 XMLParser::SetNodeValue(doc, reactivePower, m_electricalData.reactivePower);
338 XMLParser::SetNodeAttribute(doc, reactivePower,
"UnitID",
static_cast<int>(m_electricalData.reactivePowerUnit));
339 auto haveMaxReactive = XMLParser::AppendNode(doc, electricalProp,
"HaveMaxReactive");
340 XMLParser::SetNodeValue(doc, haveMaxReactive, m_electricalData.haveMaxReactive);
341 auto maxReactive = XMLParser::AppendNode(doc, electricalProp,
"MaxReactive");
342 XMLParser::SetNodeValue(doc, maxReactive, m_electricalData.maxReactive);
343 XMLParser::SetNodeAttribute(doc, maxReactive,
"UnitID",
static_cast<int>(m_electricalData.maxReactiveUnit));
344 auto haveMinReactive = XMLParser::AppendNode(doc, electricalProp,
"HaveMinReactive");
345 XMLParser::SetNodeValue(doc, haveMinReactive, m_electricalData.haveMinReactive);
346 auto minReactive = XMLParser::AppendNode(doc, electricalProp,
"MinReactive");
347 XMLParser::SetNodeValue(doc, minReactive, m_electricalData.minReactive);
348 XMLParser::SetNodeAttribute(doc, minReactive,
"UnitID",
static_cast<int>(m_electricalData.minReactiveUnit));
349 auto useMachineBase = XMLParser::AppendNode(doc, electricalProp,
"UseMachineBase");
350 XMLParser::SetNodeValue(doc, useMachineBase, m_electricalData.useMachineBase);
352 auto fault = XMLParser::AppendNode(doc, electricalProp,
"Fault");
353 auto positiveResistance = XMLParser::AppendNode(doc, fault,
"PositiveResistance");
354 XMLParser::SetNodeValue(doc, positiveResistance, m_electricalData.positiveResistance);
355 auto positiveReactance = XMLParser::AppendNode(doc, fault,
"PositiveReactance");
356 XMLParser::SetNodeValue(doc, positiveReactance, m_electricalData.positiveReactance);
357 auto negativeResistance = XMLParser::AppendNode(doc, fault,
"NegativeResistance");
358 XMLParser::SetNodeValue(doc, negativeResistance, m_electricalData.negativeResistance);
359 auto negativeReactance = XMLParser::AppendNode(doc, fault,
"NegativeReactance");
360 XMLParser::SetNodeValue(doc, negativeReactance, m_electricalData.negativeReactance);
361 auto zeroResistance = XMLParser::AppendNode(doc, fault,
"ZeroResistance");
362 XMLParser::SetNodeValue(doc, zeroResistance, m_electricalData.zeroResistance);
363 auto zeroReactance = XMLParser::AppendNode(doc, fault,
"ZeroReactance");
364 XMLParser::SetNodeValue(doc, zeroReactance, m_electricalData.zeroReactance);
365 auto groundResistance = XMLParser::AppendNode(doc, fault,
"GroundResistance");
366 XMLParser::SetNodeValue(doc, groundResistance, m_electricalData.groundResistance);
367 auto groundReactance = XMLParser::AppendNode(doc, fault,
"GroundReactance");
368 XMLParser::SetNodeValue(doc, groundReactance, m_electricalData.groundReactance);
369 auto groundNeutral = XMLParser::AppendNode(doc, fault,
"GroundNeutral");
370 XMLParser::SetNodeValue(doc, groundNeutral, m_electricalData.groundNeutral);
372 auto stability = XMLParser::AppendNode(doc, electricalProp,
"Stability");
373 auto plotSyncMachine = XMLParser::AppendNode(doc, stability,
"PlotSyncMachine");
374 XMLParser::SetNodeValue(doc, plotSyncMachine, m_electricalData.plotSyncMachine);
375 auto inertia = XMLParser::AppendNode(doc, stability,
"Inertia");
376 XMLParser::SetNodeValue(doc, inertia, m_electricalData.inertia);
377 auto damping = XMLParser::AppendNode(doc, stability,
"Damping");
378 XMLParser::SetNodeValue(doc, damping, m_electricalData.damping);
379 auto useAVR = XMLParser::AppendNode(doc, stability,
"UseAVR");
380 XMLParser::SetNodeValue(doc, useAVR, m_electricalData.useAVR);
381 auto useSpeedGovernor = XMLParser::AppendNode(doc, stability,
"UseSpeedGovernor");
382 XMLParser::SetNodeValue(doc, useSpeedGovernor, m_electricalData.useSpeedGovernor);
383 auto armResistance = XMLParser::AppendNode(doc, stability,
"ArmResistance");
384 XMLParser::SetNodeValue(doc, armResistance, m_electricalData.armResistance);
385 auto potierReactance = XMLParser::AppendNode(doc, stability,
"PotierReactance");
386 XMLParser::SetNodeValue(doc, potierReactance, m_electricalData.potierReactance);
387 auto satFactor = XMLParser::AppendNode(doc, stability,
"SatFactor");
388 XMLParser::SetNodeValue(doc, satFactor, m_electricalData.satFactor);
389 auto syncXd = XMLParser::AppendNode(doc, stability,
"SyncXd");
390 XMLParser::SetNodeValue(doc, syncXd, m_electricalData.syncXd);
391 auto syncXq = XMLParser::AppendNode(doc, stability,
"SyncXq");
392 XMLParser::SetNodeValue(doc, syncXq, m_electricalData.syncXq);
393 auto transXd = XMLParser::AppendNode(doc, stability,
"TransXd");
394 XMLParser::SetNodeValue(doc, transXd, m_electricalData.transXd);
395 auto transXq = XMLParser::AppendNode(doc, stability,
"TransXq");
396 XMLParser::SetNodeValue(doc, transXq, m_electricalData.transXq);
397 auto transTd0 = XMLParser::AppendNode(doc, stability,
"TransTd0");
398 XMLParser::SetNodeValue(doc, transTd0, m_electricalData.transTd0);
399 auto transTq0 = XMLParser::AppendNode(doc, stability,
"TransTq0");
400 XMLParser::SetNodeValue(doc, transTq0, m_electricalData.transTq0);
401 auto subXd = XMLParser::AppendNode(doc, stability,
"SubXd");
402 XMLParser::SetNodeValue(doc, subXd, m_electricalData.subXd);
403 auto subXq = XMLParser::AppendNode(doc, stability,
"SubXq");
404 XMLParser::SetNodeValue(doc, subXq, m_electricalData.subXq);
405 auto subTd0 = XMLParser::AppendNode(doc, stability,
"SubTd0");
406 XMLParser::SetNodeValue(doc, subTd0, m_electricalData.subTd0);
407 auto subTq0 = XMLParser::AppendNode(doc, stability,
"SubTq0");
408 XMLParser::SetNodeValue(doc, subTq0, m_electricalData.subTq0);
410 SaveSwitchingData(doc, electricalProp);
414bool SyncGenerator::OpenElement(rapidxml::xml_node<>* elementNode, std::vector<Element*> parentList)
416 if (!OpenCADProperties(elementNode, parentList))
return false;
418 auto electricalProp = elementNode->first_node(
"ElectricalProperties");
419 if (!electricalProp)
return false;
421 SetOnline(XMLParser::GetNodeValueInt(electricalProp,
"IsOnline"));
422 m_electricalData.name = electricalProp->first_node(
"Name")->value();
423 m_electricalData.nominalPower = XMLParser::GetNodeValueDouble(electricalProp,
"NominalPower");
424 m_electricalData.nominalPowerUnit =
425 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"NominalPower",
"UnitID"));
426 m_electricalData.nominalVoltage = XMLParser::GetNodeValueDouble(electricalProp,
"NominalVoltage");
427 m_electricalData.nominalVoltageUnit =
428 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"NominalVoltage",
"UnitID"));
429 m_electricalData.activePower = XMLParser::GetNodeValueDouble(electricalProp,
"ActivePower");
430 m_electricalData.activePowerUnit =
431 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"ActivePower",
"UnitID"));
432 m_electricalData.reactivePower = XMLParser::GetNodeValueDouble(electricalProp,
"ReactivePower");
433 m_electricalData.reactivePowerUnit =
434 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"ReactivePower",
"UnitID"));
435 m_electricalData.haveMaxReactive = XMLParser::GetNodeValueInt(electricalProp,
"HaveMaxReactive");
436 m_electricalData.maxReactive = XMLParser::GetNodeValueDouble(electricalProp,
"MaxReactive");
437 m_electricalData.maxReactiveUnit =
438 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"MaxReactive",
"UnitID"));
439 m_electricalData.haveMinReactive = XMLParser::GetNodeValueInt(electricalProp,
"HaveMinReactive");
440 m_electricalData.minReactive = XMLParser::GetNodeValueDouble(electricalProp,
"MinReactive");
441 m_electricalData.minReactiveUnit =
442 static_cast<ElectricalUnit>(XMLParser::GetAttributeValueInt(electricalProp,
"MinReactive",
"UnitID"));
443 m_electricalData.useMachineBase = XMLParser::GetNodeValueInt(electricalProp,
"UseMachineBase");
445 auto fault = electricalProp->first_node(
"Fault");
446 if (!fault)
return false;
447 m_electricalData.positiveResistance = XMLParser::GetNodeValueDouble(fault,
"PositiveResistance");
448 m_electricalData.positiveReactance = XMLParser::GetNodeValueDouble(fault,
"PositiveReactance");
449 m_electricalData.negativeResistance = XMLParser::GetNodeValueDouble(fault,
"NegativeResistance");
450 m_electricalData.negativeReactance = XMLParser::GetNodeValueDouble(fault,
"NegativeReactance");
451 m_electricalData.zeroResistance = XMLParser::GetNodeValueDouble(fault,
"ZeroResistance");
452 m_electricalData.zeroReactance = XMLParser::GetNodeValueDouble(fault,
"ZeroReactance");
453 m_electricalData.groundResistance = XMLParser::GetNodeValueDouble(fault,
"GroundResistance");
454 m_electricalData.groundReactance = XMLParser::GetNodeValueDouble(fault,
"GroundReactance");
455 m_electricalData.groundNeutral = XMLParser::GetNodeValueInt(fault,
"GroundNeutral");
457 auto stability = electricalProp->first_node(
"Stability");
458 if (!stability)
return false;
459 m_electricalData.plotSyncMachine = XMLParser::GetNodeValueInt(stability,
"PlotSyncMachine");
460 m_electricalData.inertia = XMLParser::GetNodeValueDouble(stability,
"Inertia");
461 m_electricalData.damping = XMLParser::GetNodeValueDouble(stability,
"Damping");
462 m_electricalData.useAVR = XMLParser::GetNodeValueInt(stability,
"UseAVR");
463 m_electricalData.useSpeedGovernor = XMLParser::GetNodeValueInt(stability,
"UseSpeedGovernor");
464 m_electricalData.armResistance = XMLParser::GetNodeValueDouble(stability,
"ArmResistance");
465 m_electricalData.potierReactance = XMLParser::GetNodeValueDouble(stability,
"PotierReactance");
466 m_electricalData.satFactor = XMLParser::GetNodeValueDouble(stability,
"SatFactor");
467 m_electricalData.syncXd = XMLParser::GetNodeValueDouble(stability,
"SyncXd");
468 m_electricalData.syncXq = XMLParser::GetNodeValueDouble(stability,
"SyncXq");
469 m_electricalData.transXd = XMLParser::GetNodeValueDouble(stability,
"TransXd");
470 m_electricalData.transXq = XMLParser::GetNodeValueDouble(stability,
"TransXq");
471 m_electricalData.transTd0 = XMLParser::GetNodeValueDouble(stability,
"TransTd0");
472 m_electricalData.transTq0 = XMLParser::GetNodeValueDouble(stability,
"TransTq0");
473 m_electricalData.subXd = XMLParser::GetNodeValueDouble(stability,
"SubXd");
474 m_electricalData.subXq = XMLParser::GetNodeValueDouble(stability,
"SubXq");
475 m_electricalData.subTd0 = XMLParser::GetNodeValueDouble(stability,
"SubTd0");
476 m_electricalData.subTq0 = XMLParser::GetNodeValueDouble(stability,
"SubTq0");
478 if (!OpenSwitchingData(electricalProp))
return false;
485void SyncGenerator::SavePlotData()
487 m_electricalData.terminalVoltageVector.emplace_back(std::abs(m_electricalData.terminalVoltage));
488 m_electricalData.electricalPowerVector.emplace_back(m_electricalData.electricalPower);
489 m_electricalData.mechanicalPowerVector.emplace_back(m_electricalData.pm);
490 m_electricalData.freqVector.emplace_back(m_electricalData.speed / (2.0f * M_PI));
491 m_electricalData.fieldVoltageVector.emplace_back(m_electricalData.fieldVoltage);
492 m_electricalData.deltaVector.emplace_back(wxRadToDeg(m_electricalData.delta));
ElectricalUnit
Electrical units.
Class that can contain all control elements. Can identify (using RTTI) the elements from a generic li...
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
virtual void GeneralMenuItens(wxMenu &menu)
Insert general itens to context menu.
bool SetOnline(bool online=true)
Set if the element is online or offline.
Abstract class for rotary machines power elements.
virtual void SetDynamicEvent(bool dynEvent=true)
Set if the power element have dynamic event.
Synchronous generator power element.
virtual bool GetContextMenu(wxMenu &menu)
Get the element contex menu.
virtual bool ShowForm(wxWindow *parent, Element *element)
Show element data form.
virtual bool GetPlotData(ElementPlotData &plotData, PlotStudy study=PlotStudy::STABILITY)
Fill the plot data.
virtual Element * GetCopy()
Get a the element copy.
virtual wxString GetTipText() const
Get the tip text.
virtual void SetNominalVoltage(std::vector< double > nominalVoltage, std::vector< ElectricalUnit > nominalVoltageUnit)
Set nominal voltage of the element.
This class manages the graphical and power elements. It is responsible for handling the user's intera...
std::vector< double > swTime