diff --git a/src/antares/service/local_services/thermal_local.py b/src/antares/service/local_services/thermal_local.py index d1ce96f7..63bf9314 100644 --- a/src/antares/service/local_services/thermal_local.py +++ b/src/antares/service/local_services/thermal_local.py @@ -15,8 +15,16 @@ import pandas as pd from antares.config.local_configuration import LocalConfiguration -from antares.model.thermal import ThermalCluster, ThermalClusterMatrixName, ThermalClusterProperties +from antares.model.thermal import ( + ThermalCluster, + ThermalClusterMatrixName, + ThermalClusterProperties, + ThermalClusterPropertiesLocal, +) from antares.service.base_services import BaseThermalService +from antares.tools.ini_tool import IniFile, IniFileTypes +from antares.tools.matrix_tool import read_timeseries +from antares.tools.time_series_tool import TimeSeriesFileType class ThermalLocalService(BaseThermalService): @@ -31,7 +39,75 @@ def update_thermal_properties( raise NotImplementedError def get_thermal_matrix(self, thermal_cluster: ThermalCluster, ts_name: ThermalClusterMatrixName) -> pd.DataFrame: - raise NotImplementedError + if ts_name.value == "series": + time_serie_type = TimeSeriesFileType.THERMAL_SERIES + elif ts_name.value == "modulation": + time_serie_type = TimeSeriesFileType.THERMAL_MODULATION + elif ts_name.value == "data": + time_serie_type = TimeSeriesFileType.THERMAL_DATA + elif ts_name.value == "CO2Cost": + time_serie_type = TimeSeriesFileType.THERMAL_CO2 + else: + time_serie_type = TimeSeriesFileType.THERMAL_FUEL + + return read_timeseries( + time_serie_type, + self.config.study_path, + area_id=thermal_cluster.area_id, + cluster_id=thermal_cluster.properties.group.value, + ) def read_thermal_clusters(self, area_id: str) -> List[ThermalCluster]: - raise NotImplementedError + thermal_dict = IniFile(self.config.study_path, IniFileTypes.THERMAL_LIST_INI, area_name=area_id).ini_dict + thermal_clusters = [] + if thermal_dict: + for thermal_cluster in thermal_dict: + # TODO refactor this as it is really not clean + thermal_properties = ThermalClusterPropertiesLocal( + group=thermal_dict[thermal_cluster]["group"], + thermal_name=thermal_dict[thermal_cluster]["name"], + enabled=thermal_dict[thermal_cluster]["enabled"], + unit_count=thermal_dict[thermal_cluster]["unitcount"], + nominal_capacity=thermal_dict[thermal_cluster]["nominalcapacity"], + gen_ts=thermal_dict[thermal_cluster]["gen-ts"], + min_stable_power=thermal_dict[thermal_cluster]["min-stable-power"], + min_up_time=thermal_dict[thermal_cluster]["min-up-time"], + min_down_time=thermal_dict[thermal_cluster]["min-down-time"], + must_run=thermal_dict[thermal_cluster]["must-run"], + spinning=thermal_dict[thermal_cluster]["spinning"], + volatility_forced=thermal_dict[thermal_cluster]["volatility.forced"], + volatility_planned=thermal_dict[thermal_cluster]["volatility.planned"], + law_forced=thermal_dict[thermal_cluster]["law.forced"], + law_planned=thermal_dict[thermal_cluster]["law.planned"], + marginal_cost=thermal_dict[thermal_cluster]["marginal-cost"], + spread_cost=thermal_dict[thermal_cluster]["spread-cost"], + fixed_cost=thermal_dict[thermal_cluster]["fixed-cost"], + startup_cost=thermal_dict[thermal_cluster]["startup-cost"], + market_bid_cost=thermal_dict[thermal_cluster]["market-bid-cost"], + co2=thermal_dict[thermal_cluster]["co2"], + nh3=thermal_dict[thermal_cluster]["nh3"], + so2=thermal_dict[thermal_cluster]["so2"], + nox=thermal_dict[thermal_cluster]["nox"], + pm2_5=thermal_dict[thermal_cluster]["pm2_5"], + pm5=thermal_dict[thermal_cluster]["pm5"], + pm10=thermal_dict[thermal_cluster]["pm10"], + nmvoc=thermal_dict[thermal_cluster]["nmvoc"], + op1=thermal_dict[thermal_cluster]["op1"], + op2=thermal_dict[thermal_cluster]["op2"], + op3=thermal_dict[thermal_cluster]["op3"], + op4=thermal_dict[thermal_cluster]["op4"], + op5=thermal_dict[thermal_cluster]["op5"], + cost_generation=thermal_dict[thermal_cluster]["costgeneration"], + efficiency=thermal_dict[thermal_cluster]["efficiency"], + variable_o_m_cost=thermal_dict[thermal_cluster]["variableomcost"], + ) + + thermal_clusters.append( + ThermalCluster( + thermal_service=self, + area_id=area_id, + name=thermal_dict[thermal_cluster]["name"], + properties=thermal_properties.yield_thermal_cluster_properties(), + ) + ) + return thermal_clusters diff --git a/src/antares/tools/time_series_tool.py b/src/antares/tools/time_series_tool.py index fe737535..02d2a11a 100644 --- a/src/antares/tools/time_series_tool.py +++ b/src/antares/tools/time_series_tool.py @@ -49,6 +49,11 @@ class TimeSeriesFileType(Enum): WIND_K = "input/wind/prepro/{area_id}/k.txt" WIND_TRANSLATION = "input/wind/prepro/{area_id}/translation.txt" RENEWABLE_DATA_SERIES = "input/renewables/series/{area_id}/{cluster_id}/series.txt" + THERMAL_SERIES = "input/thermal/series/{area_id}/{cluster_id}/series.txt" + THERMAL_DATA = "input/thermal/prepro/{area_id}/{cluster_id}/data.txt" + THERMAL_MODULATION = "input/thermal/prepro/{area_id}/{cluster_id}/modulation.txt" + THERMAL_CO2 = "input/thermal/series/{area_id}/{cluster_id}/C02Cost.txt" + THERMAL_FUEL = "input/thermal/series/{area_id}/{cluster_id}/fuelCost.txt" class TimeSeries: diff --git a/tests/antares/services/local_services/test_area.py b/tests/antares/services/local_services/test_area.py index af32cf9e..1a9f7f02 100644 --- a/tests/antares/services/local_services/test_area.py +++ b/tests/antares/services/local_services/test_area.py @@ -1306,3 +1306,71 @@ def test_read_misc_gen_local(self, local_study_w_areas): _write_file(file_path, expected_time_serie) matrix = area.get_misc_gen_matrix() pd.testing.assert_frame_equal(matrix, expected_time_serie) + + +class TestReadThermal: + def test_read_thermals_local(self, local_study_w_thermal): + study_path = local_study_w_thermal.service.config.study_path + local_study_object = read_study_local(study_path) + areas = local_study_object.read_areas() + + for area in areas: + expected_time_serie = pd.DataFrame( + [ + [-9999999980506447872, 0, 9999999980506447872], + [0, area.id, 0], + ], + dtype="object", + ) + + thermals_list = area.read_thermal_clusters(area.id) + + if thermals_list: + assert area.id == "fr" + assert isinstance(thermals_list, list) + assert isinstance(thermals_list[0], ThermalCluster) + + for thermal in thermals_list: + assert thermal.name == "test thermal cluster" + assert thermal.properties.group.value == "Other 1" + assert thermal.properties.unit_count == 1 + assert thermal.properties.efficiency == 100.000000 + assert thermal.properties.nominal_capacity == 0.000000 + assert thermal.properties.enabled + assert thermal.properties.cost_generation.value == "SetManually" + + # Create folder and file for timeserie. + cluster_path = ( + study_path / "input" / "thermal" / "series" / Path(area.id) / Path(thermal.properties.group.value) + ) + series_path = cluster_path / "series.txt" + os.makedirs(cluster_path, exist_ok=True) + _write_file(series_path, expected_time_serie) + + co2_cost_path = cluster_path / "C02Cost.txt" + _write_file(co2_cost_path, expected_time_serie) + + fuelCost_path = cluster_path / "fuelCost.txt" + _write_file(fuelCost_path, expected_time_serie) + + cluster_path = ( + study_path / "input" / "thermal" / "prepro" / Path(area.id) / Path(thermal.properties.group.value) + ) + os.makedirs(cluster_path, exist_ok=True) + series_path_1 = cluster_path / "data.txt" + series_path_2 = cluster_path / "modulation.txt" + _write_file(series_path_1, expected_time_serie) + _write_file(series_path_2, expected_time_serie) + + # Check matrix + matrix = thermal.get_prepro_data_matrix() + matrix_1 = thermal.get_prepro_modulation_matrix() + matrix_2 = thermal.get_series_matrix() + matrix_3 = thermal.get_co2_cost_matrix() + matrix_4 = thermal.get_fuel_cost_matrix() + + pd.testing.assert_frame_equal(matrix.astype(str), expected_time_serie.astype(str), check_dtype=False) + pd.testing.assert_frame_equal(matrix_1.astype(str), expected_time_serie.astype(str), check_dtype=False) + pd.testing.assert_frame_equal(matrix_2.astype(str), expected_time_serie.astype(str), check_dtype=False) + pd.testing.assert_frame_equal(matrix_3.astype(str), expected_time_serie.astype(str), check_dtype=False) + pd.testing.assert_frame_equal(matrix_4.astype(str), expected_time_serie.astype(str), check_dtype=False)