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));
117 bus->
SetID((*it)->id);
118 bus->
SetWidth((*it)->length * scale);
120 if((*it)->rotationID == 0) {
122 } else if((*it)->rotationID == 1) {
123 for(
int i = 0; i < (*it)->rotationID * 2; ++i) bus->
Rotate();
125 } else if((*it)->rotationID == 2) {
126 for(
int i = 0; i < (*it)->rotationID * 2; ++i) bus->
Rotate();
128 } else if((*it)->rotationID == 3) {
129 for(
int i = 0; i < (*it)->rotationID * 2; ++i) bus->
Rotate();
131 }
132
133
134 auto data = bus->GetElectricalData();
136 if(busData) {
137 data.number = busData->
id;
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;
168
169 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
170 wxPoint2DDouble nodePos =
171 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
172
174 bool isMotor = false;
175 if(busData->
genPower.real() <= 0.0) isMotor =
true;
177
178 if(!isMotor) {
180
181 auto data = syncGenerator->GetElectricalData();
182 data.name =
183 wxString::Format(
"%s %u (%s)", _(
"Generator"), syncGeneratorList.size() + 1, busData->
busName);
188 double numUnits =
static_cast<double>(genData->
numUnits);
189 data.activePower = genData->
power.real() * numUnits;
190 data.reactivePower = genData->
power.imag() * 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();
203 data.useMachineBase = false;
204 }
205
206 syncGenerator->SetElectricalData(data);
207
208 machine = syncGenerator;
209 } else {
211
212 auto data = syncMotor->GetElectricalData();
213 data.name = wxString::Format("%s %u (%s)", _("Synchronous compensator"), syncMotorList.size() + 1,
215 data.activePower = busData->
genPower.real() == 0.0 ? 0.0 : -busData->
genPower.real();
216 data.reactivePower = busData->
genPower.imag();
219 data.useMachineBase = false;
220
221 syncMotor->SetElectricalData(data);
222
223 machine = syncMotor;
224 }
225
226 if(machine) {
227 machine->
SetID((*it)->id);
229
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);
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;
244 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
245 wxPoint2DDouble nodePos =
246 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
247
249
251 load->
SetID((*it)->id);
253
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;
269 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
270 wxPoint2DDouble nodePos =
271 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
272
274 bool isInductor = false;
275 Shunt* shuntElement =
nullptr;
276
277 double ql = 0.0;
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 {
287 }
288 if(ql <= 0.0) isInductor = true;
289
290 if(!isInductor) {
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 {
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
311
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
316 shuntElement->
Move(wxPoint2DDouble((*it)->position.m_x * scale, (*it)->position.m_y * scale));
317
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;
333
334 Bus* parentBus = GetBusFromID(busList, (*it)->busConnectionID[0].first);
335 wxPoint2DDouble nodePos =
336 parseAnarede.GetNodePositionFromID(parentBus, scale, (*it)->busConnectionNode[0].second);
337
339 indMotor->
SetID((*it)->id);
341
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);
353 for(
int i = 0; i < (*it)->rotationID * 2; ++i) indMotor->
Rotate();
354
355 indMotorList.push_back(indMotor);
356 } break;
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
366 parseAnarede.GetBranchDataFromID((*it)->electricalID, (*it)->busConnectionID[0].second,
368
370 transformer->
SetID((*it)->id);
371 transformer->
AddParent(parentBus1, nodePos1);
372 transformer->
AddParent(parentBus2, nodePos2);
373
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();
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;
386 data.turnsRatio = branchData->
tap;
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) {
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
408 (*it)->electricalID, (*it)->busConnectionID[0].second, (*it)->busConnectionID[1].second,
ANA_LINE);
409
411 line->
SetID((*it)->id);
413 for(unsigned int i = 0; i < (*it)->nodesPosition.size(); ++i)
415 wxPoint2DDouble((*it)->nodesPosition[i].m_x * scale, (*it)->nodesPosition[i].m_y * scale));
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;
424 line->SetElectricalData(data);
425
426 lineList.push_back(line);
427 }
428 }
429
430
431 std::vector<ParseAnarede::BusData*> busDataVector = parseAnarede.GetBusData();
432 for(auto it = busDataVector.begin(), itEnd = busDataVector.end(); it != itEnd; ++it) {
434
435
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
445 if(std::abs(busData->
loadPower.real()) > 1e-5 ||
446 std::abs(busData->
loadPower.imag()) > 1e-5) {
447
448 Load* load =
nullptr;
449 for(auto itL = loadList.begin(), itLEnd = loadList.end(); itL != itLEnd; ++itL) {
450 if((*itL)->GetParentList().size() > 0) {
451 if((*itL)->GetParentList()[0] == bus) {
452 load = *itL;
453 break;
454 }
455 }
456 }
457 if(!load) {
459 new Load(wxString::Format(
"%s %u (%s)", _(
"Load"), loadList.size() + 1, busData->
busName));
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
470 if(std::abs(busData->
genPower.real()) > 1e-5 || std::abs(busData->
genPower.imag()) > 1e-5) {
471
472 if(busData->
genPower.real() > 0.0) {
474 for(auto itSM = syncGeneratorList.begin(), itSMEnd = syncGeneratorList.end(); itSM != itSMEnd;
475 ++itSM) {
476 if((*itSM)->GetParentList().size() > 0) {
477 if((*itSM)->GetParentList()[0] == bus) {
478 syncGenerator = *itSM;
479 break;
480 }
481 }
482 }
483 if(!syncGenerator) {
485 "%s %u (%s)", _(
"Generator"), syncGeneratorList.size() + 1, busData->
busName));
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 {
496 for(auto itSM = syncMotorList.begin(), itSMEnd = syncMotorList.end(); itSM != itSMEnd; ++itSM) {
497 if((*itSM)->GetParentList().size() > 0) {
498 if((*itSM)->GetParentList()[0] == bus) {
499 syncMotor = *itSM;
500 break;
501 }
502 }
503 }
504 if(!syncMotor) {
506 "%s %u (%s)", _(
"Synchronous compensator"), syncMotorList.size() + 1, busData->
busName));
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
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}
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.
void SetInserted(bool inserted=true)
Set if the element is properly inserted in the workspace.
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