diff --git a/src/cimsparql/adaptions.py b/src/cimsparql/adaptions.py index 4460a4bb..a2819490 100644 --- a/src/cimsparql/adaptions.py +++ b/src/cimsparql/adaptions.py @@ -73,6 +73,7 @@ def set_generation_type(self) -> None: def adapt(self, eq_uri: str) -> None: self.add_zero_sv_power_flow() self.add_zero_sv_injection() + self.add_generating_unit() self.add_mrid() self.add_dtypes() self.set_generation_type() @@ -150,6 +151,13 @@ def add_network_analysis_enable(self) -> None: prepared_update_query = prepareUpdate(query.substitute(self.namespaces())) self.graph.update(prepared_update_query) + def add_generating_unit(self) -> None: + with open(Path(__file__).parent / "sparql/test_configuration_modifications/add_gen_unit_mrid.sparql") as f: + query = Template(f.read()) + + prepared_update_query = prepareUpdate(query.substitute(self.namespaces())) + self.graph.update(prepared_update_query) + def is_uuid(x: str) -> bool: return re.match("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", x) is not None diff --git a/src/cimsparql/data_models.py b/src/cimsparql/data_models.py index d9e4bc6b..e0405c05 100644 --- a/src/cimsparql/data_models.py +++ b/src/cimsparql/data_models.py @@ -412,3 +412,11 @@ class AssociatedSwitches(CoercingSchema): AssociatedSwitchesDataFrame = DataFrame[AssociatedSwitches] + + +class GenUnitAndSyncMachineMridSchema(CoercingSchema): + gen_unit_mrid: str = pa.Field(unique=True) + sync_machine_mrid: str = pa.Field(unique=True) + + +GenUnitAndSyncMachineMridDataFrame = DataFrame[GenUnitAndSyncMachineMridSchema] diff --git a/src/cimsparql/model.py b/src/cimsparql/model.py index 14294d75..f59fee35 100644 --- a/src/cimsparql/model.py +++ b/src/cimsparql/model.py @@ -31,6 +31,7 @@ DisconnectedDataFrame, ExchangeDataFrame, FullModelDataFrame, + GenUnitAndSyncMachineMridDataFrame, HVDCBidzonesDataFrame, HVDCDataFrame, LoadsDataFrame, @@ -690,6 +691,11 @@ def associated_switches(self) -> AssociatedSwitchesDataFrame: query = self.template_to_query(templates.ASSOCIATED_SWITCHES) return AssociatedSwitchesDataFrame(self.get_table_and_convert(query)) + @time_it + def gen_unit_and_sync_machine_mrid(self) -> GenUnitAndSyncMachineMridDataFrame: + query = self.template_to_query(templates.GEN_UNIT_MRID_AND_SYNC_MACHINE) + return GenUnitAndSyncMachineMridDataFrame(self.get_table_and_convert(query)) + class SingleClientModel(Model): def __init__( diff --git a/src/cimsparql/sparql/gen_unit_and_sync_machine_mapping.sparql b/src/cimsparql/sparql/gen_unit_and_sync_machine_mapping.sparql new file mode 100644 index 00000000..1f1273a7 --- /dev/null +++ b/src/cimsparql/sparql/gen_unit_and_sync_machine_mapping.sparql @@ -0,0 +1,6 @@ +# Name: GeneratingUnit mrid to physical equipment mrid +PREFIX cim: <${cim}> +select ?gen_unit_mrid ?sync_machine_mrid where { + ?s cim:SynchronousMachine.GeneratingUnit/cim:IdentifiedObject.mRID ?gen_unit_mrid; + cim:IdentifiedObject.mRID ?sync_machine_mrid +} diff --git a/src/cimsparql/sparql/test_configuration_modifications/add_gen_unit_mrid.sparql b/src/cimsparql/sparql/test_configuration_modifications/add_gen_unit_mrid.sparql new file mode 100644 index 00000000..8daeb134 --- /dev/null +++ b/src/cimsparql/sparql/test_configuration_modifications/add_gen_unit_mrid.sparql @@ -0,0 +1,12 @@ +prefix cim:<${cim}> +prefix SN:<${SN}> +insert { + graph { + _:b0 a SN:GeneratingUnit; + cim:IdentifiedObject.name "GeneratingUnit" . + ?machine cim:SynchronousMachine.GeneratingUnit _:b0 + }} +where { + ?machine a cim:SynchronousMachine + filter not exists{?machine cim:SynchronousMachine.GeneratingUnit ?unit} +} diff --git a/src/cimsparql/templates.py b/src/cimsparql/templates.py index f2750fb2..4be65a45 100644 --- a/src/cimsparql/templates.py +++ b/src/cimsparql/templates.py @@ -24,6 +24,7 @@ def _read_template(filename: pathlib.Path) -> Template: DISCONNECTED_QUERY = _read_template(sparql_folder / "disconnected.sparql") EXCHANGE_QUERY = _read_template(sparql_folder / "exchange.sparql") FULL_MODEL_QUERY = _read_template(sparql_folder / "full_model.sparql") +GEN_UNIT_MRID_AND_SYNC_MACHINE = _read_template(sparql_folder / "gen_unit_and_sync_machine_mapping.sparql") HVDC = _read_template(sparql_folder / "hvdc.sparql") HVDC_CONVERTER_BIDZONES = _read_template(sparql_folder / "converter_hvdc_bidzones.sparql") LOADS_QUERY = _read_template(sparql_folder / "loads.sparql") diff --git a/tests/test_graphdb.py b/tests/test_graphdb.py index 157a9138..3ba495ec 100644 --- a/tests/test_graphdb.py +++ b/tests/test_graphdb.py @@ -65,6 +65,7 @@ async def collect_data(model: Model) -> dict[str, pd.DataFrame]: model.disconnected, model.exchange, model.full_model, + model.gen_unit_and_sync_machine_mrid, model.hvdc_converter_bidzones, model.loads, model.market_dates, diff --git a/tests/test_micro_t1_nl.py b/tests/test_micro_t1_nl.py index c3c69654..8fc1ffe9 100644 --- a/tests/test_micro_t1_nl.py +++ b/tests/test_micro_t1_nl.py @@ -352,3 +352,12 @@ def test_associated_switches(test_model: t_common.ModelTest) -> None: # Test values for power transformer BE-TR3. Should be connected to two switches switches = set(df.query("name == 'BE-TR2_1'")["switch_names"].iloc[0].split(",")) assert switches == {"BE_Breaker_1", "BE_Breaker_2"} + + +@pytest.mark.parametrize("test_model", t_entsoe.micro_models()) +def test_gen_unit_and_sync_machine_mrid(test_model: t_common.ModelTest) -> None: + t_common.check_model(test_model) + assert test_model.model + + df = test_model.model.gen_unit_and_sync_machine_mrid() + assert len(df) == 4 diff --git a/tests/test_xml_adaptor.py b/tests/test_xml_adaptor.py index 4ba334ae..dd19c7d3 100644 --- a/tests/test_xml_adaptor.py +++ b/tests/test_xml_adaptor.py @@ -64,3 +64,9 @@ def test_add_network_analysis_enable(xml_adaptor: XmlModelAdaptor) -> None: xml_adaptor.add_network_analysis_enable() query = "select * {?terminal cim:Terminal.ConductingEquipment/SN:Equipment.networkAnalysisEnable True}" assert len(xml_adaptor.graph.query(query, initNs=xml_adaptor.namespaces())) > 0 + + +def test_add_generating_unit(xml_adaptor: XmlModelAdaptor) -> None: + xml_adaptor.add_generating_unit() + query = "select * {?machine cim:SynchronousMachine.GeneratingUnit ?unit}" + assert len(xml_adaptor.graph.query(query, initNs=xml_adaptor.namespaces())) > 0