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