Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion epowcore/power_factory/to_gdf/power_factory_extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ def extract_switches(self) -> None:
self.uid += 1
self._component_dict[pf_switch] = switch
self.graph.add_node(pf_switch)

def extract_fuses(self) -> None:
"""Extract the PowerFactory fuses to the data format. Currently represented as a switch for the gdf"""
pf_fuses = self.app.GetCalcRelevantObjects("RelFuse")
Expand Down Expand Up @@ -323,6 +323,12 @@ def select_pss_type(self, generator: Any) -> None:
self.graph.add_node(pss)
# Create edge with the appropriate generator
self.graph.add_edge(pss, generator)
self.graph.edges[pss, generator].update(
{
generic_pss.uid: generic_pss.connector_names.copy(),
self._component_dict[generator].uid: [],
}
)

def select_avr_type(self, generator: Any) -> None:
"""Selects one of the currently supported Exciter to extract"""
Expand All @@ -348,6 +354,12 @@ def select_avr_type(self, generator: Any) -> None:
self.graph.add_node(avr)
# Create edge with the appropriate generator
self.graph.add_edge(avr, generator)
self.graph.edges[avr, generator].update(
{
generic_avr.uid: generic_avr.connector_names.copy(),
self._component_dict[generator].uid: [],
}
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When trying to import the example IEEE 39 Grid from PowerFactory to GDF, this fails for me, with KeyError[really long object] is not in the graph.

I say we postpone this PR until it is properly tested with multiple exports.
I don't want to merge this into main, where we have a running importer (even though it is generating models with a slight issue).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproduced the IEEE39 KeyError locally. The controller metadata was being updated before the corresponding graph edge existed, so I added the missing generator edges for AVR, governor, and PSS before updating the metadata.

Re-tested with the PowerFactory 39 Bus New England System: import now completes with 140 nodes / 147 edges and includes IEEET1, IEEEG1, and PTIST1 controller connections. I also smoke-tested the 14 Bus export. Core tests: 51 passed, 8 skipped.


def select_gov_type(self, generator: Any) -> None:
"""Selects one of the currently supported Governor to extract"""
Expand Down Expand Up @@ -382,6 +394,12 @@ def select_gov_type(self, generator: Any) -> None:
self.graph.add_node(gov)
# Create edge with the appropriate generator
self.graph.add_edge(gov, generator)
self.graph.edges[gov, generator].update(
{
generic_gov.uid: generic_gov.connector_names.copy(),
self._component_dict[generator].uid: [],
}
)

def set_core_model_graph(self) -> None:
"""This creates the graph for the GenericCoreModel"""
Expand Down
17 changes: 17 additions & 0 deletions tests/power_factory/pf_converter_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import unittest

from epowcore.gdf.exciters.exciter import Exciter
from epowcore.gdf.governors.governor import Governor
from epowcore.gdf.power_system_stabilizers.power_system_stabilizer import PowerSystemStabilizer
from epowcore.gdf.transformers.two_winding_transformer import TwoWindingTransformer
from epowcore.power_factory.power_factory_converter import PFModel, PowerFactoryConverter

Expand All @@ -10,22 +14,35 @@ def test_minimal_conversion_no_errors(self) -> None:
"""Test if the CoreModel extraction from the Minimal PF model throws errors."""
converter = PowerFactoryConverter()
core_model = converter.to_gdf(PFModel("Minimal", "Base", 50.0))

self.assertEqual(len(core_model.graph.nodes), 8)
self.assertEqual(len(core_model.graph.edges), 7)

two_winding_id = core_model.type_list(TwoWindingTransformer)[0].uid

self.assertTrue(
any(
two_winding_id in x[2] and x[2][two_winding_id] == ["HV"]
for x in core_model.graph.edges.data()
)
)

self.assertTrue(
any(
two_winding_id in x[2] and x[2][two_winding_id] == ["LV"]
for x in core_model.graph.edges.data()
)
)

for controller_type in (Exciter, Governor, PowerSystemStabilizer):
controller = core_model.type_list(controller_type)[0]
self.assertTrue(
any(
controller.uid in edge_data and edge_data[controller.uid] == ["In", "Out"]
for _, _, edge_data in core_model.graph.edges.data()
)
)


if __name__ == "__main__":
unittest.main()
Loading