diff --git a/config/config.default.yaml b/config/config.default.yaml index bb1a156e73..48d359d410 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -488,7 +488,7 @@ sector: dynamic_capacity: true supplemental_heating: enable: false - booster_heat_pump: false + booster_technologies: [] max_top_temperature: 90 min_bottom_temperature: 35 ates: diff --git a/config/plotting.default.yaml b/config/plotting.default.yaml index f3a827a6e6..79b76896ee 100644 --- a/config/plotting.default.yaml +++ b/config/plotting.default.yaml @@ -424,6 +424,7 @@ plotting: urban central water pits: "#d96f4c" urban central water pits charger: "#a85d47" urban central water pits discharger: "#b36452" + urban central water pits boosting: "#ffa36c" aquifer thermal energy storage: "#6d00fc" aquifer thermal energy storage charger: "#6d00fc" aquifer thermal energy storage discharger: "#6d00fc" @@ -470,11 +471,13 @@ plotting: CHP electric: '#8a5751' district heating: '#e8beac' resistive heater: '#d8f9b8' + ptes resistive heater: '#a0e78d' residential rural resistive heater: '#bef5b5' residential urban decentral resistive heater: '#b2f1a9' services rural resistive heater: '#a5ed9d' services urban decentral resistive heater: '#98e991' urban central resistive heater: '#8cdf85' + urban central ptes resistive heater: '#71c96b' retrofitting: '#8487e8' building retrofitting: '#8487e8' # hydrogen diff --git a/config/test/config.myopic.yaml b/config/test/config.myopic.yaml index 44182c1496..69a68a1d2a 100644 --- a/config/test/config.myopic.yaml +++ b/config/test/config.myopic.yaml @@ -39,7 +39,10 @@ sector: ptes: supplemental_heating: enable: true - booster_heat_pump: true + booster_technologies: ["heat_pump", "resistive_heaters"] + heat_pump_sources: + urban central: + - ptes electricity: extendable_carriers: diff --git a/config/test/config.overnight.yaml b/config/test/config.overnight.yaml index cd3730b0c1..5a40f59f87 100644 --- a/config/test/config.overnight.yaml +++ b/config/test/config.overnight.yaml @@ -65,9 +65,12 @@ sector: ptes: supplemental_heating: enable: true - booster_heat_pump: true + booster_technologies: ["heat_pump", "resistive_heaters"] ates: enable: true + heat_pump_sources: + urban central: + - ptes industry: diff --git a/config/test/config.perfect.yaml b/config/test/config.perfect.yaml index 291088ac4c..1817adf863 100644 --- a/config/test/config.perfect.yaml +++ b/config/test/config.perfect.yaml @@ -48,9 +48,12 @@ sector: ptes: supplemental_heating: enable: true - booster_heat_pump: true + booster_technologies: ["heat_pump", "resistive_heaters"] ates: enable: true + heat_pump_sources: + urban central: + - ptes atlite: diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index 539238c1bf..604253d5c2 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -22,8 +22,9 @@ district_heating,--,, -- ptes,,, -- -- dynamic_capacity,--,"{true, false}",Add option for dynamic temperature-dependent energy capacity of pit storage in district heating -- -- supplemental_heating,,, --- -- -- enable,--,"{true, false}",Add option to enable supplemental heating of pit storage in district heating --- -- -- booster_heat_pump: true,--,"{true, false}",Add option to enable a booster heat pump for supplemental heating of pit storage in district heating +-- -- -- enable,--,"{true, false}",Add option to enable supplemental heating of pit storage (PTES) in district heating +-- -- -- booster_technologies,--,List of booster technologies suitable for supplemental heating of PTES. Must be subset of ['heat_pump'; + 'resistive_heaters'], -- -- max_top_temperature,C,float,The maximum top temperature of the pit storage according to DEA technology catalogue (2018) -- -- min_bottom_temperature,C,float,The minimum bottom temperature of the pit storage according to DEA technology catalogue (2018) -- ates,,, @@ -47,7 +48,7 @@ district_heating,--,, -- -- heat_exchanger_pinch_point_temperature_difference,K,float,Heat pump pinch point temperature difference in heat exchangers assumed for approximation. -- -- isentropic_compressor_efficiency,--,float,Isentropic efficiency of heat pump compressor assumed for approximation. Must be between 0 and 1. -- -- heat_loss,--,float,Heat pump heat loss assumed for approximation. Must be between 0 and 1. --- -- min_delta_t_lift,--,float,"Minimum feasible temperature lift for heat pumps, used to approximate technical limits in heat pump operation. This value accounts for practical constraints in heat pump design." +-- -- min_delta_t_lift,--,float,Minimum feasible temperature lift for heat pumps assumed for approximation. -- limited_heat_sources,--,Dictionary with names of limited heat sources (not air) for which data by Fraunhofer ISI (`Manz et al. 2024 ) is used, -- -- geothermal,-,Name of the heat source. Must be the same as in ``heat_pump_sources``, -- -- -- constant_temperature_celsius,°C,heat source temperature, diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 8ea11b09d4..c1f49c7d33 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -35,13 +35,17 @@ Release Notes **Changes** +* Fix: Heat pump investment costs now calculated on the heat bus directly, with the nominal efficiency factor removed + +* Added resistive heaters as a temperature boosting technology for PTES. Additionally, the heat pump booster now uses ambient air as its heat source for boosting. + * Introduce the ability to use the bidding zones as administrative zones for the clustering (https://github.com/PyPSA/pypsa-eur/pull/1578). This also introduces the ability to create a custom `busmap` from custom `busshapes`. To use bidding zones as clustering mode, a `bz` mode has been introduced for `administrative` clustering. This feature is compatible with the general NUTS clustering approach. Custom `busshapes` must be provided as `data/busshapes/base_s_{clusters}_{base_network}.geojson`. * Improved balance map plotting: Carriers in the balance map legends which can serve as both supply and consumption (e.g. H2 for industry) are now placed in the legend category where its total absolute value is larger in the total system balance. * Added aquifer thermal energy storage (ATES) to district heating. Some parameters (CAPEX, standing losses) might require tuning by the user. Eligibility computation is relatively basic. Turned off by default. -* Added supplemental heating of thermal energy storages (currently implemented for PTES). This can be enabled by setting: ``sector: district_heating: ptes: supplemental_heating: true`` . To enable a boosting heat pump as the supplemental heating technology, use: ``sector: district_heating: ptes: supplemental_heating: booster_heat_pump: true`` +* Added supplemental heating of thermal energy storages (currently implemented for PTES). This can be enabled by setting: ``sector: district_heating: ptes: supplemental_heating: true`` . * Non-sequestered HVC (plastic waste) is now allocated based on the population instead of production. It can be either burned without energetic utilization or in CHPs to support the district heating system. diff --git a/rules/build_sector.smk b/rules/build_sector.smk index dcc896149c..187dcf018a 100755 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -489,6 +489,9 @@ rule build_ptes_operations: ptes_e_max_pu_profiles=resources( "ptes_e_max_pu_profiles_base_s_{clusters}_{planning_horizons}.nc" ), + ptes_temperature_boost_ratio_profiles=resources( + "ptes_temperature_boost_ratio_profiles_base_s_{clusters}_{planning_horizons}.nc" + ), resources: mem_mb=2000, log: @@ -1388,6 +1391,15 @@ rule prepare_sector_network: )(w) else [] ), + ptes_temperature_boost_ratio_profiles=lambda w: ( + resources( + "ptes_temperature_boost_ratio_profiles_base_s_{clusters}_{planning_horizons}.nc" + ) + if config_provider( + "sector", "district_heating", "ptes", "supplemental_heating", "enable" + )(w) + else [] + ), solar_thermal_total=lambda w: ( resources("solar_thermal_total_base_s_{clusters}.nc") if config_provider("sector", "solar_thermal")(w) diff --git a/scripts/build_cop_profiles/run.py b/scripts/build_cop_profiles/run.py index 0d32b0a453..97fc0b40a3 100644 --- a/scripts/build_cop_profiles/run.py +++ b/scripts/build_cop_profiles/run.py @@ -128,18 +128,23 @@ def get_cop( for heat_system_type, heat_sources in snakemake.params.heat_pump_sources.items(): cop_this_system_type = [] for heat_source in heat_sources: - if heat_source in ["ground", "air", "ptes"]: + if heat_source == "ptes": + source_inlet_temperature_celsius = xr.open_dataarray( + snakemake.input["temp_air_total"] + ) + sink_inlet_temperature_celsius = xr.open_dataarray( + snakemake.input[f"temp_{heat_source}_total"] + ) + elif heat_source in [ + "ground", + "air", + ]: source_inlet_temperature_celsius = xr.open_dataarray( snakemake.input[ f"temp_{heat_source.replace('ground', 'soil')}_total" ] ) - elif heat_source in snakemake.params.limited_heat_sources.keys(): - source_inlet_temperature_celsius = ( - snakemake.params.limited_heat_sources[heat_source][ - "constant_temperature_celsius" - ] - ) + sink_inlet_temperature_celsius = central_heating_return_temperature else: raise ValueError( f"Unknown heat source {heat_source}. Must be one of [ground, air] or {snakemake.params.heat_sources.keys()}." diff --git a/scripts/build_ptes_operations/ptes_temperature_approximator.py b/scripts/build_ptes_operations/ptes_temperature_approximator.py index 51197eff1b..a80a34fbae 100644 --- a/scripts/build_ptes_operations/ptes_temperature_approximator.py +++ b/scripts/build_ptes_operations/ptes_temperature_approximator.py @@ -19,17 +19,17 @@ class PtesTemperatureApproximator: return_temperature : xr.DataArray The return temperature profile from the district heating network. max_ptes_top_temperature : float - Maximum operational temperature of top layer in PTES, default 90°C. + Maximum operational temperature of top layer in PTES. min_ptes_bottom_temperature : float - Minimum operational temperature of bottom layer in PTES, default 35°C. + Minimum operational temperature of bottom layer in PTES. """ def __init__( self, forward_temperature: xr.DataArray, return_temperature: xr.DataArray, - max_ptes_top_temperature: float = 90, - min_ptes_bottom_temperature: float = 35, + max_ptes_top_temperature: float, + min_ptes_bottom_temperature: float, ): """ Initialize PtesTemperatureApproximator. @@ -41,9 +41,9 @@ def __init__( return_temperature : xr.DataArray The return temperature profile from the district heating network. max_ptes_top_temperature : float, optional - Maximum operational temperature of top layer in PTES, default 90°C. + Maximum operational temperature of top layer in PTES. min_ptes_bottom_temperature : float, optional - Minimum operational temperature of bottom layer in PTES, default 35°C. + Minimum operational temperature of bottom layer in PTES. """ self.forward_temperature = forward_temperature self.return_temperature = return_temperature @@ -106,3 +106,19 @@ def e_max_pu(self) -> xr.DataArray: self.max_ptes_top_temperature - self.bottom_temperature ) return normalized_delta_t.clip(min=0) # Ensure non-negative values + + @property + def temperature_boost_ratio(self) -> xr.DataArray: + """ + Calculate the additional lift required between the store's + current top temperature and the forward temperature with the lift + already achieved inside the store. + + Returns + ------- + xr.DataArray + The resulting fraction of PTES charge that must be further heated. + """ + return (self.forward_temperature - self.top_temperature) / ( + self.top_temperature - self.return_temperature + ) diff --git a/scripts/build_ptes_operations/run.py b/scripts/build_ptes_operations/run.py index 169e7612ef..b0e5993736 100644 --- a/scripts/build_ptes_operations/run.py +++ b/scripts/build_ptes_operations/run.py @@ -27,6 +27,7 @@ supplemental_heating: enable: max_top_temperature: + min_bottom_temperature: Inputs ------ @@ -43,6 +44,8 @@ Binary indicator for additional heating (1 = direct PTES use, 0 = supplemental heating required). - `resources//ptes_e_max_pu_profiles.nc` Normalized PTES capacity profiles. +- `resources//ptes_temperature_boost_ratio_profiles.nc` + Ratio of PTES charge that requires additional heating due to temperature differences. Source ------ @@ -116,3 +119,11 @@ ptes_temperature_approximator.e_max_pu.to_netcdf( snakemake.output.ptes_e_max_pu_profiles ) + + # Get PTES temperature boost ratio + logger.info( + f"Saving PTES reheat ratio profiles to {snakemake.output.ptes_temperature_boost_ratio_profiles}" + ) + ptes_temperature_approximator.temperature_boost_ratio.to_netcdf( + snakemake.output.ptes_temperature_boost_ratio_profiles + ) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index ad42cb2278..c3e4775808 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1576,7 +1576,7 @@ def insert_electricity_distribution_grid( n.links.loc[v2gs, "bus1"] += " low voltage" hps = n.links.index[n.links.carrier.str.contains("heat pump")] - n.links.loc[hps, "bus0"] += " low voltage" + n.links.loc[hps, "bus1"] += " low voltage" rh = n.links.index[n.links.carrier.str.contains("resistive heater")] n.links.loc[rh, "bus0"] += " low voltage" @@ -2753,7 +2753,8 @@ def add_heat( direct_heat_source_utilisation_profile_file: str, hourly_heat_demand_total_file: str, ptes_e_max_pu_file: str, - ptes_direct_utilisation_profile: str, + ptes_direct_utilisation_profile_file: str, + ptes_temperature_boost_ratio_profile_file: str, ates_e_nom_max: str, ates_capex_as_fraction_of_geothermal_heat_source: float, ates_recovery_factor: float, @@ -2787,8 +2788,10 @@ def add_heat( Path to NetCDF file containing direct heat source utilisation profiles hourly_heat_demand_total_file : str Path to CSV file containing hourly heat demand data - ptes_supplemental_heating_required_file: str - Path to CSV file indicating when supplemental heating for thermal energy storage (TES) is needed + ptes_direct_utilisation_profile_file : str + Path to CSV file containing when supplemental heating for thermal energy storage (TES) is needed + ptes_temperature_boost_ratio_profile_file : str + Path to CSV file containing Ratio of PTES charge that requires additional heating district_heat_share_file : str Path to CSV file containing district heating share information solar_thermal_total_file : str @@ -3054,34 +3057,72 @@ def add_heat( if options["district_heating"]["ptes"]["supplemental_heating"][ "enable" ]: - ptes_supplemental_heating_required = ( - xr.open_dataarray(ptes_direct_utilisation_profile) + n.add("Carrier", f"{heat_system} water pits boosting") + + n.add( + "Bus", + nodes + f" {heat_system} water pits boosting", + location=nodes, + carrier=f"{heat_system} water pits boosting", + unit="MWh_th", + ) + + ptes_direct_utilisiation_profile = ( + xr.open_dataarray(ptes_direct_utilisation_profile_file) .sel(name=nodes) .to_pandas() .reindex(index=n.snapshots) ) + + n.add( + "Link", + nodes, + suffix=f" {heat_system} water pits discharger", + bus0=nodes + f" {heat_system} water pits", + bus1=nodes + f" {heat_system} heat", + bus2=nodes + f" {heat_system} water pits boosting", + carrier=f"{heat_system} water pits discharger", + efficiency=costs.at[ + "central water pit discharger", + "efficiency", + ] + * ptes_direct_utilisiation_profile, + efficiency2=costs.at[ + "central water pit discharger", + "efficiency", + ] + * (ptes_direct_utilisiation_profile - 1) + * (-1), + p_nom_extendable=True, + lifetime=costs.at["central water pit storage", "lifetime"], + ) + n.links.loc[ + nodes + f" {heat_system} water pits charger", + "energy to power ratio", + ] = energy_to_power_ratio_water_pit + else: - ptes_supplemental_heating_required = 1 + ptes_direct_utilisiation_profile = 1 - n.add( - "Link", - nodes, - suffix=f" {heat_system} water pits discharger", - bus0=nodes + f" {heat_system} water pits", - bus1=nodes + f" {heat_system} heat", - carrier=f"{heat_system} water pits discharger", - efficiency=costs.at[ - "central water pit discharger", - "efficiency", - ] - * ptes_supplemental_heating_required, - p_nom_extendable=True, - lifetime=costs.at["central water pit storage", "lifetime"], - ) - n.links.loc[ - nodes + f" {heat_system} water pits charger", - "energy to power ratio", - ] = energy_to_power_ratio_water_pit + n.add( + "Link", + nodes, + suffix=f" {heat_system} water pits discharger", + bus0=nodes + f" {heat_system} water pits", + bus1=nodes + f" {heat_system} heat", + carrier=f"{heat_system} water pits discharger", + efficiency=costs.at[ + "central water pit discharger", + "efficiency", + ] + * ptes_direct_utilisiation_profile, + p_nom_extendable=True, + lifetime=costs.at["central water pit storage", "lifetime"], + ) + n.links.loc[ + nodes + f" {heat_system} water pits charger", + "energy to power ratio", + ] = energy_to_power_ratio_water_pit if options["district_heating"]["ptes"]["dynamic_capacity"]: # Load pre-calculated e_max_pu profiles @@ -3226,14 +3267,17 @@ def add_heat( "Link", nodes, suffix=f" {heat_system} {heat_source} heat pump", - bus0=nodes, - bus1=nodes + f" {heat_carrier}", - bus2=nodes + f" {heat_system} heat", + bus0=nodes + f" {heat_system} heat", + bus1=nodes, + bus2=nodes + f" {heat_carrier}", carrier=f"{heat_system} {heat_source} heat pump", - efficiency=(-(cop_heat_pump - 1)).clip(upper=0), - efficiency2=cop_heat_pump, - capital_cost=costs.at[costs_name_heat_pump, "efficiency"] - * costs.at[costs_name_heat_pump, "capital_cost"] + efficiency=(1 / cop_heat_pump).where(cop_heat_pump > 0, 0.0), + efficiency2=((cop_heat_pump - 1) / cop_heat_pump).where( + cop_heat_pump > 0, 0.0 + ), + p_min_pu=-1, + p_max_pu=0, + capital_cost=costs.at[costs_name_heat_pump, "capital_cost"] * overdim_factor, p_nom_extendable=True, lifetime=costs.at[costs_name_heat_pump, "lifetime"], @@ -3265,12 +3309,13 @@ def add_heat( not options["district_heating"]["ptes"]["supplemental_heating"][ "enable" ] - and options["district_heating"]["ptes"]["supplemental_heating"][ - "booster_heat_pump" + and "heat_pump" + in options["district_heating"]["ptes"]["supplemental_heating"][ + "booster_technologies" ] ): raise ValueError( - "'booster_heat_pump' is true, but 'enable' is false in 'supplemental_heating'." + "Supplemental heating: 'booster_technologies' contains 'heat_pump', but 'enable' is false." ) if ( @@ -3278,23 +3323,43 @@ def add_heat( and options["district_heating"]["ptes"]["supplemental_heating"][ "enable" ] - and options["district_heating"]["ptes"]["supplemental_heating"][ - "booster_heat_pump" + and "heat_pump" + in options["district_heating"]["ptes"]["supplemental_heating"][ + "booster_technologies" ] ): + ptes_temperature_boost_ratio = ( + xr.open_dataarray(ptes_temperature_boost_ratio_profile_file) + .sel(name=nodes) + .to_pandas() + .reindex(index=n.snapshots) + ) + n.add( "Link", nodes, suffix=f" {heat_system} {heat_source} heat pump", - bus0=nodes, - bus1=nodes + f" {heat_system} water pits", - bus2=nodes + f" {heat_system} heat", + bus0=nodes + f" {heat_system} heat", + bus1=nodes, + bus2=nodes + f" {heat_system} water pits boosting", carrier=f"{heat_system} {heat_source} heat pump", - efficiency=(-(cop_heat_pump - 1)).clip(upper=0), - efficiency2=cop_heat_pump, - capital_cost=costs.at[costs_name_heat_pump, "efficiency"] - * costs.at[costs_name_heat_pump, "capital_cost"] - * overdim_factor, + efficiency=( + ptes_temperature_boost_ratio + / ((1 + ptes_temperature_boost_ratio) * cop_heat_pump) + ).where( + (ptes_temperature_boost_ratio > 0) & (cop_heat_pump > 0), 0.0 + ), + efficiency2=(1 / (1 + ptes_temperature_boost_ratio)).where( + ptes_temperature_boost_ratio > 0, 0.0 + ), + p_min_pu=(ptes_direct_utilisiation_profile - 1), + p_max_pu=0, + capital_cost=costs.at[costs_name_heat_pump, "capital_cost"] + * overdim_factor + * ( + ptes_temperature_boost_ratio + / (1 + ptes_temperature_boost_ratio) + ).max(), p_nom_extendable=True, lifetime=costs.at[costs_name_heat_pump, "lifetime"], ) @@ -3304,12 +3369,13 @@ def add_heat( "Link", nodes, suffix=f" {heat_system} {heat_source} heat pump", - bus0=nodes, - bus1=nodes + f" {heat_system} heat", + bus0=nodes + f" {heat_system} heat", + bus1=nodes, carrier=f"{heat_system} {heat_source} heat pump", - efficiency=cop_heat_pump, - capital_cost=costs.at[costs_name_heat_pump, "efficiency"] - * costs.at[costs_name_heat_pump, "capital_cost"] + efficiency=(1 / cop_heat_pump).where(cop_heat_pump > 0, 0.0), + p_min_pu=-1, + p_max_pu=0, + capital_cost=costs.at[costs_name_heat_pump, "capital_cost"] * overdim_factor, p_nom_extendable=True, lifetime=costs.at[costs_name_heat_pump, "lifetime"], @@ -3332,6 +3398,56 @@ def add_heat( lifetime=costs.at[key, "lifetime"], ) + if ( + not options["district_heating"]["ptes"]["supplemental_heating"][ + "enable" + ] + and "resistive_heaters" + in options["district_heating"]["ptes"]["supplemental_heating"][ + "booster_technologies" + ] + ): + raise ValueError( + "Supplemental heating: 'booster_technologies' contains 'resistive_heaters', but 'enable' is false." + ) + if ( + "resistive_heaters" + in options["district_heating"]["ptes"]["supplemental_heating"][ + "booster_technologies" + ] + and heat_system == HeatSystem.URBAN_CENTRAL + ): + ptes_temperature_boost_ratio = ( + xr.open_dataarray(ptes_temperature_boost_ratio_profile_file) + .sel(name=nodes) + .to_pandas() + .reindex(index=n.snapshots) + ) + + n.add( + "Link", + nodes, + suffix=f" {heat_system} ptes resistive heater", + bus0=nodes, + bus1=nodes + f" {heat_system} water pits boosting", + bus2=nodes + f" {heat_system} heat", + carrier=f"{heat_system} ptes resistive heater", + efficiency=-( + costs.at[key, "efficiency"] / ptes_temperature_boost_ratio + ).where(ptes_temperature_boost_ratio > 0, 0.0), + efficiency2=(costs.at[key, "efficiency"]) + * (1 + (1 / ptes_temperature_boost_ratio)).where( + ptes_temperature_boost_ratio > 0, 0.0 + ), + capital_cost=( + costs.at[key, "efficiency"] + * costs.at[key, "capital_cost"] + * overdim_factor + ), + p_nom_extendable=True, + lifetime=costs.at[key, "lifetime"], + ) + if options["boilers"]: key = f"{heat_system.central_or_decentral} gas boiler" @@ -6135,9 +6251,9 @@ def add_import_options( snakemake = mock_snakemake( "prepare_sector_network", opts="", - clusters="10", + clusters="8", sector_opts="", - planning_horizons="2050", + planning_horizons="2030", ) configure_logging(snakemake) # pylint: disable=E0606 @@ -6259,6 +6375,8 @@ def add_import_options( direct_heat_source_utilisation_profile_file=snakemake.input.direct_heat_source_utilisation_profiles, hourly_heat_demand_total_file=snakemake.input.hourly_heat_demand_total, ptes_e_max_pu_file=snakemake.input.ptes_e_max_pu_profiles, + ptes_direct_utilisation_profile_file=snakemake.input.ptes_direct_utilisation_profiles, + ptes_temperature_boost_ratio_profile_file=snakemake.input.ptes_temperature_boost_ratio_profiles, ates_e_nom_max=snakemake.input.ates_potentials, ates_capex_as_fraction_of_geothermal_heat_source=snakemake.params.sector[ "district_heating" @@ -6270,7 +6388,6 @@ def add_import_options( "recovery_factor" ], enable_ates=snakemake.params.sector["district_heating"]["ates"]["enable"], - ptes_direct_utilisation_profile=snakemake.input.ptes_direct_utilisation_profiles, district_heat_share_file=snakemake.input.district_heat_share, solar_thermal_total_file=snakemake.input.solar_thermal_total, retro_cost_file=snakemake.input.retro_cost,