diff --git a/Snakefile b/Snakefile index 4acba0c8..826521c1 100644 --- a/Snakefile +++ b/Snakefile @@ -8,6 +8,8 @@ from pathlib import Path import yaml from snakemake.remote.HTTP import RemoteProvider as HTTPRemoteProvider from snakemake.utils import min_version + +# TODO: check if this works with mock_snakemake from scripts._helpers import path_provider min_version("7.7") diff --git a/doc/configtables/run.csv b/doc/configtables/run.csv index 75f29928..e2a81e0b 100644 --- a/doc/configtables/run.csv +++ b/doc/configtables/run.csv @@ -2,7 +2,7 @@ name,--,str/list,"Specify a name for your run. Results will be stored under this name. If ``scenario: enable`` is set to ``true``, the name must contain a subset of scenario names defined in ``scenario: file``." scenarios,,, -- enable,bool,"{true, false}","Switch to select whether workflow should generate scenarios based on ``file``." --- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run:scenarios`` has to be set to ``true`` and ``run:name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combindation of settings, alter and use the ``config/create_scenarios.py`` script in ``scripts``." +-- file,str,,"Path to the scenario yaml file. The scenario file contains config overrides for each scenario. In order to be taken account, ``run: scenarios`` has to be set to ``true`` and ``run: name`` has to be a subset of top level keys given in the scenario file. In order to automatically create a `scenario.yaml` file based on a combination of settings, alter and use the ``config/create_scenarios.py`` script in the ``config`` directory." disable_progrssbar,bool,"{true, false}","Switch to select whether progressbar should be disabled." shared_resources,bool/str/list,,"Switch to select whether resources should be shared across runs. If a string or list is passed, it is assumed to be wildcard(s) which indicates up to which set of wildcards the resource folder should be shared. If set to 'base', only resources before creating the elec.nc file are shared." shared_cutouts,bool,"{true, false}","Switch to select whether cutouts should be shared across runs." diff --git a/rules/build_electricity.smk b/rules/build_electricity.smk index 4c83e0b0..8876c68e 100644 --- a/rules/build_electricity.smk +++ b/rules/build_electricity.smk @@ -20,8 +20,9 @@ if config["enable"].get("prepare_links_p_nom", False): rule build_electricity_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), load=config_provider("load"), @@ -64,8 +65,9 @@ rule build_powerplants: rule base_network: params: countries=config_provider("countries"), - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, lines=config_provider("lines"), links=config_provider("links"), @@ -177,8 +179,8 @@ if config["enable"].get("build_natura_raster", False): rule build_natura_raster: input: natura=ancient("data/bundle/natura/Natura2000_end2015.shp"), - cutouts=expand( - "cutouts/" + CDIR + "{cutouts}.nc", **config_provider("atlite") + cutouts=lambda w: expand( + "cutouts/" + CDIR + "{cutouts}.nc", **config_provider("atlite")(w) ), output: resources("natura.tiff"), @@ -195,11 +197,11 @@ if config["enable"].get("build_natura_raster", False): rule build_ship_raster: input: ship_density="data/shipdensity_global.zip", - cutouts=expand( + cutouts=lambda w: expand( "cutouts/" + CDIR + "{cutout}.nc", cutout=[ - config_provider("renewable", k, "cutout") - for k in config_provider("electricity", "renewable_carriers") + config_provider("renewable", k, "cutout")(w) + for k in config_provider("electricity", "renewable_carriers")(w) ], ), output: @@ -269,8 +271,9 @@ else: rule build_renewable_profiles: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, renewable=config_provider("renewable"), input: @@ -352,9 +355,9 @@ rule build_hydro_profile: input: country_shapes=resources("country_shapes.geojson"), eia_hydro_generation="data/eia_hydro_annual_generation.csv", - cutout=f"cutouts/" + cutout=lambda w: f"cutouts/" + CDIR - + config_provider("renewable", "hydro", "cutout") + + config_provider("renewable", "hydro", "cutout")(w) + ".nc", output: resources("profile_hydro.nc"), @@ -397,6 +400,23 @@ if config["lines"]["dynamic_line_rating"]["activate"]: "../scripts/build_line_rating.py" +def input_profile_tech(w): + return { + f"profile_{tech}": resources(f"profile_{tech}.nc") + for tech in config_provider("electricity", "renewable_carriers")(w) + } + + +def input_conventional(w): + return { + f"conventional_{carrier}_{attr}": fn + for carrier, d in config_provider("conventional", default={None: {}})(w).items() + if carrier in config_provider("electricity", "conventional_carriers")(w) + for attr, fn in d.items() + if str(fn).startswith("data/") + } + + rule add_electricity: params: length_factor=config_provider("lines", "length_factor"), @@ -407,21 +427,12 @@ rule add_electricity: conventional=config_provider("conventional"), costs=config_provider("costs"), input: - **{ - f"profile_{tech}": resources(f"profile_{tech}.nc") - for tech in config_provider("electricity", "renewable_carriers") - }, - **{ - f"conventional_{carrier}_{attr}": fn - for carrier, d in config.get("conventional", {None: {}}).items() - if carrier in config_provider("electricity", "conventional_carriers") - for attr, fn in d.items() - if str(fn).startswith("data/") - }, + unpack(input_profile_tech), + unpack(input_conventional), base_network=resources("networks/base.nc"), - line_rating=( + line_rating=lambda w: ( resources("networks/line_rating.nc") - if config_provider("lines", "dynamic_line_rating", "activate") + if config_provider("lines", "dynamic_line_rating", "activate")(w) else resources("networks/base.nc") ), tech_costs=COSTS, @@ -430,9 +441,9 @@ rule add_electricity: hydro_capacities=ancient("data/bundle/hydro_capacities.csv"), geth_hydro_capacities="data/geth2015_hydro_capacities.csv", unit_commitment="data/unit_commitment.csv", - fuel_price=( + fuel_price=lambda w: ( resources("monthly_fuel_price.csv") - if config_provider("conventional", "dynamic_fuel_price") + if config_provider("conventional", "dynamic_fuel_price")(w) else [] ), load=resources("electricity_demand.csv"), @@ -509,9 +520,9 @@ rule cluster_network: regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), regions_offshore=resources("regions_offshore_elec_s{simpl}.geojson"), busmap=ancient(resources("busmap_elec_s{simpl}.csv")), - custom_busmap=( + custom_busmap=lambda w: ( "data/custom_busmap_elec_s{simpl}_{clusters}.csv" - if config_provider("enable", "custom_busmap", default=False) + if config_provider("enable", "custom_busmap", default=False)(w) else [] ), tech_costs=COSTS, diff --git a/rules/build_sector.smk b/rules/build_sector.smk index 62b69337..cfd7191e 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -7,7 +7,10 @@ rule build_population_layouts: input: nuts3_shapes=resources("nuts3_shapes.geojson"), urban_percent="data/urban_percent.csv", - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: pop_layout_total=resources("pop_layout_total.nc"), pop_layout_urban=resources("pop_layout_urban.nc"), @@ -31,7 +34,10 @@ rule build_clustered_population_layouts: pop_layout_urban=resources("pop_layout_urban.nc"), pop_layout_rural=resources("pop_layout_rural.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), log: @@ -52,7 +58,10 @@ rule build_simplified_population_layouts: pop_layout_urban=resources("pop_layout_urban.nc"), pop_layout_rural=resources("pop_layout_rural.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: clustered_pop_layout=resources("pop_layout_elec_s{simpl}.csv"), resources: @@ -126,13 +135,17 @@ rule cluster_gas_network: rule build_daily_heat_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: heat_demand=resources("daily_heat_demand_{scope}_elec_s{simpl}_{clusters}.nc"), resources: @@ -150,8 +163,9 @@ rule build_daily_heat_demand: rule build_hourly_heat_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, input: heat_profile="data/heat_load_profile_BDEW.csv", @@ -173,13 +187,17 @@ rule build_hourly_heat_demand: rule build_temperature_profiles: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: temp_soil=resources("temp_soil_{scope}_elec_s{simpl}_{clusters}.nc"), temp_air=resources("temp_air_{scope}_elec_s{simpl}_{clusters}.nc"), @@ -227,15 +245,18 @@ rule build_cop_profiles: rule build_solar_thermal_profiles: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, - # TODO use config_provider solar_thermal=config_provider("solar_thermal"), input: pop_layout=resources("pop_layout_{scope}.nc"), regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), - cutout="cutouts/" + CDIR + config_provider("atlite", "default_cutout") + ".nc", + cutout=lambda w: "cutouts/" + + CDIR + + config_provider("atlite", "default_cutout")(w) + + ".nc", output: solar_thermal=resources("solar_thermal_{scope}_elec_s{simpl}_{clusters}.nc"), resources: @@ -314,76 +335,54 @@ rule build_biomass_potentials: "../scripts/build_biomass_potentials.py" -if config["sector"]["biomass_transport"] or config["sector"]["biomass_spatial"]: - - rule build_biomass_transport_costs: - input: - transport_cost_data=HTTP.remote( - "publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", - keep_local=True, - ), - output: - biomass_transport_costs=resources("biomass_transport_costs.csv"), - threads: 1 - resources: - mem_mb=1000, - log: - logs("build_biomass_transport_costs.log"), - benchmark: - benchmarks("build_biomass_transport_costs") - conda: - "../envs/environment.yaml" - script: - "../scripts/build_biomass_transport_costs.py" - - build_biomass_transport_costs_output = rules.build_biomass_transport_costs.output +rule build_biomass_transport_costs: + input: + transport_cost_data=HTTP.remote( + "publications.jrc.ec.europa.eu/repository/bitstream/JRC98626/biomass potentials in europe_web rev.pdf", + keep_local=True, + ), + output: + biomass_transport_costs=resources("biomass_transport_costs.csv"), + threads: 1 + resources: + mem_mb=1000, + log: + logs("build_biomass_transport_costs.log"), + benchmark: + benchmarks("build_biomass_transport_costs") + conda: + "../envs/environment.yaml" + script: + "../scripts/build_biomass_transport_costs.py" -if not (config["sector"]["biomass_transport"] or config["sector"]["biomass_spatial"]): - # this is effecively an `else` statement which is however not liked by snakefmt - build_biomass_transport_costs_output = {} - - -if config["sector"]["regional_co2_sequestration_potential"]["enable"]: - - rule build_sequestration_potentials: - params: - sequestration_potential=config_provider( - "sector", "regional_co2_sequestration_potential" - ), - input: - sequestration_potential=HTTP.remote( - "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", - keep_local=True, - ), - regions_onshore=resources( - "regions_onshore_elec_s{simpl}_{clusters}.geojson" - ), - regions_offshore=resources( - "regions_offshore_elec_s{simpl}_{clusters}.geojson" - ), - output: - sequestration_potential=resources( - "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" - ), - threads: 1 - resources: - mem_mb=4000, - log: - logs("build_sequestration_potentials_s{simpl}_{clusters}.log"), - benchmark: - benchmarks("build_sequestration_potentials_s{simpl}_{clusters}") - conda: - "../envs/environment.yaml" - script: - "../scripts/build_sequestration_potentials.py" - - build_sequestration_potentials_output = rules.build_sequestration_potentials.output - - -if not config["sector"]["regional_co2_sequestration_potential"]["enable"]: - # this is effecively an `else` statement which is however not liked by snakefmt - build_sequestration_potentials_output = {} +rule build_sequestration_potentials: + params: + sequestration_potential=config_provider( + "sector", "regional_co2_sequestration_potential" + ), + input: + sequestration_potential=HTTP.remote( + "https://raw.githubusercontent.com/ericzhou571/Co2Storage/main/resources/complete_map_2020_unit_Mt.geojson", + keep_local=True, + ), + regions_onshore=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), + regions_offshore=resources("regions_offshore_elec_s{simpl}_{clusters}.geojson"), + output: + sequestration_potential=resources( + "co2_sequestration_potential_elec_s{simpl}_{clusters}.csv" + ), + threads: 1 + resources: + mem_mb=4000, + log: + logs("build_sequestration_potentials_s{simpl}_{clusters}.log"), + benchmark: + benchmarks("build_sequestration_potentials_s{simpl}_{clusters}") + conda: + "../envs/environment.yaml" + script: + "../scripts/build_sequestration_potentials.py" rule build_salt_cavern_potentials: @@ -643,43 +642,34 @@ rule build_industrial_energy_demand_per_node_today: "../scripts/build_industrial_energy_demand_per_node_today.py" -if config["sector"]["retrofitting"]["retro_endogen"]: - - rule build_retro_cost: - params: - retrofitting=config_provider("sector", "retrofitting"), - countries=config_provider("countries"), - input: - building_stock="data/retro/data_building_stock.csv", - data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", - air_temperature=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), - u_values_PL="data/retro/u_values_poland.csv", - tax_w="data/retro/electricity_taxes_eu.csv", - construction_index="data/retro/comparative_level_investment.csv", - floor_area_missing="data/retro/floor_area_missing.csv", - clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), - cost_germany="data/retro/retro_cost_germany.csv", - window_assumptions="data/retro/window_assumptions.csv", - output: - retro_cost=resources("retro_cost_elec_s{simpl}_{clusters}.csv"), - floor_area=resources("floor_area_elec_s{simpl}_{clusters}.csv"), - resources: - mem_mb=1000, - log: - logs("build_retro_cost_s{simpl}_{clusters}.log"), - benchmark: - benchmarks("build_retro_cost/s{simpl}_{clusters}") - conda: - "../envs/environment.yaml" - script: - "../scripts/build_retro_cost.py" - - build_retro_cost_output = rules.build_retro_cost.output - - -if not config["sector"]["retrofitting"]["retro_endogen"]: - # this is effecively an `else` statement which is however not liked by snakefmt - build_retro_cost_output = {} +rule build_retro_cost: + params: + retrofitting=config_provider("sector", "retrofitting"), + countries=config_provider("countries"), + input: + building_stock="data/retro/data_building_stock.csv", + data_tabula="data/bundle-sector/retro/tabula-calculator-calcsetbuilding.csv", + air_temperature=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), + u_values_PL="data/retro/u_values_poland.csv", + tax_w="data/retro/electricity_taxes_eu.csv", + construction_index="data/retro/comparative_level_investment.csv", + floor_area_missing="data/retro/floor_area_missing.csv", + clustered_pop_layout=resources("pop_layout_elec_s{simpl}_{clusters}.csv"), + cost_germany="data/retro/retro_cost_germany.csv", + window_assumptions="data/retro/window_assumptions.csv", + output: + retro_cost=resources("retro_cost_elec_s{simpl}_{clusters}.csv"), + floor_area=resources("floor_area_elec_s{simpl}_{clusters}.csv"), + resources: + mem_mb=1000, + log: + logs("build_retro_cost_s{simpl}_{clusters}.log"), + benchmark: + benchmarks("build_retro_cost/s{simpl}_{clusters}") + conda: + "../envs/environment.yaml" + script: + "../scripts/build_retro_cost.py" rule build_population_weighted_energy_totals: @@ -720,8 +710,9 @@ rule build_shipping_demand: rule build_transport_demand: params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, sector=config_provider("sector"), input: @@ -825,11 +816,31 @@ rule prepare_sector_network: eurostat_report_year=config_provider("energy", "eurostat_report_year"), RDIR=RDIR, input: - **build_retro_cost_output, - **build_biomass_transport_costs_output, **rules.cluster_gas_network.output, **rules.build_gas_input_locations.output, - **build_sequestration_potentials_output, + retro_cost=lambda w: ( + resources("retro_cost_elec_s{simpl}_{clusters}.csv") + if config_provider("sector", "retrofitting", "retro_endogen")(w) + else [] + ), + floor_area=lambda w: ( + resources("floor_area_elec_s{simpl}_{clusters}.csv") + if config_provider("sector", "retrofitting", "retro_endogen")(w) + else [] + ), + biomass_transport_costs=lambda w: ( + resources("biomass_transport_costs.csv") + if config_provider("sector", "biomass_transport")(w) + or config_provider("sector", "biomass_spatial")(w) + else [] + ), + sequestration_potential=lambda w: ( + resources("co2_sequestration_potential_elec_s{simpl}_{clusters}.csv") + if config_provider( + "sector", "regional_co2_sequestration_potential", "enable" + )(w) + else [] + ), network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"), energy_totals_name=resources("energy_totals.csv"), eurostat=input_eurostat, @@ -843,12 +854,12 @@ rule prepare_sector_network: dsm_profile=resources("dsm_profile_s{simpl}_{clusters}.csv"), co2_totals_name=resources("co2_totals.csv"), co2="data/bundle-sector/eea/UNFCCC_v23.csv", - biomass_potentials=( + biomass_potentials=lambda w: ( resources( "biomass_potentials_s{simpl}_{clusters}_" + "{}.csv".format(config_provider("biomass", "year")) ) - if config_provider("foresight") == "overnight" + if config_provider("foresight")(w) == "overnight" else resources( "biomass_potentials_s{simpl}_{clusters}_{planning_horizons}.csv" ) @@ -886,19 +897,19 @@ rule prepare_sector_network: cop_air_total=resources("cop_air_total_elec_s{simpl}_{clusters}.nc"), cop_air_rural=resources("cop_air_rural_elec_s{simpl}_{clusters}.nc"), cop_air_urban=resources("cop_air_urban_elec_s{simpl}_{clusters}.nc"), - solar_thermal_total=( + solar_thermal_total=lambda w: ( resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc") - if config_provider("sector", "solar_thermal") + if config_provider("sector", "solar_thermal")(w) else [] ), - solar_thermal_urban=( + solar_thermal_urban=lambda w: ( resources("solar_thermal_urban_elec_s{simpl}_{clusters}.nc") - if config_provider("sector", "solar_thermal") + if config_provider("sector", "solar_thermal")(w) else [] ), - solar_thermal_rural=( + solar_thermal_rural=lambda w: ( resources("solar_thermal_rural_elec_s{simpl}_{clusters}.nc") - if config_provider("sector", "solar_thermal") + if config_provider("sector", "solar_thermal")(w) else [] ), output: diff --git a/rules/common.smk b/rules/common.smk index bf5e0894..c352a3a9 100644 --- a/rules/common.smk +++ b/rules/common.smk @@ -78,8 +78,8 @@ def config_provider(*keys, default=None): def solver_threads(w): - solver_options = config_provider("solving", "solver_options") - option_set = config_provider("solving", "solver", "options") + solver_options = config_provider("solving", "solver_options")(w) + option_set = config_provider("solving", "solver", "options")(w) threads = solver_options[option_set].get("threads", 4) return threads @@ -107,7 +107,7 @@ def memory(w): def input_custom_extra_functionality(w): path = config_provider( "solving", "options", "custom_extra_functionality", default=False - ) + )(w) if path: return os.path.join(os.path.dirname(workflow.snakefile), path) return [] @@ -131,7 +131,7 @@ def has_internet_access(url="www.zenodo.org") -> bool: def input_eurostat(w): # 2016 includes BA, 2017 does not - report_year = config_provider("energy", "eurostat_report_year") + report_year = config_provider("energy", "eurostat_report_year")(w) return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition" diff --git a/rules/postprocess.smk b/rules/postprocess.smk index 542c8d29..79634bf6 100644 --- a/rules/postprocess.smk +++ b/rules/postprocess.smk @@ -111,6 +111,14 @@ if config["foresight"] != "perfect": if config["foresight"] == "perfect": + def output_map_year(w): + return { + f"map_{year}": RESULTS + + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_" + + f"{year}.pdf" + for year in config_provider("scenario", "planning_horizons")(w) + } + rule plot_power_network_perfect: params: plotting=config_provider("plotting"), @@ -119,12 +127,7 @@ if config["foresight"] == "perfect": + "postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc", regions=resources("regions_onshore_elec_s{simpl}_{clusters}.geojson"), output: - **{ - f"map_{year}": RESULTS - + "maps/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}-costs-all_" - + f"{year}.pdf" - for year in config_provider("scenario", "planning_horizons") - }, + unpack(output_map_year), threads: 2 resources: mem_mb=10000, @@ -158,8 +161,9 @@ rule make_summary: params: foresight=config_provider("foresight"), costs=config_provider("costs"), - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, scenario=config_provider("scenario"), RDIR=RDIR, diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index bea6b6cc..a52f17c0 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -49,6 +49,14 @@ rule add_existing_baseyear: "../scripts/add_existing_baseyear.py" +def input_profile_tech_brownfield(w): + return { + f"profile_{tech}": resources(f"profile_{tech}.nc") + for tech in config_provider("electricity", "renewable_carriers")(w) + if tech != "hydro" + } + + rule add_brownfield: params: H2_retrofit=config_provider("sector", "H2_retrofit"), @@ -56,16 +64,13 @@ rule add_brownfield: "sector", "H2_retrofit_capacity_per_CH4" ), threshold_capacity=config_provider("existing_capacities", " threshold_capacity"), - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, carriers=config_provider("electricity", "renewable_carriers"), input: - **{ - f"profile_{tech}": resources(f"profile_{tech}.nc") - for tech in config_provider("electricity", "renewable_carriers") - if tech != "hydro" - }, + unpack(input_profile_tech_brownfield), simplify_busmap=resources("busmap_elec_s{simpl}.csv"), cluster_busmap=resources("busmap_elec_s{simpl}_{clusters}.csv"), network=RESULTS diff --git a/rules/solve_perfect.smk b/rules/solve_perfect.smk index d1a5f745..0d94ad9c 100644 --- a/rules/solve_perfect.smk +++ b/rules/solve_perfect.smk @@ -48,14 +48,17 @@ rule add_existing_baseyear: "../scripts/add_existing_baseyear.py" +def input_network_year(w): + return { + f"network_{year}": RESULTS + + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{year}.nc" + for year in config_provider("scenario", "planning_horizons")(w)[1:] + } + + rule prepare_perfect_foresight: input: - **{ - f"network_{year}": RESULTS - + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_" - + f"{year}.nc" - for year in config_provider("scenario", "planning_horizons")[1:] - }, + unpack(input_network_year), brownfield_network=lambda w: ( RESULTS + "prenetworks-brownfield/" @@ -122,11 +125,21 @@ rule solve_sector_network_perfect: "../scripts/solve_network.py" +def input_networks_make_summary_perfect(w): + return { + f"networks_{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}": RESULTS + + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" + for simpl in config_provider("scenario", "simpl")(w) + for clusters in config_provider("scenario", "clusters")(w) + for opts in config_provider("scenario", "opts")(w) + for sector_opts in config_provider("scenario", "sector_opts")(w) + for ll in config_provider("scenario", "ll")(w) + } + + rule make_summary_perfect: input: - **{ - f"networks_{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}": RESULTS - + f"postnetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_brownfield_all_years.nc" + unpack(input_networks_make_summary_perfect), costs="resources/costs_2020.csv", output: nodal_costs=RESULTS + "csvs/nodal_costs.csv", diff --git a/rules/validate.smk b/rules/validate.smk index 3c42c5f0..66949335 100644 --- a/rules/validate.smk +++ b/rules/validate.smk @@ -17,8 +17,9 @@ rule build_electricity_production: The data is used for validation of the optimization results. """ params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), output: @@ -37,8 +38,9 @@ rule build_cross_border_flows: The data is used for validation of the optimization results. """ params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), input: @@ -59,8 +61,9 @@ rule build_electricity_prices: The data is used for validation of the optimization results. """ params: - snapshots={ - k: config_provider("snapshots", k) for k in ["start", "end", "inclusive"] + snapshots=lambda w: { + k: config_provider("snapshots", k)(w) + for k in ["start", "end", "inclusive"] }, countries=config_provider("countries"), output: