Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
EMTElement Class Reference

Element to connect ATP-EMTP. More...

#include <EMTElement.h>

Inheritance diagram for EMTElement:
Collaboration diagram for EMTElement:

Public Member Functions

 EMTElement (wxString name)
 
virtual ElementGetCopy ()
 Get a the element copy.
 
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, so the parent must be a bus. The element basic points are calculated in this method, so apply this when the element is being inserted.
 
virtual void DrawDC (wxPoint2DDouble translation, double scale, wxGraphicsContext *gc) const
 Draw the element using GDI+.
 
virtual void DrawDC (wxPoint2DDouble translation, double scale, wxDC &dc) const
 Draw the element using wxDC.
 
virtual bool Contains (wxPoint2DDouble position) const
 Checks if the element contains a position.
 
virtual bool Intersects (wxRect2DDouble rect) const
 Check if the element's rect intersects other rect.
 
virtual void Rotate (bool clockwise=true)
 Rotate the element.
 
virtual bool GetContextMenu (wxMenu &menu)
 Get the element contex menu.
 
virtual wxString GetTipText () const
 Get the tip text.
 
virtual bool ShowForm (wxWindow *parent, Element *element)
 Show element data form.
 
virtual rapidxml::xml_node * SaveElement (rapidxml::xml_document<> &doc, rapidxml::xml_node<> *elementListNode)
 
virtual bool OpenElement (rapidxml::xml_node<> *elementNode, std::vector< Element * > parentList)
 
virtual EMTElementData GetEMTElementData ()
 
virtual void SetEMTElementData (EMTElementData data)
 
wxArrayString GetATPNodes (wxArrayString atpFile)
 
bool SetATPParameter (wxTextFile &atpFile, const wxString &card, const int &line, const int &initPos, const int &size, const wxString &value)
 
bool AddConnectionToNode (wxTextFile &atpFile, const wxString &node)
 
std::vector< double > MedianFilter (const std::vector< double > &data)
 
bool CalculateCurrent (wxString &errorMsg, const bool &saveFFTData=false)
 
void UpdateData (const PropertiesData *properties=nullptr, bool updateVoltageBase=false)
 
- Public Member Functions inherited from Shunt
virtual void Move (wxPoint2DDouble position)
 Move the element other position.
 
virtual void MoveNode (Element *element, wxPoint2DDouble position)
 Move a node. StartMove(wxPoint2DDouble position) before start moving.
 
virtual void StartMove (wxPoint2DDouble position)
 Update the element attributes related to the movement.
 
virtual void RotateNode (Element *parent, bool clockwise=true)
 Rotate a node.
 
virtual void RemoveParent (Element *parent)
 Remove a parent.
 
virtual bool NodeContains (wxPoint2DDouble position)
 Check if a node contains a point. If contains, set the attributes related to node movement.
 
virtual bool SetNodeParent (Element *parent)
 Set a perent to the node. If all conditions are met, a new parent are added to the element and the points related to the nodes will be calculated.
 
virtual void UpdateNodes ()
 Update the nodes according to the parents. If a parent is removed, use this method.
 
- Public Member Functions inherited from PowerElement
 PowerElement ()
 Constructor.
 
virtual ~PowerElement ()
 Destructor.
 
virtual wxPoint2DDouble GetSwitchPoint (Element *parent, wxPoint2DDouble parentPoint, wxPoint2DDouble secondPoint) const
 Get the correct switch position.
 
virtual bool SwitchesContains (wxPoint2DDouble position) const
 Check if switch contains position.
 
virtual void UpdateSwitches ()
 Update the switch position.
 
virtual void DrawDCSwitches (wxGraphicsContext *gc) const
 Draw switch.
 
virtual void DrawDCSwitches (wxDC &dc) const
 
virtual void CalculatePowerFlowPts (std::vector< wxPoint2DDouble > edges)
 Calculate the points of the power flow arrows.
 
virtual void DrawDCPowerFlowPts (wxGraphicsContext *gc) const
 Draw power flow arrows.
 
virtual void DrawDCPowerFlowPts (wxDC &dc) const
 
virtual void SetNominalVoltage (std::vector< double > nominalVoltage, std::vector< ElectricalUnit > nominalVoltageUnit)
 Set nominal voltage of the element.
 
virtual void SetSwitchingData (SwitchingData data)
 Set the switching data of the element.
 
virtual SwitchingData GetSwitchingData ()
 Returns the switching data of the element.
 
virtual void SetPowerFlowDirection (PowerFlowDirection pfDirection)
 Set the direction of the power flow.
 
virtual PowerFlowDirection GetPowerFlowDirection () const
 Return the direction of the power flow.
 
virtual bool GetPlotData (ElementPlotData &plotData, PlotStudy study=PlotStudy::STABILITY)
 Fill the plot data.
 
virtual bool HaveDynamicEvent () const
 Check if the power element have dynamic event.
 
virtual void SetDynamicEvent (bool dynEvent=true)
 Set if the power element have dynamic event.
 
virtual double GetValueFromUnit (double value, ElectricalUnit valueUnit)
 
virtual void SaveCADProperties (rapidxml::xml_document<> &doc, rapidxml::xml_node<> *elementNode)
 
virtual void SaveSwitchingData (rapidxml::xml_document<> &doc, rapidxml::xml_node<> *electricalNode)
 
virtual bool OpenCADProperties (rapidxml::xml_node<> *elementNode, std::vector< Element * > parentList)
 
virtual bool OpenSwitchingData (rapidxml::xml_node<> *electricalNode)
 
- Public Member Functions inherited from Element
 Element ()
 Constructor.
 
virtual ~Element ()
 Destructor.
 
void SetDragging (bool dragging=true)
 Set if the element are being dragged.
 
void SetHeight (double height)
 Set element height.
 
void SetPosition (const wxPoint2DDouble position)
 Set the element position and update the rectangle.
 
void SetSelected (bool selected=true)
 Set element selection.
 
void SetWidth (double width)
 Set element width.
 
void SetAngle (double angle)
 Set element angle.
 
void ShowPickbox (bool showPickbox=true)
 Set if the pickbox is shown.
 
void SetBorderSize (double borderSize)
 Set the size of the border (shown in selected elements).
 
bool SetOnline (bool online=true)
 Set if the element is online or offline.
 
virtual void SetPointList (std::vector< wxPoint2DDouble > pointList)
 Set the list of points that connect the element to the bus.
 
ElementType GetElementType ()
 
wxRect2DDouble GetRect () const
 Get the element rectangle.
 
wxPoint2DDouble GetPosition () const
 Get the element position.
 
bool IsDragging () const
 Checks if the element is being dragged.
 
double GetHeight () const
 Get the element height.
 
bool IsSelected () const
 Checks if the element is selected.
 
double GetWidth () const
 Get the element width.
 
double GetAngle () const
 Get the element angle.
 
double GetRotationAngle () const
 Get the angle of rotation.
 
bool IsPickboxShown () const
 Checks if the pickbox is shown.
 
bool IsOnline () const
 Checks if the element is online or offline.
 
virtual std::vector< wxPoint2DDouble > GetPointList () const
 Get the list of points that connect the element to bus.
 
virtual void AddParent (Element *parent)
 Add a parent to the element.
 
virtual void SetID (int id)
 Set the element ID.
 
virtual int GetID () const
 Get the element ID.
 
virtual void AddChild (Element *child)
 Add a child to the child list.
 
virtual void RemoveChild (Element *child)
 Remove a child from the list.
 
virtual void ReplaceChild (Element *oldChild, Element *newChild)
 Replace a child from the list.
 
virtual void AddPoint (wxPoint2DDouble point)
 Add point to the list of points that connect the element to the bus.
 
void SetParent (Element *parent, int num)
 
void SetChild (Element *child, int num)
 
virtual void ReplaceParent (Element *oldParent, Element *newParent)
 Replace a parent.
 
virtual bool PickboxContains (wxPoint2DDouble position)
 Check if a pickbox contains a point. If contains the attributes related to pickbox movement will be calculated.
 
virtual void MovePickbox (wxPoint2DDouble position)
 Move the pickbox.
 
virtual wxCursor GetBestPickboxCursor () const
 Get the best cursor to shown to the user when the mouse is above a pickbox.
 
virtual void ResetPickboxes ()
 Remove the pickboxes.
 
virtual void ResetNodes ()
 Remove the active nodes.
 
virtual wxPoint2DDouble WorldToScreen (wxPoint2DDouble translation, double scale, double offsetX=0.0, double offsetY=0.0) const
 Convert the element position to screen position.
 
virtual wxPoint2DDouble WorldToScreen (wxPoint2DDouble position, wxPoint2DDouble translation, double scale, double offsetX=0.0, double offsetY=0.0) const
 Convert a generic position to screen position.
 
virtual bool RotatedRectanglesIntersects (wxRect2DDouble rect1, wxRect2DDouble rect2, double angle1, double angle2) const
 Check if two roteted rectangles intersect.
 
virtual void DrawDCRectangle (wxPoint2DDouble position, double width, double height, double angle, wxDC &dc) const
 Draw a circle.
 
virtual void DrawDCRoundedRectRotated (wxDC &dc, const wxPoint2DDouble &center, double width, double height, double radius, double angleDeg, int arcSegments=8) const
 
virtual void DrawDCCircle (wxPoint2DDouble position, double radius, int numSegments, wxGraphicsContext *gc) const
 Draw a circle using device context.
 
virtual void DrawDCCircle (wxPoint2DDouble position, double radius, wxDC &dc) const
 
virtual void DrawDCArc (wxPoint2DDouble position, double radius, double initAngle, double finalAngle, int numSegments, wxGraphicsContext *gc) const
 
virtual void DrawDCArc (wxPoint2DDouble position, double radius, double initAngle, double finalAngle, wxDC &dc) const
 
virtual void DrawDCTriangle (std::vector< wxPoint2DDouble > points, wxGraphicsContext *gc) const
 Draw rectangle.
 
virtual void DrawDCTriangle (std::vector< wxPoint > points, wxDC &dc) const
 
virtual void DrawDCPickbox (wxPoint2DDouble position, wxGraphicsContext *gc) const
 Draw a point.
 
virtual wxPoint2DDouble RotateAtPosition (wxPoint2DDouble pointToRotate, double angle, bool degrees=true) const
 Rotate a point as element position being the origin.
 
virtual wxPoint2DDouble RotateLocal (wxPoint2DDouble local, double angleDeg) const
 
virtual wxPoint RotateAround (const wxPoint2DDouble &p, const wxPoint2DDouble &center, double angleDeg) const
 
virtual std::vector< Element * > GetParentList () const
 Get the parent list.
 
virtual std::vector< Element * > GetChildList () const
 Get the Child list.
 
virtual void CalculateBoundaries (wxPoint2DDouble &leftUp, wxPoint2DDouble &rightBottom) const
 Calculate the element boundaries.
 
virtual void GeneralMenuItens (wxMenu &menu)
 Insert general itens to context menu.
 
virtual double PointToLineDistance (wxPoint2DDouble point, int *segmentNumber=nullptr) const
 Calculate the distance between a line (formed by point list) and a point.
 
bool IsInserted () const
 Check if the element is properly inserted in the workspace.
 
void SetInserted (bool inserted=true)
 Set if the element is properly inserted in the workspace.
 
virtual bool OpenElement (rapidxml::xml_node<> *elementNode)
 
void SaveCADProperties (rapidxml::xml_document<> &doc, rapidxml::xml_node<> *elementNode)
 
bool OpenCADProperties (rapidxml::xml_node<> *elementNode)
 

Protected Member Functions

std::vector< double > DoMedianFilter (double *extension, std::vector< double > &result, const int &n)
 
- Protected Member Functions inherited from Shunt
void UpdateSwitchesPosition ()
 
void UpdatePowerFlowArrowsPosition ()
 
void DrawDCGround (wxPoint2DDouble position, wxGraphicsContext *gc) const
 
void DrawDCGround (wxPoint2DDouble position, wxDC &dc) const
 

Protected Attributes

EMTElementData m_data
 
- Protected Attributes inherited from PowerElement
SwitchingData m_swData
 
std::vector< std::vector< wxPoint2DDouble > > m_powerFlowArrow
 
PowerFlowDirection m_pfDirection = PowerFlowDirection::PF_NONE
 
wxColour m_busColour
 
wxColour m_onlineElementColour
 
wxColour m_offlineElementColour
 
wxColour m_closedSwitchColour
 
wxColour m_openedSwitchColour
 
wxColour m_powerFlowArrowColour
 
wxColour m_dynamicEventColour
 
bool m_dynEvent = false
 
- Protected Attributes inherited from Element
ElementType m_elementType = ElementType::TYPE_NONE
 
int m_elementID = 0
 
std::vector< Element * > m_parentList
 
std::vector< Element * > m_childList
 
wxRect2DDouble m_rect
 
wxPoint2DDouble m_position
 
double m_width = 0.0
 
double m_height = 0.0
 
double m_angle = 0.0
 
double m_borderSize = 2.0
 
double m_rotationAngle = 45.0
 
double m_switchSize = 10.0
 
std::vector< wxRect2DDouble > m_switchRect
 
bool m_selected = false
 
bool m_dragging = false
 
bool m_showPickbox = false
 
bool m_inserted = false
 
int m_activePickboxID = ID_PB_NONE
 
int m_activeNodeID = 0
 
std::vector< wxPoint2DDouble > m_pointList
 
std::vector< wxPoint2DDouble > m_movePts
 
wxPoint2DDouble m_moveStartPt
 
wxPoint2DDouble m_movePos
 
bool m_online = true
 
wxColour m_selectionColour
 

Additional Inherited Members

- Static Public Member Functions inherited from Element
static bool DoubleFromString (wxWindow *parent, wxString strValue, double &value, wxString errorMsg)
 Get a double value from a string. Show a error message if the conversion fail.
 
static bool IntFromString (wxWindow *parent, wxString strValue, int &value, wxString errorMsg)
 Convert a string to int. Show a error message if the conversion fail.
 
static wxString StringFromDouble (double value, int minDecimal=1, int maxDecimals=13)
 Convert a double value to string.
 

Detailed Description

Element to connect ATP-EMTP.

Author
Thales Lima Oliveira thale.nosp@m.s@uf.nosp@m.u.br
Date
01/07/2024

Definition at line 64 of file EMTElement.h.

Constructor & Destructor Documentation

◆ EMTElement() [1/2]

EMTElement::EMTElement ( )

Definition at line 15 of file EMTElement.cpp.

16{
17}

◆ EMTElement() [2/2]

EMTElement::EMTElement ( wxString  name)

Definition at line 19 of file EMTElement.cpp.

20{
21 m_data.name = name;
22}

◆ ~EMTElement()

EMTElement::~EMTElement ( )

Definition at line 24 of file EMTElement.cpp.

25{
26}

Member Function Documentation

◆ AddConnectionToNode()

bool EMTElement::AddConnectionToNode ( wxTextFile &  atpFile,
const wxString &  node 
)

Definition at line 432 of file EMTElement.cpp.

433{
434 // Get connnected bus data
435 bool hasBusData = false;
436 BusElectricalData busData;
437 if (!m_parentList.empty()) {
438 if (m_parentList[0] != nullptr) {
439 Bus* bus = static_cast<Bus*>(m_parentList[0]);
440 busData = bus->GetElectricalData();
441 hasBusData = true;
442 }
443 }
444
445 wxString switchMask = " PSPNC%c%s%c MEASURING %d";
446 wxString sourceMask = "14PSPNC%c %s%s%s -1. 100.";
447 wxString lineStr = "";
448 int outCardPos = -1, switchCardPos = -1, sourceCardPos = -1;
449 lineStr = atpFile.GetFirstLine();
450 while (!atpFile.Eof())
451 {
452 if (lineStr.IsEmpty()) {
453 lineStr = atpFile.GetNextLine();
454 continue;
455 }
456 if (tolower(lineStr[0]) == 'c') {
457 lineStr = atpFile.GetNextLine();
458 continue; // Skip comments
459 }
460
461 if (lineStr.Find("/SWITCH") != wxNOT_FOUND)
462 switchCardPos = atpFile.GetCurrentLine() + 1;
463
464 if (lineStr.Find("/SOURCE") != wxNOT_FOUND)
465 sourceCardPos = atpFile.GetCurrentLine() + 1;
466
467 if (lineStr.Find("/OUTPUT") != wxNOT_FOUND)
468 outCardPos = atpFile.GetCurrentLine();
469
470 lineStr = atpFile.GetNextLine();
471 }
472
473 if (outCardPos < 0) return false;
474
475 if (switchCardPos < 0 && outCardPos > 0) {
476 atpFile.InsertLine("/SWITCH", outCardPos);
477 switchCardPos = outCardPos + 1;
478 }
479
480 if (sourceCardPos < 0 && outCardPos > 0) {
481 atpFile.InsertLine("/SOURCE", outCardPos);
482 sourceCardPos = outCardPos + 1;
483 }
484
485 for (char i = 'A'; i <= 'C'; ++i) {
486 lineStr = wxString::Format(switchMask, i, node, i, i == 'A' ? 1 : 0);
487 atpFile.InsertLine(lineStr, switchCardPos + (i - 'A'));
488 }
489 sourceCardPos += 3;
490
491 double voltage = std::abs(m_data.puVoltage) * m_data.baseVoltage * (std::sqrt(2) / std::sqrt(3)); // phase-ground, peak value
492 wxString ampl = wxString::FromCDouble(voltage, 3); // Amplitude in pu
493 wxString freq = wxString::FromCDouble(m_data.frequency, 5); // Frequency in Hz
494 // Insert spaces before to complete 10 characters
495 while (freq.Length() < 10) freq = " " + freq;
496 while (ampl.Length() < 10) ampl = " " + ampl;
497
498 int cardPos = sourceCardPos;
499 for (char i = 'A'; i <= 'C'; ++i) {
500 wxString angle = wxString::FromCDouble(std::arg(m_data.puVoltage) * 180.0 / M_PI - 120.0 * (i - 'A'), 5); // Angle in degrees
501
502 // Insert spaces before to complete 10 characters
503 while (angle.Length() < 10) angle = " " + angle;
504
505 lineStr = wxString::Format(sourceMask, i, ampl, freq, angle);
506 atpFile.InsertLine(lineStr, cardPos);
507 cardPos++;
508
509 if (hasBusData) {
510 // Insert harmonic voltage
511 for (size_t j = 0; j < busData.harmonicOrder.size(); ++j) {
512 int order = busData.harmonicOrder[j];
513 if (order == 1) continue; // Skip fundamental
514
515 std::complex<double> harmVoltage = busData.harmonicVoltage[j];
516
517 voltage = std::abs(busData.harmonicVoltage[j]) * m_data.baseVoltage * (std::sqrt(2) / std::sqrt(3));
518 wxString amplH = wxString::FromCDouble(voltage, 3);
519 while (amplH.Length() < 10) amplH = " " + amplH;
520
521 wxString freqH = wxString::FromCDouble(m_data.frequency * static_cast<double>(order), 5);
522 while (freqH.Length() < 10) freqH = " " + freqH;
523
524 double angleValue = std::arg(harmVoltage) * 180.0 / M_PI;
525 if (order % 3 == 1) { // Positive sequence
526 angleValue += -120.0 * (i - 'A');
527 }
528 else if (order % 3 == 2) { // Negative sequence
529 angleValue += 120.0 * (i - 'A');
530 }
531 // Zero sequence doesn't change the angle because it's the same for all phases
532
533 wxString angleH = wxString::FromCDouble(angleValue, 5);
534 while (angleH.Length() < 10) angleH = " " + angleH;
535
536 lineStr = wxString::Format(sourceMask, i, amplH, freqH, angleH);
537 atpFile.InsertLine(lineStr, cardPos);
538 cardPos++;
539 }
540 }
541 }
542
543 return true;
544}
Node for power elements. All others power elements are connected through this.
Definition Bus.h:86

◆ AddParent()

bool EMTElement::AddParent ( Element parent,
wxPoint2DDouble  position 
)
virtual

Add a parent to the element. This method must be used on power elements that connect to a bus, so the parent must be a bus. The element basic points are calculated in this method, so apply this when the element is being inserted.

Parameters
parentElement parent.
positionNode position in the parent.

Reimplemented from Element.

Definition at line 35 of file EMTElement.cpp.

36{
37 if (parent) {
38 m_parentList.push_back(parent);
39 parent->AddChild(this);
40 wxPoint2DDouble parentPt =
41 parent->RotateAtPosition(position, -parent->GetAngle()); // Rotate click to horizontal position.
42 parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus.
43 parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); // Rotate back.
44
45 m_position = parentPt + wxPoint2DDouble(0.0, 100.0); // Shifts the position to the down of the bus.
46 m_width = 50;
47 m_height = 50;
48 m_rect = wxRect2DDouble(m_position.m_x - m_width / 2.0, m_position.m_y - m_height / 2.0, m_width, m_height);
49
50 m_pointList.push_back(parentPt);
51 m_pointList.push_back(GetSwitchPoint(parent, parentPt, m_position));
52 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -m_height / 2.0 - 10.0));
53 m_pointList.push_back(m_position + wxPoint2DDouble(0.0, -m_height / 2.0));
54
55 m_inserted = true;
56
57 wxRect2DDouble genRect(0, 0, 0, 0);
58 m_switchRect.push_back(genRect); // Push a general rectangle.
60
61 // Base data
62 auto data = static_cast<Bus*>(parent)->GetElectricalData();
63 m_data.puVoltage = data.voltage;
64 m_data.baseVoltage = GetValueFromUnit(data.nominalVoltage, data.nominalVoltageUnit);
65 m_data.frequency = data.stabFreq;
66
67 return true;
68 }
69 return false;
70}
wxPoint2DDouble GetPosition() const
Get the element position.
Definition Element.h:186
double GetAngle() const
Get the element angle.
Definition Element.h:211
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 AddChild(Element *child)
Add a child to the child list.
Definition Element.cpp:566
virtual void UpdateSwitches()
Update the switch position.
virtual wxPoint2DDouble GetSwitchPoint(Element *parent, wxPoint2DDouble parentPoint, wxPoint2DDouble secondPoint) const
Get the correct switch position.
Here is the call graph for this function:

◆ CalculateCurrent()

bool EMTElement::CalculateCurrent ( wxString &  errorMsg,
const bool &  saveFFTData = false 
)

Definition at line 582 of file EMTElement.cpp.

583{
584 wxFileName fileName(m_data.atpFile);
585 if (!fileName.IsOk()) {
586 errorMsg = wxString::Format(_("Invalid ATP file path for the electromagnetic element \"%s\"."), m_data.name);
587 return false;
588 }
589
590 //double fundFreq = properties.GetSimulationPropertiesData().stabilityFrequency;
591 double fundFreq = m_data.frequency;
592 double timeSim = (1.0 / fundFreq) * static_cast<double>(m_data.cyclesToSS);
593
594 //wxString atpFolder = properties.GetGeneralPropertiesData().atpPath.GetPath();
595 wxString atpFolder = m_data.atpPath.GetPath();
596 // Set fundamental frequency to EMT element
597 //m_data.frequency = fundFreq;
598
599 wxExecuteEnv env;
600 env.cwd = atpFolder;
601
602 // Save the ATP file in ATP work folder
603 wxTextFile origFile(m_data.atpFile.GetFullPath());
604 //fileName.SetPath(properties.GetGeneralPropertiesData().atpWorkFolder);
605 fileName.SetPath(m_data.atpWorkFolder);
606 wxString name = fileName.GetFullPath();
607 wxTextFile copyFile(fileName.GetFullPath());
608 if (origFile.Open()) {
609 copyFile.Create();
610 for (size_t i = 0; i < origFile.GetLineCount(); i++) {
611 copyFile.AddLine(origFile.GetLine(i));
612 }
613 origFile.Close();
614
615 wxString stepSizeStr = wxString::Format("%.2E", m_data.stepSize);
616 stepSizeStr.Replace(wxT(","), wxT("."));
617 wxString timeStr = wxString::Format("%.6f", timeSim);
618 timeStr.Replace(wxT(","), wxT("."));
619 SetATPParameter(copyFile, wxT("BEGIN NEW DATA CASE"), 1, 0, 8, stepSizeStr);
620 SetATPParameter(copyFile, wxT("BEGIN NEW DATA CASE"), 1, 8, 8, timeStr);
621 SetATPParameter(copyFile, wxT("BEGIN NEW DATA CASE"), 2, 0, 8, wxT("99999999"));
622 SetATPParameter(copyFile, wxT("BEGIN NEW DATA CASE"), 2, 8, 8, wxString::Format("%8d", m_data.recordFrequency));
623
624 // Add source and switch to selectec node
625 AddConnectionToNode(copyFile, m_data.atpNodeName);
626
627 copyFile.Write();
628 }
629 else {
630 errorMsg = wxString::Format(_("Fail to open ATP file of the electromagnetic element \"%s\"."), m_data.name);
631 return false;
632 }
633
634 //wxString cmd = properties.GetGeneralPropertiesData().atpPath.GetFullPath() + wxT(" both ") + fileName.GetFullPath() + wxT(" s -R");
635 wxString cmd = m_data.atpPath.GetFullPath() + wxT(" both ") + fileName.GetFullPath() + wxT(" s -R");
636 wxExecute(cmd, wxEXEC_SYNC | wxEXEC_HIDE_CONSOLE | wxEXEC_NODISABLE, nullptr, &env);
637
638 // Delete all .tmp files
639 wxDir dir(atpFolder);
640 if (dir.IsOpened()) {
641 wxString file;
642 bool cont = dir.GetFirst(&file, wxT("*.tmp"), wxDIR_FILES);
643 while (cont) {
644 wxRemoveFile(atpFolder + wxT("/") + file);
645 cont = dir.GetNext(&file);
646 }
647 }
648
649 fileName.SetFullName(fileName.GetName() + wxT(".pl4"));
650 wxFileInputStream pl4File(fileName.GetFullPath());
651 // https://github.com/ldemattos/readPL4/wiki/PISA's-PL4-Format---Time-domain
652 if (pl4File.IsOk() && pl4File.GetSize() > 0) {
653 wxDataInputStream store(pl4File);
654 store.UseBasicPrecisions();
655 float* buffer = new float[2];
656 std::vector<double> timeVec;
657 std::vector<double> valueVec;
658 double oldTime = 0.0;
659 int read16Bytes = 0;
660 while (!pl4File.Eof()) {
661 store.ReadFloat(buffer, 2);
662 if (read16Bytes > 11 && (buffer[0] >= oldTime)) {
663 oldTime = buffer[0];
664 timeVec.emplace_back(buffer[0]);
665 valueVec.emplace_back(buffer[1]);
666 }
667 read16Bytes++;
668 }
669 delete[] buffer;
670
671 if (m_data.useMedianFilter)
672 valueVec = MedianFilter(valueVec);
673
674 // FFT
675 double dataStepSize = timeVec[1] - timeVec[0]; // Real sampling time from data
676 bool useRemainder = false;
677 size_t n = ceil(1.0 / (dataStepSize * fundFreq)); // Number of samples
678 // Due to ATP logic, the number of samples can be greater than the number of samples in the PL4 file
679 // In this case, I choose to follow the remainder approach
680 if (n > valueVec.size()) {
681 n = valueVec.size();
682 useRemainder = true;
683 }
684
685 double fs = 1.0 / dataStepSize; // Sampling frequency
686 double df = fs / static_cast<double>(n); // Frequency resolution
687
688 if (useRemainder) {
689 double rmder = abs(remainder(fundFreq, df));
690 int minRmderN = n;
691 while (rmder > 1e-3) {
692 n--;
693 df = fs / static_cast<double>(n);
694
695 if (abs(remainder(fundFreq, df)) < rmder) minRmderN = n;
696
697 rmder = abs(remainder(fundFreq, df));
698
699 if (n <= 0) {
700 n = minRmderN;
701 df = fs / static_cast<double>(n);
702 break;
703 }
704 }
705 }
706
707 double dtWindow = timeVec[timeVec.size() - 1] - timeVec[timeVec.size() - n];
708
709 fftw_complex* out;
710 double* in;
711 fftw_plan p;
712 out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * (n / 2 + 1));
713 in = (double*)fftw_malloc(sizeof(double) * n);
714 // Populate input array
715 for (size_t i = (valueVec.size() - n); i < valueVec.size(); ++i) {
716 size_t index = i - (valueVec.size() - n);
717 in[index] = valueVec[i];
718 }
719
720 p = fftw_plan_dft_r2c_1d(n, in, out, FFTW_ESTIMATE);
721 fftw_execute(p); /* repeat as needed */
722 fftw_destroy_plan(p);
723
724 double ampCorrection = 2.0 / static_cast<double>(n);
725
726 // Identify fundamental frequency
727 int fundIndex = -1;
728 double fundMagnitude = 0.0;
729 for (size_t i = 0; i < (n / 2 + 1); i++) {
730 double freq = static_cast<double>(i) * df;
731 if (remainder(freq, fundFreq)) {
732 fundIndex = i;
733 fundMagnitude = sqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1]) * ampCorrection;
734 break;
735 }
736 }
737 if (fundIndex < 0) {
738 errorMsg = wxString::Format(_("Fail to identify the fundamental frequency of the electromagnetic element \"%s\"."), m_data.name);
739 return false;
740 }
741
742 // Fundamental and harmonics
743 m_data.currHarmonics.clear();
744 //m_data.currHarmonicsOrder.clear();
745 for (size_t i = 0; i < (n / 2 + 1); i++) {
746 double freq = static_cast<double>(i) * df;
747 int order = static_cast<int>(round(freq / fundFreq));
748
749 if (order > m_data.numMaxHarmonics) break; // Stop if the order is greater than the maximum number of harmonics
750
751 double magnitude = sqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1]) * ampCorrection;
752 if ((magnitude / fundMagnitude) > (m_data.harmonicsThreshold / 100.0)) {
753 //m_data.currHarmonics.emplace_back(std::complex<double>(out[i][0], out[i][1]) * ampCorrection);
754 //m_data.currHarmonicsOrder.emplace_back(order);
755 m_data.currHarmonics[order] = std::complex<double>(out[i][0], out[i][1]) * ampCorrection / sqrt(2.0); // RMS value
756 }
757 }
758
759 if (saveFFTData) {
760 m_data.atpData.clear();
761 m_data.inFFTData.clear();
762 m_data.outFFTData.clear();
763 for (size_t i = 0; i < valueVec.size(); i++) {
764 m_data.atpData.emplace_back(std::make_pair(timeVec[i], valueVec[i]));
765 }
766 for (size_t i = 0; i < n; i++) {
767 m_data.inFFTData.emplace_back(std::make_pair(timeVec[i + timeVec.size() - n], in[i]));
768 }
769 for (size_t i = 0; i < (n / 2 + 1); i++) {
770 std::complex<double> value(out[i][0] * ampCorrection, out[i][1] * ampCorrection);
771 double freq = static_cast<double>(i) * df;
772 m_data.outFFTData.emplace_back(std::make_pair(freq, value));
773 }
774 }
775
776 fftw_free(in);
777 fftw_free(out);
778
779 }
780 else {
781 wxString atpErrorMsg = _("No error found.");
782
783 fileName.SetFullName(fileName.GetName() + wxT(".lis"));
784 wxTextFile lisFile(fileName.GetFullPath());
785
786 if (!lisFile.Exists()) {
787 errorMsg = wxString::Format(_("Fail to run ATP file of the electromagnetic element \"%s\".\nThe ATP program did not return any error messages."), m_data.name);
788 return false;
789 }
790 if (lisFile.Open()) {
791 wxString line = lisFile.GetFirstLine() + "\n";
792 bool foundError = false;
793 int lineCount = -1;
794 atpErrorMsg.Clear();
795 while (!lisFile.Eof())
796 {
797 if (line.Find(wxT("KILL ")) != wxNOT_FOUND) {
798 foundError = true;
799 lineCount++;
800 }
801 if (line.Find(wxT("----------")) != wxNOT_FOUND) {
802 foundError = false;
803 }
804 if (foundError && lineCount == 1)
805 atpErrorMsg += line + " ";
806 line = lisFile.GetNextLine();
807 }
808 lisFile.Close();
809 }
810 else
811 {
812 errorMsg = wxString::Format(_("Fail to run ATP file of the electromagnetic element \"%s\".\nThe ATP program did not return any error messages."), m_data.name);
813 return false;
814 }
815
816 errorMsg = wxString::Format(_("Fail to run ATP file of the electromagnetic element \"%s\".\nThe ATP returned the following error message:\n\"%s\""), m_data.name, atpErrorMsg);
817 return false;
818 }
819 return true;
820}

◆ Contains()

virtual bool EMTElement::Contains ( wxPoint2DDouble  position) const
inlinevirtual

Checks if the element contains a position.

Parameters
positionPosition to be checked.

Reimplemented from Shunt.

Definition at line 75 of file EMTElement.h.

75{ return m_rect.Contains(position); }

◆ DoMedianFilter()

std::vector< double > EMTElement::DoMedianFilter ( double *  extension,
std::vector< double > &  result,
const int &  n 
)
protected

Definition at line 844 of file EMTElement.cpp.

845{
846 // Move window through all elements of the signal
847 for (int i = 2; i < n - 2; ++i)
848 {
849 // Pick up window elements
850 double window[5];
851 for (int j = 0; j < 5; ++j)
852 window[j] = extension[i - 2 + j];
853 // Order elements (only half of them)
854 for (int j = 0; j < 3; ++j)
855 {
856 // Find position of minimum element
857 int min = j;
858 for (int k = j + 1; k < 5; ++k)
859 if (window[k] < window[min])
860 min = k;
861 // Put found minimum element in its place
862 const double temp = window[j];
863 window[j] = window[min];
864 window[min] = temp;
865 }
866 // Get result - the middle element
867 result[i - 2] = window[2];
868 }
869 return result;
870}

◆ DrawDC() [1/2]

void EMTElement::DrawDC ( wxPoint2DDouble  translation,
double  scale,
wxDC &  dc 
) const
virtual

Draw the element using wxDC.

Parameters
translationTranslation of the system.
scaleScale of the system.
dcDevice context.

Reimplemented from Element.

Definition at line 156 of file EMTElement.cpp.

157{
158 wxColour elementColour;
159 if (m_online) {
160 if (m_dynEvent)
161 elementColour = m_dynamicEventColour;
162 else
163 elementColour = m_onlineElementColour;
164 }
165 else
166 elementColour = m_offlineElementColour;
167
168 std::vector<wxPoint> pointListInt;
169 for (auto& pt : m_pointList) {
170 pointListInt.emplace_back(static_cast<int>(pt.m_x), static_cast<int>(pt.m_y));
171 }
172
173 if (m_inserted) {
174
175 if (m_selected) {
176 dc.SetPen(wxPen(wxColour(m_selectionColour), 2 + m_borderSize * 2.0));
177 dc.SetBrush(*wxTRANSPARENT_BRUSH);
178
179 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
180
181 DrawDCRoundedRectRotated(dc, m_position, m_width, m_height, 10.0, m_angle);
182
183 // Draw node selection.
184 dc.SetPen(*wxTRANSPARENT_PEN);
185 dc.SetBrush(wxBrush(wxColour(m_selectionColour)));
186 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, dc);
187 }
188 // Draw EMTElement (layer 2).
189 // Draw node.
190 dc.SetPen(*wxTRANSPARENT_PEN);
191 dc.SetBrush(wxBrush(wxColour(elementColour)));
192 DrawDCCircle(pointListInt[0], 5.0, dc);
193
194 dc.SetPen(wxPen(wxColour(elementColour), 2));
195 dc.SetBrush(*wxTRANSPARENT_BRUSH);
196 dc.DrawLines(pointListInt.size(), &pointListInt[0]);
197
198 DrawDCSwitches(dc);
199
200 dc.SetPen(wxPen(wxColour(elementColour), 2));
201 dc.SetBrush(*wxWHITE_BRUSH);
202 DrawDCRoundedRectRotated(dc, m_position, m_width, m_height, 10.0, m_angle);
203
204 wxFont font;
205 font.SetFaceName(wxT("CMU Serif"));
206 font.SetPointSize(10);
207 font.MakeBold();
208 GCText gcText;
209 gcText.SetFont(font);
210 gcText.SetText(_("EMT"));
211 wxPoint pt = RotateAround(m_position + wxPoint2DDouble(0.0, 20.0), m_position, m_angle);
212 gcText.Draw(pt, gcText.GetWidth(), gcText.GetHeight(), dc, m_angle, m_online ? wxColour(255, 60, 0) : m_offlineElementColour);
213 //dc.SetFont(font);
214 //dc.SetTextForeground(m_online ? wxColour(255, 60, 0) : m_offlineElementColour);
215 //int textWidth, textHeight;
216 //dc.GetTextExtent(_("EMT"), &textWidth, &textHeight);
217 //wxPoint pt = RotateAround(wxPoint2DDouble(m_position.m_x, m_position.m_y - m_height / 2.0 + 20.0), m_position, m_angle);
218 //dc.DrawRotatedText(_("EMT"), pt.x, pt.y, -m_angle);
219
220 //wxGCDC* gcdc = new wxGCDC(gc);
221 dc.SetPen(wxPen(m_online ? wxColour(0, 60, 255) : m_offlineElementColour, 2));
222 std::vector<wxPoint> ptList;
223 for (double x = m_position.m_x - m_width / 2.0 + 2; x < (m_position.m_x + m_width / 2.0); x += (m_width - 4.0) / 6.0) {
224 wxPoint pt = RotateAround(wxPoint2DDouble(x, m_position.m_y + std::sin((x - (m_position.m_x - m_width / 2.0 + 2)) / m_width * 6 * M_PI) * 20.0), m_position, m_angle);
225 ptList.emplace_back(pt);
226 }
227 dc.DrawSpline(ptList.size(), ptList.data());
228 }
229}
virtual void DrawDCCircle(wxPoint2DDouble position, double radius, int numSegments, wxGraphicsContext *gc) const
Draw a circle using device context.
Definition Element.cpp:177
Class to draw text on Graphics Context using wxWidgets.
Definition GCText.h:32
virtual void Draw(wxPoint2DDouble position, wxGraphicsContext *gc, double angle=0.0, wxColour colour= *wxBLACK) const
Draw the text in wxGraphicsContext.
Definition GCText.cpp:35
virtual void SetText(wxString text)
Set correctly a new text string.
Definition GCText.cpp:68
virtual void DrawDCSwitches(wxGraphicsContext *gc) const
Draw switch.
Here is the call graph for this function:

◆ DrawDC() [2/2]

void EMTElement::DrawDC ( wxPoint2DDouble  translation,
double  scale,
wxGraphicsContext *  gc 
) const
virtual

Draw the element using GDI+.

Parameters
translationTranslation of the system.
scaleScale of the system.
gcGraphics context

Reimplemented from Element.

Definition at line 72 of file EMTElement.cpp.

73{
74 wxColour elementColour;
75 if (m_online) {
76 if (m_dynEvent)
77 elementColour = m_dynamicEventColour;
78 else
79 elementColour = m_onlineElementColour;
80 }
81 else
82 elementColour = m_offlineElementColour;
83
84 if (m_inserted) {
85
86 if (m_selected) {
87 gc->SetPen(wxPen(wxColour(m_selectionColour), 2 + m_borderSize * 2.0));
88 gc->SetBrush(*wxTRANSPARENT_BRUSH);
89
90 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
91
92 // Push the current matrix on stack.
93 gc->PushState();
94 // Rotate the matrix around the object position.
95 gc->Translate(m_position.m_x, m_position.m_y);
96 gc->Rotate(wxDegToRad(m_angle));
97 gc->Translate(-m_position.m_x, -m_position.m_y);
98
99 //gc->DrawRectangle(m_position.m_x - m_width / 2.0, m_position.m_y - m_height / 2.0, m_width, m_height);
100 gc->DrawRoundedRectangle(m_position.m_x - m_width / 2.0, m_position.m_y - m_height / 2.0, m_width, m_height, 10.0);
101
102 gc->PopState();
103
104 // Draw node selection.
105 gc->SetPen(*wxTRANSPARENT_PEN);
106 gc->SetBrush(wxBrush(wxColour(m_selectionColour)));
107 DrawDCCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, gc);
108 }
109 // Draw EMTElement (layer 2).
110 // Draw node.
111 gc->SetPen(*wxTRANSPARENT_PEN);
112 gc->SetBrush(wxBrush(wxColour(elementColour)));
113 DrawDCCircle(m_pointList[0], 5.0, 10, gc);
114
115 gc->SetPen(wxPen(wxColour(elementColour), 2));
116 gc->SetBrush(*wxTRANSPARENT_BRUSH);
117 gc->StrokeLines(m_pointList.size(), &m_pointList[0]);
118
119 DrawDCSwitches(gc);
120
121 // Push the current matrix on stack.
122 gc->PushState();
123 // Rotate the matrix around the object position.
124 gc->Translate(m_position.m_x, m_position.m_y);
125 gc->Rotate(wxDegToRad(m_angle));
126 gc->Translate(-m_position.m_x, -m_position.m_y);
127
128 gc->SetPen(wxPen(wxColour(elementColour), 2));
129 gc->SetBrush(*wxWHITE_BRUSH);
130 //gc->DrawRectangle(m_position.m_x - m_width / 2.0, m_position.m_y - m_height / 2.0, m_width, m_height);
131 gc->DrawRoundedRectangle(m_position.m_x - m_width / 2.0, m_position.m_y - m_height / 2.0, m_width, m_height, 10.0);
132
133 //gc->SetPen(*wxBLACK_PEN);
134 //wxFont font(10, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
135 wxFont font;
136 font.SetFaceName(wxT("CMU Serif"));
137 font.SetPointSize(10);
138 font.MakeBold();
139 gc->SetFont(font, m_online ? wxColour(255, 60, 0) : m_offlineElementColour);
140 double textWidth, textHeight;
141 gc->GetTextExtent(_("EMT"), &textWidth, &textHeight);
142 gc->DrawText(_("EMT"), m_position.m_x - textWidth / 2.0, m_position.m_y - textHeight / 2.0 + 20.0);
143
144 wxGCDC* gcdc = new wxGCDC(gc);
145 gcdc->SetPen(wxPen(m_online ? wxColour(0, 60, 255) : m_offlineElementColour, 2));
146 std::vector<wxPoint> ptList;
147 for (double x = m_position.m_x - m_width / 2.0 + 2; x < (m_position.m_x + m_width / 2.0); x += (m_width - 4.0) / 6.0) {
148 ptList.emplace_back(x, m_position.m_y + std::sin((x - (m_position.m_x - m_width / 2.0 + 2)) / m_width * 6 * M_PI) * 20.0);
149 }
150 gcdc->DrawSpline(ptList.size(), ptList.data());
151
152 gc->PopState();
153 }
154}
Here is the call graph for this function:

◆ GetATPNodes()

wxArrayString EMTElement::GetATPNodes ( wxArrayString  atpFile)

Definition at line 336 of file EMTElement.cpp.

337{
338 wxArrayString nodeList;
339 uint32_t mode = 0;
340 std::vector<wxString> mode0Cards{ "/OUTPUT", "BLANK", "TACS", "INCLUDE", "TRANSFORMER" };
341 std::vector<wxString> mode1Cards{ "/SOURCE" };
342 std::vector<wxString> mode2Cards{ "/BRANCH", "/SWITCH", };
343 wxString ground = "000000";
344 for (wxString line : atpFile) {
345 if (line.IsEmpty()) continue;
346 if (tolower(line[0]) == 'c') continue; // Skip comments
347
348 bool cardHeader = false;
349 for (wxString card : mode0Cards) {
350 if (line.Find(card) != wxNOT_FOUND) {
351 mode = 0;
352 cardHeader = true;
353 break;
354 }
355 }
356 for (wxString card : mode1Cards) {
357 if (line.Find(card) != wxNOT_FOUND) {
358 mode = 1;
359 cardHeader = true;
360 break;
361 }
362 }
363 for (wxString card : mode2Cards) {
364 if (line.Find(card) != wxNOT_FOUND) {
365 mode = 2;
366 cardHeader = true;
367 break;
368 }
369 }
370 if (cardHeader) continue;
371
372
373 wxString node = "";
374 switch (mode)
375 {
376 case 1: {
377 node = line(2, 6).Trim();
378 node.Replace(" ", "0");
379 if (node != ground && node[5] >= 'A') { // Ignore ground and monophasic nodes
380 if (nodeList.Index(node(0, 5)) == wxNOT_FOUND)
381 nodeList.Add(node(0, 5));
382 }
383 } break;
384 case 2: {
385 node = line(2, 6);
386 if (node != ground && node[5] >= 'A') { // Ignore ground and monophasic nodes
387 if (nodeList.Index(node(0, 5)) == wxNOT_FOUND)
388 nodeList.Add(node(0, 5));
389 }
390 node = line(8, 6);
391 if (node != ground && node[5] >= 'A') { // Ignore ground and monophasic nodes
392 if (nodeList.Index(node(0, 5)) == wxNOT_FOUND)
393 nodeList.Add(node(0, 5));
394 }
395 } break;
396 }
397 }
398 return nodeList;
399}

◆ GetContextMenu()

bool EMTElement::GetContextMenu ( wxMenu &  menu)
virtual

Get the element contex menu.

Parameters
menumenu that will be inserted the element itens.
Returns
True if was possible to build the menu, false otherwise.

Reimplemented from Element.

Definition at line 243 of file EMTElement.cpp.

244{
245 menu.Append(ID_EDIT_ELEMENT, _("Edit Electromagnetic Transient"));
246 GeneralMenuItens(menu);
247 return true;
248}
@ ID_EDIT_ELEMENT
Definition Element.h:75
virtual void GeneralMenuItens(wxMenu &menu)
Insert general itens to context menu.
Definition Element.cpp:457
Here is the call graph for this function:

◆ GetCopy()

Element * EMTElement::GetCopy ( )
virtual

Get a the element copy.

Returns
Copy of the element.

Reimplemented from Element.

Definition at line 28 of file EMTElement.cpp.

29{
30 EMTElement* copy = new EMTElement();
31 *copy = *this;
32 return copy;
33}
Element to connect ATP-EMTP.
Definition EMTElement.h:65

◆ GetEMTElementData()

virtual EMTElementData EMTElement::GetEMTElementData ( )
inlinevirtual

Definition at line 85 of file EMTElement.h.

85{ return m_data; }

◆ GetTipText()

wxString EMTElement::GetTipText ( ) const
virtual

Get the tip text.

Returns
Tip text.

Reimplemented from Element.

Definition at line 250 of file EMTElement.cpp.

251{
252 wxString tipText = m_data.name;
253 tipText += wxT("\n");
254
255 tipText += wxString::Format(_("\nP = %.5f p.u."), m_data.power.real());
256 tipText += wxString::Format(_("\nQ = %.5f p.u."), m_data.power.imag());
257 if (auto itCurrrent = m_data.currHarmonics.find(1); itCurrrent != m_data.currHarmonics.end())
258 tipText += wxString::Format(_("\nI = %.5f A"), std::abs(itCurrrent->second));
259
260 wxString harmonicsInfo = _("\n\nHarmonics info:");
261 bool hasHarmonics = false;
262 for (auto& [order, current] : m_data.currHarmonics) {
263 if (order != 1) {
264 hasHarmonics = true;
265 harmonicsInfo += wxString::Format(_("\nIh(%d): %.5f%s%.2f%s A"), order, std::abs(current), wxString(L'\u2220'), wxRadToDeg(std::arg(current)), wxString(L'\u00B0'));
266 }
267 }
268
269 if (hasHarmonics) tipText += harmonicsInfo;
270
271 return tipText;
272}

◆ Intersects()

virtual bool EMTElement::Intersects ( wxRect2DDouble  rect) const
inlinevirtual

Check if the element's rect intersects other rect.

Parameters
rectRect to check intersection.

Reimplemented from Shunt.

Definition at line 76 of file EMTElement.h.

76{ return m_rect.Intersects(rect); }

◆ MedianFilter()

std::vector< double > EMTElement::MedianFilter ( const std::vector< double > &  data)

Definition at line 546 of file EMTElement.cpp.

547{
548 // Based on: http://www.librow.com/articles/article-1
549
550 size_t n = data.size();
551 std::vector<double> result(data);
552
553 // Check arguments
554 if (data.empty() || n < 1)
555 return result;
556 // Treat special case N = 1
557 if (n == 1)
558 {
559 result[0] = data[0];
560 return result;
561 }
562 // Allocate memory for signal extension
563 double* extension = new double[n + 4];
564 // Check memory allocation
565 //if (!extension)
566 // return;
567 // Create signal extension
568 memcpy(extension + 2, data.data(), n * sizeof(double));
569 for (int i = 0; i < 2; ++i)
570 {
571 extension[i] = data[1 - i];
572 extension[n + 2 + i] = data[n - 1 - i];
573 }
574 // Call median filter implementation
575 result = DoMedianFilter(extension, result, n + 4);
576 // Free memory
577 delete[] extension;
578
579 return result;
580}

◆ OpenElement()

bool EMTElement::OpenElement ( rapidxml::xml_node<> *  elementNode,
std::vector< Element * >  parentList 
)
virtual

Reimplemented from PowerElement.

Definition at line 315 of file EMTElement.cpp.

316{
317 if (!OpenCADProperties(elementNode, parentList)) return false;
318
319 auto electricalProp = elementNode->first_node("ElectricalProperties");
320 if (!electricalProp) return false;
321
322 SetOnline(XMLParser::GetNodeValueInt(electricalProp, "IsOnline"));
323 m_data.name = electricalProp->first_node("Name")->value();
324 m_data.atpFile = wxFileName(electricalProp->first_node("ATPFilePath")->value());
325 m_data.atpNodeName = electricalProp->first_node("ATPNodeName")->value();
326 m_data.stepSize = XMLParser::GetNodeValueDouble(electricalProp, "StepSize");
327 m_data.cyclesToSS = XMLParser::GetNodeValueInt(electricalProp, "CyclesToSS");
328 m_data.recordFrequency = XMLParser::GetNodeValueInt(electricalProp, "RecordFrequency");
329 m_data.useMedianFilter = XMLParser::GetNodeValueInt(electricalProp, "UseMedianFilter");
330 m_data.numMaxHarmonics = XMLParser::GetNodeValueInt(electricalProp, "NumMaxHarmonics");
331
332 m_inserted = true;
333 return true;
334}
bool SetOnline(bool online=true)
Set if the element is online or offline.
Definition Element.cpp:447

◆ Rotate()

void EMTElement::Rotate ( bool  clockwise = true)
virtual

Rotate the element.

Parameters
clockwiseTrue to rotate clockwise, false to rotate counter-clockwise.

Reimplemented from Element.

Definition at line 231 of file EMTElement.cpp.

232{
233 double rotAngle = m_rotationAngle;
234 if (!clockwise) rotAngle = -m_rotationAngle;
235
236 m_angle += rotAngle;
237 if (m_angle >= 360 || m_angle <= -360) m_angle = 0.0;
238 m_pointList[2] = RotateAtPosition(m_pointList[2], rotAngle);
239 m_pointList[3] = RotateAtPosition(m_pointList[3], rotAngle);
240 UpdateSwitchesPosition();
241}
Here is the call graph for this function:

◆ SaveElement()

rapidxml::xml_node * EMTElement::SaveElement ( rapidxml::xml_document<> &  doc,
rapidxml::xml_node<> *  elementListNode 
)
virtual

Reimplemented from Element.

Definition at line 285 of file EMTElement.cpp.

286{
287 auto elementNode = XMLParser::AppendNode(doc, elementListNode, "EMTElement");
288 XMLParser::SetNodeAttribute(doc, elementNode, "ID", m_elementID);
289
290 SaveCADProperties(doc, elementNode);
291
292 auto electricalProp = XMLParser::AppendNode(doc, elementNode, "ElectricalProperties");
293 auto isOnline = XMLParser::AppendNode(doc, electricalProp, "IsOnline");
294 XMLParser::SetNodeValue(doc, isOnline, m_online);
295 auto name = XMLParser::AppendNode(doc, electricalProp, "Name");
296 XMLParser::SetNodeValue(doc, name, m_data.name);
297 auto atpFilePath = XMLParser::AppendNode(doc, electricalProp, "ATPFilePath");
298 XMLParser::SetNodeValue(doc, atpFilePath, m_data.atpFile.GetFullPath());
299 auto atpNodeName = XMLParser::AppendNode(doc, electricalProp, "ATPNodeName");
300 XMLParser::SetNodeValue(doc, atpNodeName, m_data.atpNodeName);
301 auto stepSize = XMLParser::AppendNode(doc, electricalProp, "StepSize");
302 XMLParser::SetNodeValue(doc, stepSize, m_data.stepSize);
303 auto cyclesToSS = XMLParser::AppendNode(doc, electricalProp, "CyclesToSS");
304 XMLParser::SetNodeValue(doc, cyclesToSS, m_data.cyclesToSS);
305 auto recordFrequency = XMLParser::AppendNode(doc, electricalProp, "RecordFrequency");
306 XMLParser::SetNodeValue(doc, recordFrequency, m_data.recordFrequency);
307 auto useMedianFilter = XMLParser::AppendNode(doc, electricalProp, "UseMedianFilter");
308 XMLParser::SetNodeValue(doc, useMedianFilter, m_data.useMedianFilter);
309 auto numMaxHarmonics = XMLParser::AppendNode(doc, electricalProp, "NumMaxHarmonics");
310 XMLParser::SetNodeValue(doc, numMaxHarmonics, m_data.numMaxHarmonics);
311
312 return elementNode;
313}

◆ SetATPParameter()

bool EMTElement::SetATPParameter ( wxTextFile &  atpFile,
const wxString &  card,
const int &  line,
const int &  initPos,
const int &  size,
const wxString &  value 
)

Definition at line 401 of file EMTElement.cpp.

402{
403 bool foundCard = false;
404 int currLine = -1;
405 wxString lineStr = "";
406 lineStr = atpFile.GetFirstLine();
407 while (!atpFile.Eof())
408 {
409 if (tolower(lineStr[0]) == 'c') {
410 lineStr = atpFile.GetNextLine();
411 continue; // Skip comments
412 }
413 if (lineStr.Find(card) != wxNOT_FOUND) {
414 foundCard = true;
415 currLine = -1;
416 }
417 if (foundCard) currLine++;
418 if (foundCard && currLine == line) {
419 for (int i = initPos; i < initPos + size; i++) {
420 lineStr[i] = value[i - initPos];
421 }
422 atpFile.RemoveLine(atpFile.GetCurrentLine());
423 atpFile.InsertLine(lineStr, atpFile.GetCurrentLine());
424 return true;
425 }
426
427 lineStr = atpFile.GetNextLine();
428 }
429 return false;
430}

◆ SetEMTElementData()

virtual void EMTElement::SetEMTElementData ( EMTElementData  data)
inlinevirtual

Definition at line 86 of file EMTElement.h.

86{ m_data = data; }

◆ ShowForm()

bool EMTElement::ShowForm ( wxWindow *  parent,
Element element 
)
virtual

Show element data form.

Parameters
parentForm parent
elementElement that will be edited.
Returns
True if the form is shown, false otherwise.

Reimplemented from Element.

Definition at line 274 of file EMTElement.cpp.

275{
276 EMTElementForm emtForm(parent, this);
277 emtForm.SetTitle(_("Electromagnetic Transient"));
278 emtForm.CenterOnParent();
279 if (emtForm.ShowModal() == wxID_OK) {
280 return true;
281 }
282 return false;
283}

◆ UpdateData()

void EMTElement::UpdateData ( const PropertiesData properties = nullptr,
bool  updateVoltageBase = false 
)

Definition at line 822 of file EMTElement.cpp.

823{
824 if (properties != nullptr) {
825 m_data.frequency = properties->GetSimulationPropertiesData().stabilityFrequency;
826 m_data.atpPath = properties->GetGeneralPropertiesData().atpPath;
827 m_data.atpWorkFolder = properties->GetGeneralPropertiesData().atpWorkFolder;
828 }
829 if (!m_parentList.empty()) {
830 Bus* bus = static_cast<Bus*>(m_parentList[0]);
831 if (bus != nullptr) {
832 auto busData = bus->GetElectricalData();
833 std::complex<double> voltage = std::complex<double>(1.0, 0.0);
834 if (abs(busData.voltage) > 1e-3)
835 m_data.puVoltage = busData.voltage;
836 if (updateVoltageBase) {
837 m_data.baseVoltage = GetValueFromUnit(busData.nominalVoltage, busData.nominalVoltageUnit);
838 }
839 }
840 }
841
842}

Member Data Documentation

◆ m_data

EMTElementData EMTElement::m_data
protected

Definition at line 97 of file EMTElement.h.


The documentation for this class was generated from the following files: