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) {
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);
119 if((*it)->rotationID == 0) {
121 } else if((*it)->rotationID == 1) {
122 for(
int i = 0; i < (*it)->rotationID * 2; ++i) bus->
Rotate();
124 } else if((*it)->rotationID == 2) {
125 for(
int i = 0; i < (*it)->rotationID * 2; ++i) bus->
Rotate();
127 } else if((*it)->rotationID == 3) {
128 for(
int i = 0; i < (*it)->rotationID * 2; ++i) bus->
Rotate();
130 }
131
132
133 auto data = bus->GetElectricalData();
135 if(busData) {
136 data.number = busData->
id;
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;
167
168 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
169 wxPoint2DDouble nodePos =
170 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
171
173 bool isMotor = false;
174 if(busData->
genPower.real() <= 0.0) isMotor =
true;
176
177 if(!isMotor) {
179
180 auto data = syncGenerator->GetElectricalData();
181 data.name =
182 wxString::Format(
"%s %u (%s)", _(
"Generator"), syncGeneratorList.size() + 1, busData->
busName);
187 double numUnits =
static_cast<double>(genData->
numUnits);
188 data.activePower = genData->
power.real() * numUnits;
189 data.reactivePower = genData->
power.imag() * 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();
202 data.useMachineBase = false;
203 }
204
205 syncGenerator->SetElectricalData(data);
206
207 machine = syncGenerator;
208 } else {
210
211 auto data = syncMotor->GetElectricalData();
212 data.name = wxString::Format("%s %u (%s)", _("Synchronous compensator"), syncMotorList.size() + 1,
214 data.activePower = busData->
genPower.real() == 0.0 ? 0.0 : -busData->
genPower.real();
215 data.reactivePower = busData->
genPower.imag();
218 data.useMachineBase = false;
219
220 syncMotor->SetElectricalData(data);
221
222 machine = syncMotor;
223 }
224
225 if(machine) {
226 machine->
SetID((*it)->id);
228
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);
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;
243 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
244 wxPoint2DDouble nodePos =
245 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
246
248
250 load->
SetID((*it)->id);
252
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;
268 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
269 wxPoint2DDouble nodePos =
270 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
271
273 bool isInductor = false;
274 Shunt* shuntElement =
nullptr;
275
276 double ql = 0.0;
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 {
286 }
287 if(ql <= 0.0) isInductor = true;
288
289 if(!isInductor) {
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 {
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
310
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
315 shuntElement->
Move(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
316
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;
332
333 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
334 wxPoint2DDouble nodePos =
335 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
336
338 indMotor->
SetID((*it)->id);
340
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);
352 for(
int i = 0; i < (*it)->rotationID * 2; ++i) indMotor->
Rotate();
353
354 indMotorList.push_back(indMotor);
355 } break;
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
365 parseAnarede.GetBranchDataFromID((*it)->electricalID, (*it)->busConnectionID[0].second,
367
369 transformer->
SetID((*it)->id);
370 transformer->
AddParent(parentBus1, nodePos1);
371 transformer->
AddParent(parentBus2, nodePos2);
372
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();
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;
385 data.turnsRatio = branchData->
tap;
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) {
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
407 (*it)->electricalID, (*it)->busConnectionID[0].second, (*it)->busConnectionID[1].second,
ANA_LINE);
408
410 line->
SetID((*it)->id);
412 for(unsigned int i = 0; i < (*it)->nodesPosition.size(); ++i)
414 wxPoint2DDouble((*it)->nodesPosition[i].m_x * scale, (*it)->nodesPosition[i].m_y * scale));
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;
423 line->SetElectricalData(data);
424
425 lineList.push_back(line);
426 }
427 }
428
429
430 std::vector<ParseAnarede::BusData*> busDataVector = parseAnarede.GetBusData();
431 for(auto it = busDataVector.begin(), itEnd = busDataVector.end(); it != itEnd; ++it) {
433
434
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
444 if(std::abs(busData->
loadPower.real()) > 1e-5 ||
445 std::abs(busData->
loadPower.imag()) > 1e-5) {
446
447 Load* load =
nullptr;
448 for(auto itL = loadList.begin(), itLEnd = loadList.end(); itL != itLEnd; ++itL) {
449 if((*itL)->GetParentList().size() > 0) {
450 if((*itL)->GetParentList()[0] == bus) {
451 load = *itL;
452 break;
453 }
454 }
455 }
456 if(!load) {
458 new Load(wxString::Format(
"%s %u (%s)", _(
"Load"), loadList.size() + 1, busData->
busName));
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
469 if(std::abs(busData->
genPower.real()) > 1e-5 || std::abs(busData->
genPower.imag()) > 1e-5) {
470
471 if(busData->
genPower.real() > 0.0) {
473 for(auto itSM = syncGeneratorList.begin(), itSMEnd = syncGeneratorList.end(); itSM != itSMEnd;
474 ++itSM) {
475 if((*itSM)->GetParentList().size() > 0) {
476 if((*itSM)->GetParentList()[0] == bus) {
477 syncGenerator = *itSM;
478 break;
479 }
480 }
481 }
482 if(!syncGenerator) {
484 "%s %u (%s)", _(
"Generator"), syncGeneratorList.size() + 1, busData->
busName));
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 {
495 for(auto itSM = syncMotorList.begin(), itSMEnd = syncMotorList.end(); itSM != itSMEnd; ++itSM) {
496 if((*itSM)->GetParentList().size() > 0) {
497 if((*itSM)->GetParentList()[0] == bus) {
498 syncMotor = *itSM;
499 break;
500 }
501 }
502 }
503 if(!syncMotor) {
505 "%s %u (%s)", _(
"Synchronous compensator"), syncMotorList.size() + 1, busData->
busName));
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
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}
Node for power elements. All others power elements are connected through this.
virtual void Rotate(bool clockwise=true)
Rotate the element.
Shunt capactior power element.
double GetWidth() const
Get the element width.
wxPoint2DDouble GetPosition() const
Get the element position.
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,...
void SetWidth(double width)
Set element width.
double GetHeight() const
Get the element height.
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
virtual wxPoint2DDouble RotateAtPosition(wxPoint2DDouble pointToRotate, double angle, bool degrees=true) const
Rotate a point as element position being the origin.
virtual void SetID(int id)
Set the element ID.
virtual void Move(wxPoint2DDouble position)
Move the element other position.
virtual void Rotate(bool clockwise=true)
Rotate the element.
Induction motor power element.
Inductor shunt power element.
virtual void AddPoint(wxPoint2DDouble point)
Add point to the list of points that connect the element to the bus.
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,...
Loas shunt power element.
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,...
Abstract class for rotary machines power elements.
virtual void Move(wxPoint2DDouble position)
Move the element other position.
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,...
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
virtual void Rotate(bool clockwise=true)
Rotate the element.
Class responsible to parse ANAREDE files to import data to PSP.
Abstract class for shunt power elements.
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
virtual void Move(wxPoint2DDouble position)
Move the element other position.
Synchronous generator power element.
Synchronous motor (synchronous compensator) power element.
std::complex< double > loadPower
std::complex< double > genPower
std::complex< double > power