Power System Platform  2026w11a-beta
Loading...
Searching...
No Matches
ImportForm.cpp
1/*
2 * Copyright (C) 2018 Thales Lima Oliveira <thales@ufu.br>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "ImportForm.h"
19
20#include "../elements/powerElement/Bus.h"
21#include "../elements/powerElement/Capacitor.h"
22#include "../elements/powerElement/IndMotor.h"
23#include "../elements/powerElement/Inductor.h"
24#include "../elements/powerElement/Line.h"
25#include "../elements/powerElement/Load.h"
26#include "../elements/powerElement/SyncGenerator.h"
27#include "../elements/powerElement/SyncMotor.h"
28#include "../elements/powerElement/Transformer.h"
29
30#include "../utils/PropertiesData.h"
31#include "../utils/GraphAutoLayout.h"
32
33#include "../editors/Workspace.h"
34
35ImportForm::ImportForm(wxWindow* parent, Workspace* workspace) : ImportFormBase(parent)
36{
37 SetInitialSize();
38
39 m_parent = parent;
40 m_workspace = workspace;
41}
42
43ImportForm::~ImportForm() {}
44
45void ImportForm::OnButtonCancelClick(wxCommandEvent& event)
46{
47 EndModal(wxID_CANCEL);
48 //if(m_workspace) delete m_workspace;
49}
50
51void ImportForm::OnButtonOKClick(wxCommandEvent& event)
52{
53 if(ImportSelectedFiles())
54 EndModal(wxID_OK);
55 else {
56 // Error message
57 wxMessageDialog msgDialog(this, _("It was not possible to import the selected files."), _("Error"),
58 wxOK | wxCENTRE | wxICON_ERROR);
59 msgDialog.ShowModal();
60 }
61}
62
63bool ImportForm::ImportSelectedFiles()
64{
65 switch(m_notebook->GetSelection()) {
66 case 0: {
67 return ImportCEPELFiles();
68 break;
69 }
70 case 1: {
71 return ImportMatpowerFiles();
72 break;
73 }
74 default:
75 break;
76 }
77 return false;
78}
79
80Bus* ImportForm::GetBusFromID(std::vector<Bus*> busList, int id)
81{
82 for(auto it = busList.begin(), itEnd = busList.end(); it != itEnd; ++it) {
83 if((*it)->GetID() == id) return *it;
84 }
85 return nullptr;
86}
87
88bool ImportForm::ImportCEPELFiles()
89{
90 ParseAnarede parseAnarede(m_filePickerANAREDELST->GetFileName(), m_filePickerANAREDEPWF->GetFileName());
91 if(!parseAnarede.Parse()) return false;
92 double scale = 1.25;
93
94 double mvaBasePower = parseAnarede.GetMVAPowerBase();
95 auto simProp = m_workspace->GetProperties()->GetSimulationPropertiesData();
96 simProp.basePower = mvaBasePower;
97 m_workspace->GetProperties()->SetSimulationPropertiesData(simProp);
98
99 std::vector<Element*> elementList;
100
101 std::vector<Bus*> busList;
102 std::vector<SyncGenerator*> syncGeneratorList;
103 std::vector<SyncMotor*> syncMotorList;
104 std::vector<Load*> loadList;
105 std::vector<Inductor*> indList;
106 std::vector<Capacitor*> capList;
107 std::vector<IndMotor*> indMotorList;
108 std::vector<Transformer*> transformerList;
109 std::vector<Line*> lineList;
110
111 auto components = parseAnarede.GetComponents();
112 for(auto it = components.begin(), itEnd = components.end(); it != itEnd; ++it) {
113 switch((*it)->type) {
114 case ANA_BUS: {
115 Bus* bus = new Bus(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
116 bus->SetInserted();
117 bus->SetID((*it)->id);
118 bus->SetWidth((*it)->length * scale);
119 bus->StartMove(bus->GetPosition());
120 if((*it)->rotationID == 0) {
121 bus->Move(bus->GetPosition() + wxPoint2DDouble(bus->GetWidth() / 2, bus->GetHeight() / 2));
122 } else if((*it)->rotationID == 1) {
123 for(int i = 0; i < (*it)->rotationID * 2; ++i) bus->Rotate();
124 bus->Move(bus->GetPosition() + wxPoint2DDouble(-bus->GetHeight() / 2, bus->GetWidth() / 2));
125 } else if((*it)->rotationID == 2) {
126 for(int i = 0; i < (*it)->rotationID * 2; ++i) bus->Rotate();
127 bus->Move(bus->GetPosition() + wxPoint2DDouble(-bus->GetWidth() / 2, -bus->GetHeight() / 2));
128 } else if((*it)->rotationID == 3) {
129 for(int i = 0; i < (*it)->rotationID * 2; ++i) bus->Rotate();
130 bus->Move(bus->GetPosition() + wxPoint2DDouble(-bus->GetHeight() / 2, -bus->GetWidth() / 2));
131 }
132
133 // Electrical data
134 auto data = bus->GetElectricalData();
135 ParseAnarede::BusData* busData = parseAnarede.GetBusDataFromID((*it)->electricalID);
136 if(busData) {
137 data.number = busData->id;
138 data.name = busData->busName;
139 switch(busData->type) {
140 case 0:
141 case 3: {
142 data.isVoltageControlled = false;
143 data.slackBus = false;
144 } break;
145 case 1: {
146 data.isVoltageControlled = true;
147 data.slackBus = false;
148 } break;
149 case 2: {
150 data.isVoltageControlled = true;
151 data.slackBus = true;
152 } break;
153 default: {
154 return false;
155 } break;
156 }
157 data.voltage = std::complex<double>(busData->voltage * std::cos(wxDegToRad(busData->angle)),
158 busData->voltage * std::sin(wxDegToRad(busData->angle)));
159 data.controlledVoltage = busData->voltage;
160 } else
161 return false;
162
163 bus->SetElectricalData(data);
164 busList.push_back(bus);
165 } break;
166 case ANA_GENERATOR:
167 case ANA_IND_GENERATOR: {
168 // Find parent bus
169 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
170 wxPoint2DDouble nodePos =
171 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
172
173 ParseAnarede::BusData* busData = parseAnarede.GetBusDataFromID((*it)->busConnectionID[0].second);
174 bool isMotor = false;
175 if(busData->genPower.real() <= 0.0) isMotor = true;
176 Machines* machine = nullptr;
177
178 if(!isMotor) {
179 SyncGenerator* syncGenerator = new SyncGenerator();
180
181 auto data = syncGenerator->GetElectricalData();
182 data.name =
183 wxString::Format("%s %u (%s)", _("Generator"), syncGeneratorList.size() + 1, busData->busName);
184 if((*it)->type == ANA_IND_GENERATOR) {
185 ParseAnarede::IndGenData* genData =
186 static_cast<ParseAnarede::IndGenData*>(parseAnarede.GetIndElementDataFromID(
187 (*it)->electricalID, (*it)->busConnectionID[0].second, ANA_IND_GENERATOR));
188 double numUnits = static_cast<double>(genData->numUnits);
189 data.activePower = genData->power.real() * numUnits;
190 data.reactivePower = genData->power.imag() * numUnits;
191 data.maxReactive = genData->maxReactivePower * numUnits;
192 data.minReactive = genData->minReactivePower * numUnits;
193 data.nominalPower = genData->ratedPower * numUnits;
194 double xd = genData->xd / (100.0 * numUnits);
195 data.syncXd = xd > 1e-3 ? xd : 1.0;
196 data.syncXq = genData->xq / (100.0 * numUnits);
197 data.potierReactance = genData->xl / (100.0 * numUnits);
198 } else {
199 data.activePower = busData->genPower.real();
200 data.reactivePower = busData->genPower.imag();
201 data.minReactive = busData->minReactivePower;
202 data.maxReactive = busData->maxReactivePower;
203 data.useMachineBase = false; // ANAREDE use system's base
204 }
205
206 syncGenerator->SetElectricalData(data);
207
208 machine = syncGenerator;
209 } else {
210 SyncMotor* syncMotor = new SyncMotor();
211
212 auto data = syncMotor->GetElectricalData();
213 data.name = wxString::Format("%s %u (%s)", _("Synchronous compensator"), syncMotorList.size() + 1,
214 busData->busName);
215 data.activePower = busData->genPower.real() == 0.0 ? 0.0 : -busData->genPower.real();
216 data.reactivePower = busData->genPower.imag();
217 data.minReactive = busData->minReactivePower;
218 data.maxReactive = busData->maxReactivePower;
219 data.useMachineBase = false; // ANAREDE use system's base
220
221 syncMotor->SetElectricalData(data);
222
223 machine = syncMotor;
224 }
225
226 if(machine) {
227 machine->SetID((*it)->id);
228 machine->AddParent(parentBus, nodePos);
229
230 machine->StartMove(machine->GetPosition());
231 machine->Move(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
232
233 for(int i = 0; i < 2; ++i) machine->Rotate(false); // Set to ANAREDE default rotation
234 for(int i = 0; i < (*it)->rotationID * 2; ++i) machine->Rotate();
235
236 if(!isMotor)
237 syncGeneratorList.push_back(static_cast<SyncGenerator*>(machine));
238 else
239 syncMotorList.push_back(static_cast<SyncMotor*>(machine));
240 }
241 } break;
242 case ANA_LOAD:
243 case ANA_IND_LOAD: {
244 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
245 wxPoint2DDouble nodePos =
246 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
247
248 ParseAnarede::BusData* busData = parseAnarede.GetBusDataFromID((*it)->busConnectionID[0].second);
249
250 Load* load = new Load();
251 load->SetID((*it)->id);
252 load->AddParent(parentBus, nodePos);
253
254 load->StartMove(load->GetPosition());
255 load->Move(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
256
257 auto data = load->GetElectricalData();
258 data.name = wxString::Format("%s %u (%s)", _("Load"), loadList.size() + 1, busData->busName);
259 data.activePower = busData->loadPower.real();
260 data.reactivePower = busData->loadPower.imag();
261 load->SetElectricalData(data);
262
263 for(int i = 0; i < (*it)->rotationID * 2; ++i) load->Rotate();
264
265 loadList.push_back(load);
266 } break;
267 case ANA_SHUNT:
268 case ANA_IND_SHUNT: {
269 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
270 wxPoint2DDouble nodePos =
271 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
272
273 ParseAnarede::BusData* busData = parseAnarede.GetBusDataFromID((*it)->busConnectionID[0].second);
274 bool isInductor = false;
275 Shunt* shuntElement = nullptr;
276
277 double ql = 0.0;
278 if((*it)->type == ANA_IND_SHUNT) {
279 ParseAnarede::IndElementData* shuntData = parseAnarede.GetIndElementDataFromID(
280 (*it)->electricalID, (*it)->busConnectionID[0].second, ANA_IND_SHUNT);
281 if(shuntData) {
282 double numUnits = static_cast<double>(shuntData->numUnits);
283 ql = shuntData->power.imag() * numUnits;
284 }
285 } else {
286 ql = busData->shuntReactive;
287 }
288 if(ql <= 0.0) isInductor = true;
289
290 if(!isInductor) {
291 Capacitor* cap = new Capacitor();
292 auto data = cap->GetElectricalData();
293 data.name = wxString::Format("%s %u (%s)", _("Capacitor"), indList.size() + 1, busData->busName);
294 data.reactivePower = ql;
295 cap->SetElectricalData(data);
296 shuntElement = cap;
297 } else {
298 Inductor* ind = new Inductor();
299 auto data = ind->GetElectricalData();
300 data.name = wxString::Format("%s %u (%s)", _("Inductor"), indList.size() + 1, busData->busName);
301 data.reactivePower = std::abs(ql);
302 ind->SetElectricalData(data);
303 shuntElement = ind;
304 }
305
306 if(shuntElement) {
307 shuntElement->SetID((*it)->id);
308 shuntElement->AddParent(parentBus, nodePos);
309
310 shuntElement->StartMove(shuntElement->GetPosition());
311 // Offset (ind->GetHeight() / 2 + 10) to adequate the y coordinate
312 shuntElement->Move(wxPoint2DDouble(
313 (*it)->position.m_x * scale, (*it)->position.m_y * scale + shuntElement->GetHeight() / 2 + 10));
314 if((*it)->rotationID != 0) {
315 // Remove offset in position
316 shuntElement->Move(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
317 // Get the rotated point ralated to the offset
318 wxPoint2DDouble movePt = shuntElement->RotateAtPosition(
319 shuntElement->GetPosition() + wxPoint2DDouble(0, shuntElement->GetHeight() / 2 + 10),
320 (*it)->rotationID * 90.0, true);
321 shuntElement->Move(movePt);
322
323 for(int i = 0; i < (*it)->rotationID * 2; ++i) shuntElement->Rotate();
324 }
325
326 if(!isInductor)
327 capList.push_back(static_cast<Capacitor*>(shuntElement));
328 else
329 indList.push_back(static_cast<Inductor*>(shuntElement));
330 }
331 } break;
332 case ANA_MIT: {
333 // Find parent bus
334 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
335 wxPoint2DDouble nodePos =
336 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
337
338 IndMotor* indMotor = new IndMotor();
339 indMotor->SetID((*it)->id);
340 indMotor->AddParent(parentBus, nodePos);
341
342 indMotor->StartMove(indMotor->GetPosition());
343 indMotor->Move(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
344
345 auto data = indMotor->GetElectricalData();
346 data.name = wxString::Format("%s %u (%s)", _("Motor"), indMotorList.size() + 1,
347 parentBus->GetElectricalData().name);
348 data.activePower = 0.0;
349 data.reactivePower = 0.0;
350 indMotor->SetElectricalData(data);
351
352 for(int i = 0; i < 2; ++i) indMotor->Rotate(false); // Set to ANAREDE default rotation
353 for(int i = 0; i < (*it)->rotationID * 2; ++i) indMotor->Rotate();
354
355 indMotorList.push_back(indMotor);
356 } break;
357 case ANA_TRANSFORMER: {
358 Bus* parentBus1 = GetBusFromID(busList, (*it)->busConnectionID[0].first);
359 Bus* parentBus2 = GetBusFromID(busList, (*it)->busConnectionID[1].first);
360 wxPoint2DDouble nodePos1 =
361 parseAnarede.GetNodePositionFromID(parentBus1, scale, (*it)->busConnectionNode[0].second);
362 wxPoint2DDouble nodePos2 =
363 parseAnarede.GetNodePositionFromID(parentBus2, scale, (*it)->busConnectionNode[1].second);
364
365 ParseAnarede::BranchData* branchData =
366 parseAnarede.GetBranchDataFromID((*it)->electricalID, (*it)->busConnectionID[0].second,
367 (*it)->busConnectionID[1].second, ANA_TRANSFORMER);
368
369 Transformer* transformer = new Transformer();
370 transformer->SetID((*it)->id);
371 transformer->AddParent(parentBus1, nodePos1);
372 transformer->AddParent(parentBus2, nodePos2);
373
374 transformer->StartMove(transformer->GetPosition());
375 transformer->Move(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
376
377 for(int i = 0; i < 2; ++i) transformer->Rotate(); // Set to ANAREDE default rotation
378 for(int i = 0; i < (*it)->rotationID * 2; ++i) transformer->Rotate();
379
380 auto data = transformer->GetElectricalData();
381 data.name =
382 wxString::Format("%s %u (%s - %s)", _("Transformer"), transformerList.size() + 1,
383 parentBus1->GetElectricalData().name, parentBus2->GetElectricalData().name);
384 data.resistance = branchData->resistance / 100.0;
385 data.indReactance = branchData->indReactance / 100.0;
386 data.turnsRatio = branchData->tap;
387 data.phaseShift = branchData->phaseShift;
388 transformer->SetElectricaData(data);
389
390 transformerList.push_back(transformer);
391 } break;
392 default: {
393 } break;
394 }
395 }
396
397 auto powerLines = parseAnarede.GetLines();
398 for(auto it = powerLines.begin(), itEnd = powerLines.end(); it != itEnd; ++it) {
399 if((*it)->type == ANA_LINE) {
400 Bus* parentBus1 = GetBusFromID(busList, (*it)->busConnectionID[0].first);
401 Bus* parentBus2 = GetBusFromID(busList, (*it)->busConnectionID[1].first);
402 wxPoint2DDouble nodePos1 =
403 parseAnarede.GetNodePositionFromID(parentBus1, scale, (*it)->busConnectionNode[0].second);
404 wxPoint2DDouble nodePos2 =
405 parseAnarede.GetNodePositionFromID(parentBus2, scale, (*it)->busConnectionNode[1].second);
406
407 ParseAnarede::BranchData* branchData = parseAnarede.GetBranchDataFromID(
408 (*it)->electricalID, (*it)->busConnectionID[0].second, (*it)->busConnectionID[1].second, ANA_LINE);
409
410 Line* line = new Line();
411 line->SetID((*it)->id);
412 line->AddParent(parentBus1, nodePos1);
413 for(unsigned int i = 0; i < (*it)->nodesPosition.size(); ++i)
414 line->AddPoint(
415 wxPoint2DDouble((*it)->nodesPosition[i].m_x * scale, (*it)->nodesPosition[i].m_y * scale));
416 line->AddParent(parentBus2, nodePos2);
417
418 auto data = line->GetElectricalData();
419 data.name = wxString::Format("%s %u (%s - %s)", _("Line"), lineList.size() + 1,
420 parentBus1->GetElectricalData().name, parentBus2->GetElectricalData().name);
421 data.resistance = branchData->resistance / 100.0;
422 data.indReactance = branchData->indReactance / 100.0;
423 data.capSusceptance = branchData->capSusceptance / mvaBasePower;
424 line->SetElectricalData(data);
425
426 lineList.push_back(line);
427 }
428 }
429
430 // Search for bus data without component
431 std::vector<ParseAnarede::BusData*> busDataVector = parseAnarede.GetBusData();
432 for(auto it = busDataVector.begin(), itEnd = busDataVector.end(); it != itEnd; ++it) {
433 ParseAnarede::BusData* busData = *it;
434
435 // Search for bus
436 Bus* bus = nullptr;
437 for(auto itB = busList.begin(), itBEnd = busList.end(); itB != itBEnd; ++itB) {
438 if((*itB)->GetElectricalData().number == busData->id) {
439 bus = *itB;
440 break;
441 }
442 }
443 if(bus) {
444 // Check load data
445 if(std::abs(busData->loadPower.real()) > 1e-5 ||
446 std::abs(busData->loadPower.imag()) > 1e-5) { // Have loads
447 // Find load associated with the bus
448 Load* load = nullptr;
449 for(auto itL = loadList.begin(), itLEnd = loadList.end(); itL != itLEnd; ++itL) {
450 if((*itL)->GetParentList().size() > 0) { // Don't search in empty vectors
451 if((*itL)->GetParentList()[0] == bus) { // Found load
452 load = *itL;
453 break;
454 }
455 }
456 }
457 if(!load) { // The load don't exists, create a new one.
458 Load* newLoad =
459 new Load(wxString::Format("%s %u (%s)", _("Load"), loadList.size() + 1, busData->busName));
460 newLoad->AddParent(bus, bus->GetPosition());
461 auto data = newLoad->GetElectricalData();
462 data.activePower = busData->loadPower.real();
463 data.reactivePower = busData->loadPower.imag();
464 newLoad->SetElectricalData(data);
465
466 loadList.push_back(newLoad);
467 }
468 }
469 // Check generation data
470 if(std::abs(busData->genPower.real()) > 1e-5 || std::abs(busData->genPower.imag()) > 1e-5) {
471 // Find synchornous machine associated with bus
472 if(busData->genPower.real() > 0.0) { // Synchronous generator
473 SyncGenerator* syncGenerator = nullptr;
474 for(auto itSM = syncGeneratorList.begin(), itSMEnd = syncGeneratorList.end(); itSM != itSMEnd;
475 ++itSM) {
476 if((*itSM)->GetParentList().size() > 0) { // Don't search in empty vectors
477 if((*itSM)->GetParentList()[0] == bus) { // Found load
478 syncGenerator = *itSM;
479 break;
480 }
481 }
482 }
483 if(!syncGenerator) {
484 SyncGenerator* newSyncGenerator = new SyncGenerator(wxString::Format(
485 "%s %u (%s)", _("Generator"), syncGeneratorList.size() + 1, busData->busName));
486 newSyncGenerator->AddParent(bus, bus->GetPosition());
487 auto data = newSyncGenerator->GetElectricalData();
488 data.activePower = busData->genPower.real();
489 data.reactivePower = busData->genPower.imag();
490 newSyncGenerator->SetElectricalData(data);
491
492 syncGeneratorList.push_back(newSyncGenerator);
493 }
494 } else {
495 SyncMotor* syncMotor = nullptr;
496 for(auto itSM = syncMotorList.begin(), itSMEnd = syncMotorList.end(); itSM != itSMEnd; ++itSM) {
497 if((*itSM)->GetParentList().size() > 0) { // Don't search in empty vectors
498 if((*itSM)->GetParentList()[0] == bus) { // Found load
499 syncMotor = *itSM;
500 break;
501 }
502 }
503 }
504 if(!syncMotor) {
505 SyncMotor* newSyncMotor = new SyncMotor(wxString::Format(
506 "%s %u (%s)", _("Synchronous compensator"), syncMotorList.size() + 1, busData->busName));
507 newSyncMotor->AddParent(bus, bus->GetPosition());
508 auto data = newSyncMotor->GetElectricalData();
509 data.activePower = std::abs(busData->genPower.real());
510 data.reactivePower = busData->genPower.imag();
511 newSyncMotor->SetElectricalData(data);
512
513 syncMotorList.push_back(newSyncMotor);
514 }
515 }
516 }
517 }
518 }
519 // Check for branch data without component (?)
520
521 for(auto it = busList.begin(), itEnd = busList.end(); it != itEnd; ++it) elementList.push_back(*it);
522 for(auto it = transformerList.begin(), itEnd = transformerList.end(); it != itEnd; ++it) elementList.push_back(*it);
523 for(auto it = lineList.begin(), itEnd = lineList.end(); it != itEnd; ++it) elementList.push_back(*it);
524 for(auto it = syncGeneratorList.begin(), itEnd = syncGeneratorList.end(); it != itEnd; ++it)
525 elementList.push_back(*it);
526 for(auto it = syncMotorList.begin(), itEnd = syncMotorList.end(); it != itEnd; ++it) elementList.push_back(*it);
527 for(auto it = loadList.begin(), itEnd = loadList.end(); it != itEnd; ++it) elementList.push_back(*it);
528 for(auto it = indList.begin(), itEnd = indList.end(); it != itEnd; ++it) elementList.push_back(*it);
529 for(auto it = capList.begin(), itEnd = capList.end(); it != itEnd; ++it) elementList.push_back(*it);
530 for(auto it = indMotorList.begin(), itEnd = indMotorList.end(); it != itEnd; ++it) elementList.push_back(*it);
531
532 m_workspace->SetElementList(elementList);
533 m_workspace->SetName(parseAnarede.GetProjectName());
534 return true;
535}
536
537bool ImportForm::ImportMatpowerFiles()
538{
539 ParseMatpower parseMatpower(m_filePickerMatpowerM->GetFileName());
540 if(!parseMatpower.Parse()) return false;
541
542 double mvaBasePower = parseMatpower.GetMVAPowerBase();
543 auto simProp = m_workspace->GetProperties()->GetSimulationPropertiesData();
544 simProp.basePower = mvaBasePower;
545 m_workspace->GetProperties()->SetSimulationPropertiesData(simProp);
546
547 std::vector<Element*> elementList;
548
549 std::vector<Bus*> busList;
550 std::vector<SyncGenerator*> syncGeneratorList;
551 std::vector<SyncMotor*> syncMotorList;
552 std::vector<Load*> loadList;
553 std::vector<Inductor*> indList;
554 std::vector<Capacitor*> capList;
555 std::vector<IndMotor*> indMotorList;
556 std::vector<Transformer*> transformerList;
557 std::vector<Line*> lineList;
558
559 int iterations = wxAtoi(m_textCtrlIterations->GetValue());
560 double scale;
561 if(!m_textCtrlScale->GetValue().ToDouble(&scale)) return false;
562
563 // Automatically calculate buses positions using weighted graph to determine the layout
564 GraphAutoLayout gal(parseMatpower.GetBusData(), parseMatpower.GetBranchData());
565 gal.CalculatePositions(iterations, scale);
566
567 // Fill bus list
568 auto busDataList = parseMatpower.GetBusData();
569 for(auto it = busDataList.begin(), itEnd = busDataList.end(); it != itEnd; ++it) {
570 ParseMatpower::BusData* busData = *it;
571
572 Bus* bus = new Bus(busData->busPosition);
573 bus->SetID((*it)->id);
574
575 // Electrical data
576 auto data = bus->GetElectricalData();
577 if(busData) {
578 data.number = busData->id;
579 data.name = busData->busName;
580 switch(busData->type) {
581 case 3: {
582 data.isVoltageControlled = true;
583 data.slackBus = true;
584 } break;
585 case 1: {
586 data.isVoltageControlled = false;
587 data.slackBus = false;
588 } break;
589 case 2: {
590 data.isVoltageControlled = true;
591 data.slackBus = false;
592 } break;
593 default: {
594 return false;
595 } break;
596 }
597 data.voltage = std::complex<double>(busData->voltage * std::cos(wxDegToRad(busData->angle)),
598 busData->voltage * std::sin(wxDegToRad(busData->angle)));
599 data.controlledVoltage = busData->voltage;
600 // TODO: Nominal voltage are getting errors (e.g. 118bus.m)
601 // if(busData->baseVoltage > 1e-3) { data.nominalVoltage = busData->baseVoltage; }
602 } else
603 return false;
604
605 bus->SetElectricalData(data);
606 busList.push_back(bus);
607 }
608 // Fill lines list
609 auto branchDataList = parseMatpower.GetBranchData();
610 int lineID = 0;
611 int transformerID = 0;
612 for(auto it = branchDataList.begin(), itEnd = branchDataList.end(); it != itEnd; ++it) {
613 ParseMatpower::BranchData* branchData = *it;
614 Bus* fstParentBus = GetBusFromID(busList, branchData->busConnections.first);
615 Bus* sndParentBus = GetBusFromID(busList, branchData->busConnections.second);
616 if(branchData->tap > 1e-3) { // Transformer
617 Transformer* transformer = new Transformer();
618 transformer->SetID(transformerID);
619 transformer->AddParent(fstParentBus, fstParentBus->GetPosition());
620 transformer->AddParent(sndParentBus, sndParentBus->GetPosition());
621
622 auto data = transformer->GetElectricalData();
623 data.resistance = branchData->resistance;
624 data.indReactance = branchData->indReactance;
625 data.turnsRatio = branchData->tap;
626 data.phaseShift = branchData->phaseShift;
627 data.name =
628 wxString::Format("%s %u (%s - %s)", _("Transfomer"), transformerList.size() + 1,
629 fstParentBus->GetElectricalData().name, sndParentBus->GetElectricalData().name);
630
631 transformer->SetElectricaData(data);
632
633 transformer->SetOnline(branchData->isOnline);
634
635 transformerList.push_back(transformer);
636 transformerID++;
637 } else { // Line
638 Line* line = new Line();
639 line->SetID(lineID);
640 line->AddParent(fstParentBus, fstParentBus->GetPosition());
641 line->AddParent(sndParentBus, sndParentBus->GetPosition());
642
643 auto data = line->GetElectricalData();
644 data.resistance = branchData->resistance;
645 data.indReactance = branchData->indReactance;
646 data.capSusceptance = branchData->capSusceptance;
647 data.name =
648 wxString::Format("%s %u (%s - %s)", _("Line"), lineList.size() + 1,
649 fstParentBus->GetElectricalData().name, sndParentBus->GetElectricalData().name);
650
651 line->SetElectricalData(data);
652
653 line->SetOnline(branchData->isOnline);
654
655 lineList.push_back(line);
656 lineID++;
657 }
658 }
659
660 // Connect Generators
661 auto genDataList = parseMatpower.GetGenData();
662 int genID = 0;
663 for(auto it = genDataList.begin(), itEnd = genDataList.end(); it != itEnd; ++it) {
664 SyncGenerator* generator = new SyncGenerator();
665 ParseMatpower::GenData* genData = *it;
666 generator->SetID(genID);
667
668 Bus* parentBus = GetBusFromID(busList, (*it)->busID);
669 generator->AddParent(parentBus, parentBus->GetPosition());
670
671 auto data = generator->GetElectricalData();
672 data.name = wxString::Format("%s %u (%s)", _("Machine"), syncGeneratorList.size() + 1,
673 parentBus->GetElectricalData().name);
674 data.activePower = genData->pg;
675 data.reactivePower = genData->qg;
676 data.maxReactive = genData->maxReactivePower;
677 data.minReactive = genData->minReactivePower;
678 data.nominalPower = genData->baseMVA;
679 generator->SetElectricalData(data);
680
681 syncGeneratorList.push_back(generator);
682
683 genID++;
684 }
685
686 // Connect Loads and capacitors
687 for(auto it = busList.begin(), itEnd = busList.end(); it != itEnd; ++it) {
688 Bus* bus = *it;
689 ParseMatpower::BusData* busData = parseMatpower.GetBusDataFromID(bus->GetID());
690 if(busData->pd > 1e-3 || busData->qd > 1e-3) {
691 // The bus have load
692 Load* load = new Load();
693
694 load->AddParent(bus, bus->GetPosition());
695
696 auto data = load->GetElectricalData();
697 data.name = wxString::Format("%s %u (%s)", _("Load"), loadList.size() + 1, busData->busName);
698 data.activePower = busData->pd;
699 data.reactivePower = busData->qd;
700 load->SetElectricalData(data);
701
702 loadList.push_back(load);
703 }
704 if(std::abs(busData->gs) > 1e-3) {
705 // The bus have constant impedance load
706 Load* load = new Load();
707
708 load->AddParent(bus, bus->GetPosition());
709
710 auto data = load->GetElectricalData();
711 data.name = wxString::Format("%s %u (%s)", _("Load"), loadList.size() + 1, busData->busName);
712 data.activePower = busData->gs;
713 data.reactivePower = busData->bs;
714 data.loadType = CONST_IMPEDANCE;
715 load->SetElectricalData(data);
716
717 loadList.push_back(load);
718 } else if(std::abs(busData->bs) > 1e-3) {
719 // The bus have capacitor or inductor connected
720 if(busData->bs < 1e-3) {
721 // Inductor
722 Inductor* inductor = new Inductor();
723
724 inductor->AddParent(bus, bus->GetPosition());
725
726 auto data = inductor->GetElectricalData();
727 data.name = wxString::Format("%s %u (%s)", _("Inductor"), indList.size() + 1, busData->busName);
728 data.reactivePower = std::abs(busData->bs);
729 inductor->SetElectricalData(data);
730
731 indList.push_back(inductor);
732 } else {
733 // Capacitor
734 Capacitor* capacitor = new Capacitor();
735
736 capacitor->AddParent(bus, bus->GetPosition());
737
738 auto data = capacitor->GetElectricalData();
739 data.name = wxString::Format("%s %u (%s)", _("Capacitor"), capList.size() + 1, busData->busName);
740 data.reactivePower = std::abs(busData->bs);
741 capacitor->SetElectricalData(data);
742
743 capList.push_back(capacitor);
744 }
745 }
746 }
747
748 // Adjust generators positions
749 for(auto it = syncGeneratorList.begin(), itEnd = syncGeneratorList.end(); it != itEnd; ++it) {
750 SyncGenerator* generator = *it;
751 generator->StartMove(generator->GetPosition());
752 // TODO: Check why node position have 100 pts offset in x axis
753 generator->MoveNode(generator->GetParentList()[0],
754 generator->GetParentList()[0]->GetPosition() - wxPoint2DDouble(140, 0));
755 generator->Move(generator->GetParentList()[0]->GetPosition() - wxPoint2DDouble(40, 100));
756 generator->Rotate();
757 generator->Rotate();
758 }
759
760 // Adjust loads positions
761 for(auto it = loadList.begin(), itEnd = loadList.end(); it != itEnd; ++it) {
762 Load* load = *it;
763 // Move load to the left of the bus
764 load->StartMove(wxPoint2DDouble(0, 0));
765 load->MoveNode(load->GetParentList()[0], wxPoint2DDouble(-load->GetParentList()[0]->GetWidth() / 2 + 10, 0));
766 load->Move(wxPoint2DDouble(-load->GetParentList()[0]->GetWidth() / 2 + 10, 0));
767 }
768
769 // Adjust capacitors positions
770 for(auto it = capList.begin(), itEnd = capList.end(); it != itEnd; ++it) {
771 Capacitor* capacitor = *it;
772 // Move capacitor to the right of the bus capacitor->StartMove(wxPoint2DDouble(0, 0));
773 capacitor->StartMove(wxPoint2DDouble(0, 0));
774 capacitor->MoveNode(capacitor->GetParentList()[0],
775 wxPoint2DDouble(capacitor->GetParentList()[0]->GetWidth() / 2 - 20, 0));
776 capacitor->Move(wxPoint2DDouble(capacitor->GetParentList()[0]->GetWidth() / 2 - 20, 0));
777 }
778
779 // Adjust inductors positions
780 for(auto it = indList.begin(), itEnd = indList.end(); it != itEnd; ++it) {
781 Inductor* inductor = *it;
782 // Move indutor to the far right of the bus inductor->StartMove(wxPoint2DDouble(0, 0));
783 inductor->StartMove(wxPoint2DDouble(0, 0));
784 inductor->MoveNode(inductor->GetParentList()[0],
785 wxPoint2DDouble(inductor->GetParentList()[0]->GetWidth() / 2 - 10, 0));
786 inductor->Move(wxPoint2DDouble(inductor->GetParentList()[0]->GetWidth() / 2 + 10, 0));
787 }
788
789 // Adjust branches
790 for(auto it = busList.begin(), itEnd = busList.end(); it != itEnd; ++it) {
791 Bus* bus = *it;
792 int numberOfConnectedBranches = 0;
793 std::vector<Line*> linesConnected;
794 std::vector<Transformer*> transformersConnected;
795
796 std::vector<Element*> childElements = bus->GetChildList();
797 for(unsigned int i = 0; i < childElements.size(); ++i) {
798 if(Line* line = dynamic_cast<Line*>(childElements[i])) {
799 linesConnected.push_back(line);
800 numberOfConnectedBranches++;
801 } else if(Transformer* transformer = dynamic_cast<Transformer*>(childElements[i])) {
802 transformersConnected.push_back(transformer);
803 numberOfConnectedBranches++;
804 }
805 }
806 /*for(auto itc = bus->GetChildList().begin(), itEnd = bus->GetChildList().end(); itc != itEnd; ++itc) {
807 if(Line* line = dynamic_cast<Line*>(*itc)) {
808 linesConnected.push_back(line);
809 numberOfConnectedLines++;
810 }
811 }*/
812
813 if(numberOfConnectedBranches > 0) {
814 double dx = (bus->GetWidth() - 30) / (static_cast<double>(numberOfConnectedBranches + 1));
815 int cont = 0;
816 for(unsigned int i = 0; i < linesConnected.size(); ++i) {
817 Line* lineToMove = linesConnected[i];
818 // Line nove move in x axis
819 wxPoint2DDouble newPos(dx * static_cast<double>(i + 1), 0);
820 lineToMove->StartMove(bus->GetPosition());
821 lineToMove->MoveNode(bus, bus->GetPosition() - wxPoint2DDouble(bus->GetWidth() / 2 - 10, 0) + newPos);
822 cont++;
823 }
824 for(unsigned int i = 0; i < transformersConnected.size(); ++i) {
825 Transformer* trafoToMove = transformersConnected[i];
826 wxPoint2DDouble newPos(dx * static_cast<double>(i + cont + 1), 0);
827 trafoToMove->StartMove(bus->GetPosition());
828 trafoToMove->MoveNode(bus, bus->GetPosition() - wxPoint2DDouble(bus->GetWidth() / 2 - 10, 0) + newPos);
829 trafoToMove->SetBestPositionAndRotation();
830 }
831 }
832 }
833
834 for(auto it = busList.begin(), itEnd = busList.end(); it != itEnd; ++it) elementList.push_back(*it);
835 for(auto it = transformerList.begin(), itEnd = transformerList.end(); it != itEnd; ++it) elementList.push_back(*it);
836 for(auto it = lineList.begin(), itEnd = lineList.end(); it != itEnd; ++it) elementList.push_back(*it);
837 for(auto it = syncGeneratorList.begin(), itEnd = syncGeneratorList.end(); it != itEnd; ++it)
838 elementList.push_back(*it);
839 for(auto it = syncMotorList.begin(), itEnd = syncMotorList.end(); it != itEnd; ++it) elementList.push_back(*it);
840 for(auto it = loadList.begin(), itEnd = loadList.end(); it != itEnd; ++it) elementList.push_back(*it);
841 for(auto it = indList.begin(), itEnd = indList.end(); it != itEnd; ++it) elementList.push_back(*it);
842 for(auto it = capList.begin(), itEnd = capList.end(); it != itEnd; ++it) elementList.push_back(*it);
843 for(auto it = indMotorList.begin(), itEnd = indMotorList.end(); it != itEnd; ++it) elementList.push_back(*it);
844
845 m_workspace->SetElementList(elementList);
846
847 return true;
848}
849
850ParseAnarede::ParseAnarede(wxFileName lstFile, wxFileName pwfFile)
851{
852 m_lstFile = lstFile;
853 m_pwfFile = pwfFile;
854}
855
856bool ParseAnarede::Parse()
857{
858 wxTextFile lst(m_lstFile.GetFullPath());
859 wxTextFile pwf(m_pwfFile.GetFullPath());
860 if(!lst.Open()) return false;
861 if(!pwf.Open()) return false;
862
863 // Parse LST file
864 for(wxString line = lst.GetFirstLine(); !lst.Eof(); line = lst.GetNextLine()) {
865 // Current line
866 switch(static_cast<char>(line[0])) {
867 case 'C': { // Component
868 int parsePosition = 1;
869
870 Component* component = new Component();
871
872 component->id = wxAtoi(GetLSTLineNextValue(line, parsePosition));
873 // Check if is component type is valid
874 if(StrToElementType(GetLSTLineNextValue(line, parsePosition), component->type)) {
875 if(component->type == ANA_BUS) {
876 if(!GetLenghtAndRotationFromBusCode(GetLSTLineNextValue(line, parsePosition), component->length,
877 component->rotationID))
878 return false;
879 } else {
880 component->rotationID = wxAtoi(GetLSTLineNextValue(line, parsePosition));
881 }
882 parsePosition += 2; // Jump to position
883 if(!GetLSTLineNextValue(line, parsePosition).ToCDouble(&component->position.m_x)) return false;
884 if(!GetLSTLineNextValue(line, parsePosition).ToCDouble(&component->position.m_y)) return false;
885 parsePosition += 8; // Jump to electrical ID
886 component->electricalID = wxAtoi(GetLSTLineNextValue(line, parsePosition));
887
888 // Bus connection IDs
889 if(component->type != ANA_BUS) {
890 int fromBus = wxAtoi(GetLSTLineNextValue(line, parsePosition)); // Origin bus
891 int toBus = 0;
892 // If the component is a transformer, parse the next value (toBus)
893 if(component->type == ANA_TRANSFORMER) {
894 toBus = wxAtoi(GetLSTLineNextValue(line, parsePosition)); // Destiny bus
895 }
896 // Iterate through the already parsed components (the buses is saved first)
897 for(auto it = m_components.begin(), itEnd = m_components.end(); it != itEnd; ++it) {
898 if((*it)->type == ANA_BUS) {
899 if(fromBus == (*it)->electricalID) {
900 component->busConnectionID[0] = std::make_pair((*it)->id, fromBus);
901 } else if(toBus == (*it)->electricalID) {
902 component->busConnectionID[1] = std::make_pair((*it)->id, toBus);
903 }
904 }
905 }
906 }
907 m_components.push_back(component);
908 }
909 } break;
910 case 'L': { // Line
911 int parsePosition = 1;
912
913 PowerLine* pLine = new PowerLine();
914
915 pLine->id = wxAtoi(GetLSTLineNextValue(line, parsePosition));
916 pLine->type = static_cast<ElementTypeAnarede>(wxAtoi(GetLSTLineNextValue(line, parsePosition)));
917 parsePosition += 4; // Jump to from bus
918
919 int fromBus = wxAtoi(GetLSTLineNextValue(line, parsePosition)); // Origin bus
920 int toBus = wxAtoi(GetLSTLineNextValue(line, parsePosition)); // Destiny bus
921
922 // Iterate through the already parsed components
923 for(auto it = m_components.begin(), itEnd = m_components.end(); it != itEnd; ++it) {
924 if((*it)->type == ANA_BUS) {
925 if(fromBus == (*it)->id) {
926 pLine->busConnectionID[0] = std::make_pair((*it)->id, (*it)->electricalID);
927 } else if(toBus == (*it)->id) {
928 pLine->busConnectionID[1] = std::make_pair((*it)->id, (*it)->electricalID);
929 }
930 }
931 }
932 pLine->electricalID = wxAtoi(GetLSTLineNextValue(line, parsePosition));
933
934 m_lines.push_back(pLine);
935 } break;
936 case 'U': { // Connection
937 // The connection data depends on the component type, so this data definition must be more generic.
938 int parsePosition = 1;
939
940 int id = wxAtoi(GetLSTLineNextValue(line, parsePosition));
941 (void)id; // Unused id.
942 parsePosition += 5; // Jump to next relevant data
943 int data1 = wxAtoi(GetLSTLineNextValue(line, parsePosition));
944 int data2 = wxAtoi(GetLSTLineNextValue(line, parsePosition));
945 int data3 = wxAtoi(GetLSTLineNextValue(line, parsePosition));
946 int data4 = wxAtoi(GetLSTLineNextValue(line, parsePosition));
947 int data5 = wxAtoi(GetLSTLineNextValue(line, parsePosition));
948 int data6 = wxAtoi(GetLSTLineNextValue(line, parsePosition));
949
950 // If data5 differs from -1, the connection is power line data with data5's value as its ID, otherwise
951 // data1 is the ID of a component.
952 if(data5 != -1) {
953 // Iterate through parsed lines
954 for(auto it = m_lines.begin(), itEnd = m_lines.end(); it != itEnd; ++it) {
955 if(data5 == (*it)->id) {
956 (*it)->busConnectionNode[0] = std::make_pair(data1, data2);
957 (*it)->busConnectionNode[1] = std::make_pair(data3, data4);
958 for(int i = 0; i < data6; ++i) {
959 wxPoint2DDouble nodePt;
960 if(!GetLSTLineNextValue(line, parsePosition).ToCDouble(&nodePt.m_x)) return false;
961 if(!GetLSTLineNextValue(line, parsePosition).ToCDouble(&nodePt.m_y)) return false;
962 (*it)->nodesPosition.push_back(nodePt);
963 }
964 }
965 }
966 } else {
967 // Iterate through parsed components
968 for(auto it = m_components.begin(), itEnd = m_components.end(); it != itEnd; ++it) {
969 if(data1 == (*it)->id) {
970 if((*it)->type == ANA_BUS) {
971 // If the data1 is a bus ID, the element is a element with different data order.
972 // Find the correct element ID with data3
973 for(auto itDiff = m_components.begin(), itDiffEnd = m_components.end();
974 itDiff != itDiffEnd; ++itDiff) {
975 if(data3 == (*itDiff)->id) {
976 (*itDiff)->busConnectionNode[data4 - 1] = std::make_pair(data1, data2);
977 break;
978 }
979 }
980 } else {
981 (*it)->busConnectionNode[data2 - 1] = std::make_pair(data3, data4);
982 break;
983 }
984 }
985 }
986 }
987 } break;
988 default:
989 break;
990 }
991 }
992 // Last line
993
994 // Parse PWF file
995 for(wxString line = pwf.GetFirstLine(); !pwf.Eof(); line = pwf.GetNextLine()) {
996 // Current line
997 if(line == "TITU") { // Title
998 m_projectName = pwf.GetNextLine().Trim();
999 } else if(line != "") {
1000 if(line == "FIM") break;
1001 if(line[0] != '(') { // Ignore commented line
1002 wxString exeCode = line;
1003 wxString data = "";
1004 for(wxString lineData = pwf.GetNextLine(); lineData != "99999" && !pwf.Eof();
1005 lineData = pwf.GetNextLine()) {
1006 if(lineData == "FIM") break;
1007 if(lineData[0] != '(') { // Ignore commented line
1008 data += lineData + "\n";
1009 }
1010 }
1011 if(data != "" || data != "FIM") { // Don't parse empty data
1012 if(!ParsePWFExeCode(data, exeCode)) return false;
1013 }
1014 }
1015 }
1016 }
1017 // Last line
1018
1019 return true;
1020}
1021
1022wxString ParseAnarede::GetLSTLineNextValue(wxString line, int& currentPos)
1023{
1024 // Parse each line column
1025 wxString strValue = "=";
1026 for(; currentPos < static_cast<int>(line.length()); ++currentPos) {
1027 if(line[currentPos] != ' ') { // Skip the firsts whitespaces
1028 wxString parsedLine = line.Mid(currentPos);
1029 strValue = parsedLine.BeforeFirst(' '); // Get the character before the first whitespace
1030 currentPos += strValue.length(); // Set the current parse position
1031 break;
1032 }
1033 }
1034 return strValue;
1035}
1036
1037bool ParseAnarede::GetLenghtAndRotationFromBusCode(wxString code, double& lenght, int& rotationID)
1038{
1039 // Get code in decimal.
1040 long longCode;
1041 if(!code.ToLong(&longCode)) return false;
1042 // Convert code to hex
1043 std::stringstream hexCode;
1044 hexCode << std::hex << longCode;
1045 // Convert code to string
1046 wxString hexCodeStr = hexCode.str();
1047 // Get length on the substring
1048 wxString lenghtStr = hexCodeStr.Left(hexCodeStr.length() - 1);
1049 // Convert lenght string (hex) to decimal
1050 hexCode.str("");
1051 hexCode << lenghtStr.ToStdString();
1052 int intLenght;
1053 hexCode >> std::hex >> intLenght;
1054 lenght = static_cast<double>(intLenght);
1055 // Get rotation ID from substring
1056 wxString rotationIDStr = hexCodeStr.Right(1);
1057 // Convert rotation ID string to int
1058 long rotationIDLong;
1059 if(!rotationIDStr.ToLong(&rotationIDLong)) return false;
1060 rotationID = static_cast<int>(rotationIDLong);
1061 // Calculate the true value of lenght
1062 lenght = 3.0 * lenght - 16.0;
1063 return true;
1064}
1065
1066wxPoint2DDouble ParseAnarede::GetNodePositionFromID(Bus* bus, double scale, int nodeID)
1067{
1068 wxPoint2DDouble nodePt;
1069
1070 double offset = (static_cast<double>(nodeID) - 1.0) * 16.0;
1071 nodePt = bus->GetPosition() + wxPoint2DDouble(offset * scale, 0) -
1072 wxPoint2DDouble(bus->GetWidth() / 2, bus->GetHeight() / 2);
1073 nodePt = bus->RotateAtPosition(nodePt, bus->GetAngle(), true);
1074
1075 return nodePt;
1076}
1077
1078bool ParseAnarede::StrToElementType(wxString strType, ElementTypeAnarede& type)
1079{
1080 // Check if type exists, othewise return false
1081 int typeInt = wxAtoi(strType);
1082 switch(typeInt) {
1083 case ANA_BUS:
1084 case ANA_GENERATOR:
1085 case ANA_LOAD:
1086 case ANA_SHUNT:
1087 case ANA_MIT:
1088 case ANA_TRANSFORMER:
1089 case ANA_LINE:
1090 case ANA_IND_LOAD:
1091 case ANA_IND_SHUNT:
1092 case ANA_IND_GENERATOR: {
1093 type = static_cast<ElementTypeAnarede>(typeInt);
1094 return true;
1095 } break;
1096 default:
1097 break;
1098 }
1099 return false;
1100}
1101
1102bool ParseAnarede::ParsePWFExeCode(wxString data, wxString exeCode)
1103{
1104 if(exeCode == "DCTE") {
1105 // Parse data
1106 wxString code = "";
1107 wxString value = "";
1108 for(unsigned int i = 0; i < data.length(); ++i) {
1109 code = data.Mid(i, 4);
1110 value = data.Mid(i + 5, 6).Trim(false);
1111 i += 11;
1112 if(code == "BASE") {
1113 if(!value.ToCDouble(&m_mvaBase)) return false;
1114 break;
1115 }
1116 }
1117 } else if(exeCode == "DBAR") {
1118 wxString lineData = "";
1119 while(data != "") {
1120 wxString rest = "";
1121 lineData = data.BeforeFirst('\n', &rest);
1122 data = rest;
1123 BusData* busData = new BusData();
1124
1125 if(!GetPWFStructuredData(lineData, 0, 5, busData->id)) return false;
1126 wxString isOnlineCode = lineData.Mid(6, 1);
1127 if(isOnlineCode == "L" || isOnlineCode == " ")
1128 busData->isOnline = true;
1129 else if(isOnlineCode == "D")
1130 busData->isOnline = false;
1131 else
1132 return false;
1133 if(!GetPWFStructuredData(lineData, 7, 1, busData->type)) return false;
1134 busData->voltageBase = lineData.Mid(8, 2);
1135 busData->busName = lineData.Mid(10, 12).Trim();
1136 if(!GetPWFStructuredData(lineData, 24, 4, busData->voltage, 1)) return false;
1137 if(!GetPWFStructuredData(lineData, 28, 4, busData->angle)) return false;
1138 double pg, qg;
1139 if(!GetPWFStructuredData(lineData, 32, 5, pg)) return false;
1140 if(!GetPWFStructuredData(lineData, 37, 5, qg)) return false;
1141 busData->genPower = std::complex<double>(pg, qg);
1142 if(!GetPWFStructuredData(lineData, 42, 5, busData->minReactivePower)) return false;
1143 if(!GetPWFStructuredData(lineData, 47, 5, busData->maxReactivePower)) return false;
1144 if(!GetPWFStructuredData(lineData, 52, 6, busData->ctrlBusID)) return false;
1145 double pl, ql;
1146 if(!GetPWFStructuredData(lineData, 58, 5, pl)) return false;
1147 if(!GetPWFStructuredData(lineData, 63, 5, ql)) return false;
1148 busData->loadPower = std::complex<double>(pl, ql);
1149 if(!GetPWFStructuredData(lineData, 68, 5, busData->shuntReactive)) return false;
1150
1151 m_busData.push_back(busData);
1152 }
1153 } else if(exeCode == "DLIN") {
1154 wxString lineData = "";
1155 while(data != "") {
1156 wxString rest = "";
1157 lineData = data.BeforeFirst('\n', &rest);
1158 data = rest;
1159 BranchData* branchData = new BranchData();
1160
1161 if(!GetPWFStructuredData(lineData, 15, 2, branchData->id)) return false;
1162 int from, to;
1163 if(!GetPWFStructuredData(lineData, 0, 5, from)) return false;
1164 if(!GetPWFStructuredData(lineData, 10, 5, to)) return false;
1165 branchData->busConnections = std::make_pair(from, to);
1166
1167 wxString isOnlineCode = lineData.Mid(6, 1) + lineData.Mid(9, 1) + lineData.Mid(17, 1);
1168 if(isOnlineCode.Find('D') == wxNOT_FOUND)
1169 branchData->isOnline = true;
1170 else
1171 branchData->isOnline = false;
1172 if(!GetPWFStructuredData(lineData, 20, 6, branchData->resistance, 4)) return false;
1173 if(!GetPWFStructuredData(lineData, 26, 6, branchData->indReactance, 4)) return false;
1174 if(!GetPWFStructuredData(lineData, 32, 6, branchData->capSusceptance, 4)) return false;
1175 if(!GetPWFStructuredData(lineData, 38, 5, branchData->tap, 2)) return false;
1176 if(!GetPWFStructuredData(lineData, 53, 5, branchData->phaseShift, 3)) return false;
1177
1178 if(branchData->tap < 1e-3)
1179 branchData->type = ANA_LINE;
1180 else
1181 branchData->type = ANA_TRANSFORMER;
1182
1183 m_branchData.push_back(branchData);
1184 }
1185 } else if(exeCode == "DCAI") {
1186 wxString lineData = "";
1187 while(data != "") {
1188 wxString rest = "";
1189 lineData = data.BeforeFirst('\n', &rest);
1190 data = rest;
1191 IndElementData* indData = new IndElementData();
1192 indData->type = ANA_IND_LOAD;
1193
1194 if(!GetPWFStructuredData(lineData, 9, 2, indData->id)) return false;
1195 if(!GetPWFStructuredData(lineData, 0, 5, indData->busConnection)) return false;
1196
1197 wxString isOnlineCode = lineData.Mid(13, 1);
1198 if(isOnlineCode == "L" || isOnlineCode == " ")
1199 indData->isOnline = true;
1200 else if(isOnlineCode == "D")
1201 indData->isOnline = false;
1202 else
1203 return false;
1204
1205 double pl, ql;
1206 if(!GetPWFStructuredData(lineData, 22, 5, pl)) return false;
1207 if(!GetPWFStructuredData(lineData, 28, 5, ql)) return false;
1208 indData->power = std::complex<double>(pl, ql);
1209 // Unities in operation
1210 if(!GetPWFStructuredData(lineData, 18, 3, indData->numUnits)) return false;
1211
1212 m_indElementData.push_back(indData);
1213 }
1214 } else if(exeCode == "DGEI") {
1215 wxString lineData = "";
1216 while(data != "") {
1217 wxString rest = "";
1218 lineData = data.BeforeFirst('\n', &rest);
1219 data = rest;
1220 IndGenData* genData = new IndGenData();
1221 genData->type = ANA_IND_GENERATOR;
1222
1223 if(!GetPWFStructuredData(lineData, 9, 2, genData->id)) return false;
1224 if(!GetPWFStructuredData(lineData, 0, 5, genData->busConnection)) return false;
1225
1226 wxString isOnlineCode = lineData.Mid(12, 1);
1227 if(isOnlineCode == "L" || isOnlineCode == " ")
1228 genData->isOnline = true;
1229 else if(isOnlineCode == "D")
1230 genData->isOnline = false;
1231 else
1232 return false;
1233
1234 double pg, qg;
1235 if(!GetPWFStructuredData(lineData, 22, 5, pg)) return false;
1236 if(!GetPWFStructuredData(lineData, 27, 5, qg)) return false;
1237 genData->power = std::complex<double>(pg, qg);
1238 // Unities in operation
1239 if(!GetPWFStructuredData(lineData, 16, 3, genData->numUnits)) return false;
1240 if(!GetPWFStructuredData(lineData, 32, 5, genData->minReactivePower)) return false;
1241 if(!GetPWFStructuredData(lineData, 37, 5, genData->maxReactivePower)) return false;
1242 if(!GetPWFStructuredData(lineData, 42, 6, genData->xt, 2)) return false;
1243 if(!GetPWFStructuredData(lineData, 49, 5, genData->xd, 4)) return false;
1244 if(!GetPWFStructuredData(lineData, 54, 5, genData->xq, 4)) return false;
1245 if(!GetPWFStructuredData(lineData, 59, 5, genData->xl, 4)) return false;
1246 if(!GetPWFStructuredData(lineData, 69, 5, genData->ratedPower, 3)) return false;
1247
1248 m_indElementData.push_back(genData);
1249 }
1250 } else if(exeCode == "DBSH") {
1251 int lineNumber = 1;
1252 wxString lineData = "";
1253 int busNumber = -1;
1254
1255 while(data != "") {
1256 wxString rest = "";
1257 lineData = data.BeforeFirst('\n', &rest);
1258 data = rest;
1259
1260 if(lineNumber == 1) {
1261 if(!GetPWFStructuredData(lineData, 0, 5, busNumber)) return false;
1262 } else if(lineData == "FBAN") {
1263 lineNumber = 0;
1264 busNumber = -1;
1265 } else if(lineNumber >= 2 && busNumber != -1) {
1266 IndElementData* indShunt = new IndElementData();
1267 indShunt->type = ANA_IND_SHUNT;
1268 indShunt->busConnection = busNumber;
1269
1270 if(!GetPWFStructuredData(lineData, 0, 2, indShunt->id)) return false;
1271
1272 wxString isOnlineCode = lineData.Mid(6, 1);
1273 if(isOnlineCode == "L" || isOnlineCode == " ")
1274 indShunt->isOnline = true;
1275 else if(isOnlineCode == "D")
1276 indShunt->isOnline = false;
1277 else
1278 return false;
1279
1280 if(!GetPWFStructuredData(lineData, 12, 3, indShunt->numUnits)) return false;
1281 double ql;
1282 if(!GetPWFStructuredData(lineData, 16, 6, ql)) return false;
1283 indShunt->power = std::complex<double>(0.0, ql);
1284 m_indElementData.push_back(indShunt);
1285 }
1286 ++lineNumber;
1287 }
1288 }
1289
1290 return true;
1291}
1292
1293bool ParseAnarede::GetPWFStructuredData(wxString data,
1294 unsigned int startPos,
1295 unsigned int dataLenght,
1296 int& value,
1297 int decimalPos)
1298{
1299 if(data.length() < startPos || data.length() < (startPos + dataLenght)) {
1300 value = 0;
1301 return true;
1302 }
1303 wxString strValue = data.Mid(startPos, dataLenght);
1304 strValue.Replace(' ', '0');
1305 long lValue = 0;
1306 if(!strValue.ToLong(&lValue)) return false;
1307 value = static_cast<int>(lValue);
1308 return true;
1309}
1310
1311bool ParseAnarede::GetPWFStructuredData(wxString data,
1312 unsigned int startPos,
1313 unsigned int dataLenght,
1314 double& value,
1315 int decimalPos)
1316{
1317 if(data.length() < startPos || data.length() < (startPos + dataLenght)) {
1318 value = 0.0;
1319 return true;
1320 }
1321 wxString strValue = data.Mid(startPos, dataLenght);
1322 if(strValue.Find('-') == wxNOT_FOUND) strValue.Replace(' ', '0');
1323 if(decimalPos != -1 && strValue.Find('.') == wxNOT_FOUND) strValue.insert(decimalPos, '.');
1324 if(!strValue.ToCDouble(&value)) return false;
1325 return true;
1326}
1327
1328ParseAnarede::BusData* ParseAnarede::GetBusDataFromID(int id)
1329{
1330 for(auto it = m_busData.begin(), itEnd = m_busData.end(); it != itEnd; ++it) {
1331 if((*it)->id == id) return *it;
1332 }
1333 return nullptr;
1334}
1335
1336ParseAnarede::BranchData* ParseAnarede::GetBranchDataFromID(int id, int fromBus, int toBus, ElementTypeAnarede type)
1337{
1338 for(auto it = m_branchData.begin(), itEnd = m_branchData.end(); it != itEnd; ++it) {
1339 if((*it)->id == id && (*it)->busConnections.first == fromBus && (*it)->busConnections.second == toBus &&
1340 (*it)->type == type)
1341 return *it;
1342 }
1343 return nullptr;
1344}
1345
1346ParseAnarede::IndElementData* ParseAnarede::GetIndElementDataFromID(int id, int busID, ElementTypeAnarede type)
1347{
1348 for(auto it = m_indElementData.begin(), itEnd = m_indElementData.end(); it != itEnd; ++it) {
1349 if((*it)->id == id && (*it)->busConnection == busID && (*it)->type == type) return *it;
1350 }
1351 return nullptr;
1352}
1353
1354void ParseAnarede::ClearData()
1355{
1356 for(auto it = m_components.begin(), itEnd = m_components.end(); it != itEnd; ++it) {
1357 if(*it) delete *it;
1358 }
1359 m_components.clear();
1360 for(auto it = m_lines.begin(), itEnd = m_lines.end(); it != itEnd; ++it) {
1361 if(*it) delete *it;
1362 }
1363 m_lines.clear();
1364 for(auto it = m_busData.begin(), itEnd = m_busData.end(); it != itEnd; ++it) {
1365 if(*it) delete *it;
1366 }
1367 m_busData.clear();
1368 for(auto it = m_branchData.begin(), itEnd = m_branchData.end(); it != itEnd; ++it) {
1369 if(*it) delete *it;
1370 }
1371 m_branchData.clear();
1372 for(auto it = m_indElementData.begin(), itEnd = m_indElementData.end(); it != itEnd; ++it) {
1373 if(*it) delete *it;
1374 }
1375 m_indElementData.clear();
1376}
1377
1378ParseMatpower::ParseMatpower(wxFileName mFile) { m_mFile = mFile; }
1379
1380void ParseMatpower::ClearData()
1381{
1382 // Clear data to avoid memory leak
1383 for(auto it = m_branchData.begin(), itEnd = m_branchData.end(); it != itEnd; ++it) {
1384 if(*it) delete *it;
1385 }
1386 m_branchData.clear();
1387 for(auto it = m_branchData.begin(), itEnd = m_branchData.end(); it != itEnd; ++it) {
1388 if(*it) delete *it;
1389 }
1390 m_branchData.clear();
1391 for(auto it = m_genData.begin(), itEnd = m_genData.end(); it != itEnd; ++it) {
1392 if(*it) delete *it;
1393 }
1394 m_genData.clear();
1395}
1396
1397bool ParseMatpower::Parse()
1398{
1399 wxTextFile mFile(m_mFile.GetFullPath());
1400 if(!mFile.Open()) return false;
1401
1402 // Parse M file
1403 wxString fileTxt = "";
1404 for(wxString line = mFile.GetFirstLine(); !mFile.Eof(); line = mFile.GetNextLine()) {
1405 // Current line
1406 if(line.Trim()[0] != '%') { // Check if the line is commented (with %)
1407 // Parse data:
1408 if(line.Find("mpc.baseMVA") != wxNOT_FOUND) { // Found baseMVA
1409 if(!line.AfterFirst('=').BeforeFirst(';').ToCDouble(&m_mvaBase)) return false; // No Trim() needed?
1410 }
1411 if(line.Find("mpc.bus ") != wxNOT_FOUND) { // Found bus
1412 wxStringTokenizer busStrTok = GetMFileTokenData(mFile, line);
1413 while(busStrTok.HasMoreTokens()) {
1414 BusData* busData = new BusData();
1415 wxString busDataStr = busStrTok.GetNextToken();
1416 char tokenChar = '\t';
1417 if(busDataStr.Find('\t') == wxNOT_FOUND) { tokenChar = ' '; }
1418 // Tokenize using tabulation or space (each branch data)
1419 wxStringTokenizer busDataStrTok(busDataStr, tokenChar);
1420
1421 busData->id = wxAtoi(busDataStrTok.GetNextToken()); // Bus number
1422 busData->type = wxAtoi(busDataStrTok.GetNextToken()); // Bus type
1423 if(!busDataStrTok.GetNextToken().ToCDouble(&busData->pd)) return false; // Real power demand
1424 if(!busDataStrTok.GetNextToken().ToCDouble(&busData->qd)) return false; // Reactive power demand
1425 if(!busDataStrTok.GetNextToken().ToCDouble(&busData->gs)) return false; // Shunt condutance
1426 if(!busDataStrTok.GetNextToken().ToCDouble(&busData->bs)) return false; // Shunt susceptance
1427 busData->area = wxAtoi(busDataStrTok.GetNextToken()); // Bus area
1428 if(!busDataStrTok.GetNextToken().ToCDouble(&busData->voltage)) return false; // Bus abs voltage
1429 if(!busDataStrTok.GetNextToken().ToCDouble(&busData->angle)) return false; // Angle of voltage
1430 if(!busDataStrTok.GetNextToken().ToCDouble(&busData->baseVoltage)) return false; // Base Voltage
1431
1432 m_busData.push_back(busData); // Save new bus data at vector
1433 }
1434 }
1435 if(line.Find("mpc.gen ") != wxNOT_FOUND) { // Found generator
1436 wxStringTokenizer genStrTok = GetMFileTokenData(mFile, line);
1437 while(genStrTok.HasMoreTokens()) {
1438 GenData* genData = new GenData();
1439 wxString genDataStr = genStrTok.GetNextToken();
1440 char tokenChar = '\t';
1441 if(genDataStr.Find('\t') == wxNOT_FOUND) { tokenChar = ' '; }
1442 // Tokenize using tabulation or space (each branch data)
1443 wxStringTokenizer genDataStrTok(genDataStr, tokenChar);
1444 genData->busID = wxAtoi(genDataStrTok.GetNextToken()); // Bus number
1445 if(!genDataStrTok.GetNextToken().ToCDouble(&genData->pg)) return false; // Real power output
1446 if(!genDataStrTok.GetNextToken().ToCDouble(&genData->qg)) return false; // Reative power output
1447 if(!genDataStrTok.GetNextToken().ToCDouble(&genData->maxReactivePower))
1448 return false; // Maximum reactive power (MVAr)
1449 if(!genDataStrTok.GetNextToken().ToCDouble(&genData->minReactivePower))
1450 return false; // Minumum reactive power (MVAr)
1451 genDataStrTok.GetNextToken(); // Voltage magnitude setpoint (p.u.), skip
1452 if(!genDataStrTok.GetNextToken().ToCDouble(&genData->baseMVA)) return false; // Power base (MVA)
1453 double machineStatus = 0;
1454 if(!genDataStrTok.GetNextToken().ToCDouble(&machineStatus))
1455 return false; // Machine status (> 0 = machine in-service; <= 0 = machine out-of-service)
1456 genData->isOnline = machineStatus > 1e-3 ? true : false;
1457
1458 m_genData.push_back(genData);
1459 }
1460 }
1461 if(line.Find("mpc.branch") != wxNOT_FOUND) { // Found branch
1462 wxStringTokenizer branchStrTok = GetMFileTokenData(mFile, line);
1463 while(branchStrTok.HasMoreTokens()) {
1464 BranchData* branchData = new BranchData();
1465 wxString branchDataStr = branchStrTok.GetNextToken();
1466 char tokenChar = '\t';
1467 if(branchDataStr.Find('\t') == wxNOT_FOUND) { tokenChar = ' '; }
1468 // Tokenize using tabulation or space (each branch data)
1469 wxStringTokenizer branchDataStrTok(branchDataStr, tokenChar);
1470
1471 int fromBus = wxAtoi(branchDataStrTok.GetNextToken()); // From bus number
1472 int toBus = wxAtoi(branchDataStrTok.GetNextToken()); // To bus number
1473 branchData->busConnections = std::make_pair(fromBus, toBus);
1474 if(!branchDataStrTok.GetNextToken().ToCDouble(&branchData->resistance)) return false; // Resistance
1475 if(!branchDataStrTok.GetNextToken().ToCDouble(&branchData->indReactance))
1476 return false; // Reactance
1477 if(!branchDataStrTok.GetNextToken().ToCDouble(&branchData->capSusceptance))
1478 return false; // Line charging susceptance
1479 branchDataStrTok.GetNextToken(); // MVA rating A, skip
1480 branchDataStrTok.GetNextToken(); // MVA rating B, skip
1481 branchDataStrTok.GetNextToken(); // MVA rating C, skip
1482 if(!branchDataStrTok.GetNextToken().ToCDouble(&branchData->tap)) return false; // TAP
1483 if(!branchDataStrTok.GetNextToken().ToCDouble(&branchData->phaseShift))
1484 return false; // Transformer phase-shift angle
1485 double branchStatus = 0;
1486 if(!branchDataStrTok.GetNextToken().ToCDouble(&branchStatus))
1487 return false; // Branch status (> 0 = machine in-service; <= 0 = machine out-of-service)
1488 branchData->isOnline = branchStatus > 1e-3 ? true : false;
1489
1490 m_branchData.push_back(branchData);
1491 }
1492 }
1493 if(line.Find("mpc.bus_name") != wxNOT_FOUND) { // Found buses names
1494 wxString dataStr = "";
1495 while(line.Find('}', true) == wxNOT_FOUND) { // Concatenate all lines until find ']'
1496 dataStr += line;
1497 line = mFile.GetNextLine();
1498 }
1499 dataStr += line;
1500 dataStr = dataStr.AfterFirst('{').BeforeFirst('}'); // Get only the element data
1501 wxStringTokenizer dataStrTok(dataStr, ";"); // Tokenize using ';' char (one element data)
1502 for(auto it = m_busData.begin(), itEnd = m_busData.end(); it != itEnd; ++it) {
1503 if(dataStrTok.HasMoreTokens())
1504 (*it)->busName = dataStrTok.GetNextToken().AfterFirst('\'').BeforeFirst('\'');
1505 }
1506 }
1507 }
1508 }
1509 // Last line
1510
1511 return true;
1512}
1513
1514wxStringTokenizer ParseMatpower::GetMFileTokenData(wxTextFile& mFile, wxString currentLine)
1515{
1516 wxString dataStr = "";
1517 while(currentLine.Find(']', true) == wxNOT_FOUND) { // Concatenate all lines until find ']'
1518 dataStr += currentLine;
1519 if(currentLine.Find("mpc") == wxNOT_FOUND && currentLine.Find(';') == wxNOT_FOUND) dataStr += ';';
1520 currentLine = mFile.GetNextLine();
1521 }
1522 dataStr += currentLine + ";";
1523 if(currentLine.Find(';') == wxNOT_FOUND) dataStr += ';';
1524 dataStr = dataStr.AfterFirst('[').BeforeFirst(']'); // Get only the element data
1525 wxStringTokenizer dataStrTok(dataStr, ';'); // Tokenize using ';' char (one element data)
1526 return dataStrTok;
1527}
1528
1529ParseMatpower::BusData* ParseMatpower::GetBusDataFromID(int id)
1530{
1531 for(auto it = m_busData.begin(), itEnd = m_busData.end(); it != itEnd; ++it) {
1532 if((*it)->id == id) return *it;
1533 }
1534 return nullptr;
1535}
ElementTypeAnarede
Definition ImportForm.h:76
@ ANA_IND_GENERATOR
Definition ImportForm.h:86
@ ANA_MIT
Definition ImportForm.h:81
@ ANA_GENERATOR
Definition ImportForm.h:78
@ ANA_BUS
Definition ImportForm.h:77
@ ANA_LINE
Definition ImportForm.h:83
@ ANA_IND_LOAD
Definition ImportForm.h:84
@ ANA_SHUNT
Definition ImportForm.h:80
@ ANA_TRANSFORMER
Definition ImportForm.h:82
@ ANA_LOAD
Definition ImportForm.h:79
@ ANA_IND_SHUNT
Definition ImportForm.h:85
Node for power elements. All others power elements are connected through this.
Definition Bus.h:86
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Bus.cpp:315
Shunt capactior power element.
Definition Capacitor.h:39
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Capacitor.cpp:32
virtual std::vector< Element * > GetParentList() const
Get the parent list.
Definition Element.h:559
virtual int GetID() const
Get the element ID.
Definition Element.h:271
double GetWidth() const
Get the element width.
Definition Element.h:206
wxPoint2DDouble GetPosition() const
Get the element position.
Definition Element.h:186
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Element.h:239
virtual std::vector< Element * > GetChildList() const
Get the Child list.
Definition Element.h:564
double GetAngle() const
Get the element angle.
Definition Element.h:211
void SetWidth(double width)
Set element width.
Definition Element.h:149
double GetHeight() const
Get the element height.
Definition Element.h:196
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Definition Element.cpp:260
virtual wxPoint2DDouble RotateAtPosition(wxPoint2DDouble pointToRotate, double angle, bool degrees=true) const
Rotate a point as element position being the origin.
Definition Element.cpp:223
virtual void SetID(int id)
Set the element ID.
Definition Element.h:266
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Definition Element.cpp:266
bool SetOnline(bool online=true)
Set if the element is online or offline.
Definition Element.cpp:378
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Element.h:316
void SetInserted(bool inserted=true)
Set if the element is properly inserted in the workspace.
Definition Element.h:631
Induction motor power element.
Definition IndMotor.h:119
Inductor shunt power element.
Definition Inductor.h:39
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Inductor.cpp:34
Power line element.
Definition Line.h:64
virtual void AddPoint(wxPoint2DDouble point)
Add point to the list of points that connect the element to the bus.
Definition Line.cpp:373
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Line.cpp:276
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Definition Line.cpp:378
virtual void MoveNode(Element *parent, wxPoint2DDouble position)
Move a node. StartMove(wxPoint2DDouble position) before start moving.
Definition Line.cpp:384
Loas shunt power element.
Definition Load.h:74
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Load.cpp:271
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Load.cpp:34
Abstract class for rotary machines power elements.
Definition Machines.h:34
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Definition Machines.cpp:223
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
Definition Machines.cpp:24
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Definition Machines.cpp:258
virtual void Rotate(bool clockwise=true)
Rotate the element.
Definition Machines.cpp:344
virtual void MoveNode(Element *element, wxPoint2DDouble position)
Move a node. StartMove(wxPoint2DDouble position) before start moving.
Definition Machines.cpp:236
Class responsible to parse ANAREDE files to import data to PSP.
Definition ImportForm.h:97
Abstract class for shunt power elements.
Definition Shunt.h:32
virtual void MoveNode(Element *element, wxPoint2DDouble position)
Move a node. StartMove(wxPoint2DDouble position) before start moving.
Definition Shunt.cpp:45
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Definition Shunt.cpp:67
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Definition Shunt.cpp:32
Synchronous generator power element.
Synchronous motor (synchronous compensator) power element.
Definition SyncMotor.h:135
Two-winding transformer power element.
Definition Transformer.h:84
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
virtual void Move(wxPoint2DDouble position)
Move the element other position.
virtual void MoveNode(Element *parent, wxPoint2DDouble position)
Move a node. StartMove(wxPoint2DDouble position) before start moving.
virtual void Rotate(bool clockwise=true)
Rotate the element.
virtual bool AddParent(Element *parent, wxPoint2DDouble position)
Add a parent to the element. This method must be used on power elements that connect to a bus,...
This class manages the graphical and power elements. It is responsible for handling the user's intera...
Definition Workspace.h:103
std::complex< double > loadPower
Definition ImportForm.h:134
std::complex< double > genPower
Definition ImportForm.h:130
std::complex< double > power
Definition ImportForm.h:154
std::pair< int, int > busConnections
Definition ImportForm.h:243
wxPoint2DDouble busPosition
Definition ImportForm.h:231