Merge branch 'master' into retro

This commit is contained in:
Tom Brown 2020-11-30 17:07:43 +01:00
commit 974155bd46
15 changed files with 279 additions and 575 deletions

View File

@ -25,17 +25,12 @@ rule all:
rule solve_all_networks: rule solve_all_networks:
input: input:
expand(config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", expand(config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
**config['scenario'])
rule test_script:
input:
expand("resources/heat_demand_urban_elec_s_{clusters}.nc",
**config['scenario']) **config['scenario'])
rule prepare_sector_networks: rule prepare_sector_networks:
input: input:
expand(config['results_dir'] + config['run'] + "/prenetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", expand(config['results_dir'] + config['run'] + "/prenetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
**config['scenario']) **config['scenario'])
@ -313,10 +308,10 @@ rule prepare_sector_network:
heat_profile="data/heat_load_profile_BDEW.csv", heat_profile="data/heat_load_profile_BDEW.csv",
costs=config['costs_dir'] + "costs_{planning_horizons}.csv", costs=config['costs_dir'] + "costs_{planning_horizons}.csv",
h2_cavern = "data/hydrogen_salt_cavern_potentials.csv", h2_cavern = "data/hydrogen_salt_cavern_potentials.csv",
co2_budget="data/co2_budget.csv",
profile_offwind_ac=pypsaeur("resources/profile_offwind-ac.nc"), profile_offwind_ac=pypsaeur("resources/profile_offwind-ac.nc"),
profile_offwind_dc=pypsaeur("resources/profile_offwind-dc.nc"), profile_offwind_dc=pypsaeur("resources/profile_offwind-dc.nc"),
clustermaps=pypsaeur('resources/clustermaps_{network}_s{simpl}_{clusters}.h5'), busmap_s=pypsaeur("resources/busmap_{network}_s{simpl}.csv"),
busmap=pypsaeur("resources/busmap_{network}_s{simpl}_{clusters}.csv"),
clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv", clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv",
simplified_pop_layout="resources/pop_layout_{network}_s{simpl}.csv", simplified_pop_layout="resources/pop_layout_{network}_s{simpl}.csv",
industrial_demand="resources/industrial_energy_demand_{network}_s{simpl}_{clusters}.csv", industrial_demand="resources/industrial_energy_demand_{network}_s{simpl}_{clusters}.csv",
@ -340,20 +335,20 @@ rule prepare_sector_network:
solar_thermal_rural="resources/solar_thermal_rural_{network}_s{simpl}_{clusters}.nc", solar_thermal_rural="resources/solar_thermal_rural_{network}_s{simpl}_{clusters}.nc",
retro_cost_energy = "resources/retro_cost_{network}_s{simpl}_{clusters}.csv", retro_cost_energy = "resources/retro_cost_{network}_s{simpl}_{clusters}.csv",
floor_area = "resources/floor_area_{network}_s{simpl}_{clusters}.csv" floor_area = "resources/floor_area_{network}_s{simpl}_{clusters}.csv"
output: config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc' output: config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc'
threads: 1 threads: 1
resources: mem_mb=2000 resources: mem_mb=2000
benchmark: config['results_dir'] + config['run'] + "/benchmarks/prepare_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" benchmark: config['results_dir'] + config['run'] + "/benchmarks/prepare_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}"
script: "scripts/prepare_sector_network.py" script: "scripts/prepare_sector_network.py"
rule plot_network: rule plot_network:
input: input:
network=config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" network=config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc"
output: output:
map=config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{co2_budget_name}_{planning_horizons}.pdf", map=config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf",
today=config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}-today.pdf" today=config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}-today.pdf"
threads: 2 threads: 2
resources: mem_mb=10000 resources: mem_mb=10000
script: "scripts/plot_network.py" script: "scripts/plot_network.py"
@ -370,10 +365,10 @@ rule copy_config:
rule make_summary: rule make_summary:
input: input:
networks=expand(config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", networks=expand(config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
**config['scenario']), **config['scenario']),
costs=config['costs_dir'] + "costs_{}.csv".format(config['scenario']['planning_horizons'][0]), costs=config['costs_dir'] + "costs_{}.csv".format(config['scenario']['planning_horizons'][0]),
plots=expand(config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{co2_budget_name}_{planning_horizons}.pdf", plots=expand(config['results_dir'] + config['run'] + "/maps/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}-costs-all_{planning_horizons}.pdf",
**config['scenario']) **config['scenario'])
#heat_demand_name='data/heating/daily_heat_demand.h5' #heat_demand_name='data/heating/daily_heat_demand.h5'
output: output:
@ -416,16 +411,16 @@ if config["foresight"] == "overnight":
rule solve_network: rule solve_network:
input: input:
network=config['results_dir'] + config['run'] + "/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", network=config['results_dir'] + config['run'] + "/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
costs=config['costs_dir'] + "costs_{planning_horizons}.csv", costs=config['costs_dir'] + "costs_{planning_horizons}.csv",
config=config['summary_dir'] + '/' + config['run'] + '/configs/config.yaml' config=config['summary_dir'] + '/' + config['run'] + '/configs/config.yaml'
output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc"
shadow: "shallow" shadow: "shallow"
log: log:
solver=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log", solver=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_solver.log",
python=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python.log", python=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_python.log",
memory=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_memory.log" memory=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_memory.log"
benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}"
threads: 4 threads: 4
resources: mem_mb=config['solving']['mem'] resources: mem_mb=config['solving']['mem']
# group: "solve" # with group, threads is ignored https://bitbucket.org/snakemake/snakemake/issues/971/group-job-description-does-not-contain # group: "solve" # with group, threads is ignored https://bitbucket.org/snakemake/snakemake/issues/971/group-job-description-does-not-contain
@ -436,14 +431,15 @@ if config["foresight"] == "myopic":
rule add_existing_baseyear: rule add_existing_baseyear:
input: input:
network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc',
powerplants=pypsaeur('resources/powerplants.csv'), powerplants=pypsaeur('resources/powerplants.csv'),
clustermaps=pypsaeur('resources/clustermaps_{network}_s{simpl}_{clusters}.h5'), busmap_s=pypsaeur("resources/busmap_{network}_s{simpl}.csv"),
busmap=pypsaeur("resources/busmap_{network}_s{simpl}_{clusters}.csv"),
clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv", clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv",
costs=config['costs_dir'] + "costs_{}.csv".format(config['scenario']['planning_horizons'][0]), costs=config['costs_dir'] + "costs_{}.csv".format(config['scenario']['planning_horizons'][0]),
cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc", cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc",
cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc" cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc"
output: config['results_dir'] + config['run'] + '/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc' output: config['results_dir'] + config['run'] + '/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc'
wildcard_constraints: wildcard_constraints:
planning_horizons=config['scenario']['planning_horizons'][0] #only applies to baseyear planning_horizons=config['scenario']['planning_horizons'][0] #only applies to baseyear
threads: 1 threads: 1
@ -452,36 +448,36 @@ if config["foresight"] == "myopic":
def process_input(wildcards): def process_input(wildcards):
i = config["scenario"]["planning_horizons"].index(int(wildcards.planning_horizons)) i = config["scenario"]["planning_horizons"].index(int(wildcards.planning_horizons))
return config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_" + str(config["scenario"]["planning_horizons"][i-1]) + ".nc" return config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_" + str(config["scenario"]["planning_horizons"][i-1]) + ".nc"
rule add_brownfield: rule add_brownfield:
input: input:
network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc',
network_p=process_input, #solved network at previous time step network_p=process_input, #solved network at previous time step
costs=config['costs_dir'] + "costs_{planning_horizons}.csv", costs=config['costs_dir'] + "costs_{planning_horizons}.csv",
cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc", cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc",
cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc" cop_air_total="resources/cop_air_total_{network}_s{simpl}_{clusters}.nc"
output: config['results_dir'] + config['run'] + "/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" output: config['results_dir'] + config['run'] + "/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc"
threads: 4 threads: 4
resources: mem_mb=2000 resources: mem_mb=10000
script: "scripts/add_brownfield.py" script: "scripts/add_brownfield.py"
ruleorder: add_existing_baseyear > add_brownfield ruleorder: add_existing_baseyear > add_brownfield
rule solve_network_myopic: rule solve_network_myopic:
input: input:
network=config['results_dir'] + config['run'] + "/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc", network=config['results_dir'] + config['run'] + "/prenetworks-brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc",
costs=config['costs_dir'] + "costs_{planning_horizons}.csv", costs=config['costs_dir'] + "costs_{planning_horizons}.csv",
config=config['summary_dir'] + '/' + config['run'] + '/configs/config.yaml' config=config['summary_dir'] + '/' + config['run'] + '/configs/config.yaml'
output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc" output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}.nc"
shadow: "shallow" shadow: "shallow"
log: log:
solver=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log", solver=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_solver.log",
python=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_python.log", python=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_python.log",
memory=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_memory.log" memory=config['results_dir'] + config['run'] + "/logs/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}_memory.log"
benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}" benchmark: config['results_dir'] + config['run'] + "/benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{planning_horizons}"
threads: 4 threads: 4
resources: mem_mb=config['solving']['mem'] resources: mem_mb=config['solving']['mem']
script: "scripts/solve_network.py" script: "scripts/solve_network.py"

View File

@ -7,7 +7,7 @@ summary_dir: results
costs_dir: '../technology-data/outputs/' costs_dir: '../technology-data/outputs/'
run: 'your-run-name' # use this to keep track of runs with different settings run: 'your-run-name' # use this to keep track of runs with different settings
foresight: 'overnight' # options are overnight, myopic, perfect (perfect is not yet implemented) foresight: 'overnight' # options are overnight, myopic, perfect (perfect is not yet implemented)
# if you use myopic or perfect foresight, set the investment years in "planning_horizons" below
scenario: scenario:
sectors: [E] # ignore this legacy setting sectors: [E] # ignore this legacy setting
@ -25,7 +25,18 @@ scenario:
# solarx or onwindx changes the available installable potential by factor x # solarx or onwindx changes the available installable potential by factor x
# dist{n} includes distribution grids with investment cost of n times cost in data/costs.csv # dist{n} includes distribution grids with investment cost of n times cost in data/costs.csv
planning_horizons : [2030] # investment years for myopic and perfect; or costs year for overnight planning_horizons : [2030] # investment years for myopic and perfect; or costs year for overnight
co2_budget_name: ['go'] #gives shape of CO2 budgets over planning horizon # for example, set to [2020, 2030, 2040, 2050] for myopic foresight
# CO2 budget as a fraction of 1990 emissions
# this is over-ridden if CO2Lx is set in sector_opts
co2_budget:
2020: 0.7011648746
2025: 0.5241935484
2030: 0.2970430108
2035: 0.1500896057
2040: 0.0712365591
2045: 0.0322580645
2050: 0
# snapshots are originally set in PyPSA-Eur/config.yaml but used again by PyPSA-Eur-Sec # snapshots are originally set in PyPSA-Eur/config.yaml but used again by PyPSA-Eur-Sec
snapshots: snapshots:
@ -62,8 +73,8 @@ existing_capacities:
sector: sector:
'central' : True 'central' : True
'central_fraction' : 0.6 'central_fraction' : 0.6
'dsm_restriction_value' : 0.75 #Set to 0 for no restriction on BEV DSM 'bev_dsm_restriction_value' : 0.75 #Set to 0 for no restriction on BEV DSM
'dsm_restriction_time' : 7 #Time at which SOC of BEV has to be dsm_restriction_value 'bev_dsm_restriction_time' : 7 #Time at which SOC of BEV has to be dsm_restriction_value
'transport_heating_deadband_upper' : 20. 'transport_heating_deadband_upper' : 20.
'transport_heating_deadband_lower' : 15. 'transport_heating_deadband_lower' : 15.
'ICE_lower_degree_factor' : 0.375 #in per cent increase in fuel consumption per degree above deadband 'ICE_lower_degree_factor' : 0.375 #in per cent increase in fuel consumption per degree above deadband
@ -71,10 +82,22 @@ sector:
'EV_lower_degree_factor' : 0.98 'EV_lower_degree_factor' : 0.98
'EV_upper_degree_factor' : 0.63 'EV_upper_degree_factor' : 0.63
'district_heating_loss' : 0.15 'district_heating_loss' : 0.15
'bev' : True #turns on EV battery 'bev_dsm' : True #turns on EV battery
'bev_availability' : 0.5 #How many cars do smart charging 'bev_availability' : 0.5 #How many cars do smart charging
'v2g' : True #allows feed-in to grid from EV battery 'v2g' : True #allows feed-in to grid from EV battery
'transport_fuel_cell_share' : 0. #0 means all EVs, 1 means all FCs #what is not EV or FCEV is fossil-fuelled
'land_transport_fuel_cell_share': # 1 means all FCEVs
2020: 0
2030: 0.05
2040: 0.1
2050: 0.15
'land_transport_electric_share': # 1 means all EVs
2020: 0
2030: 0.25
2040: 0.6
2050: 0.85
'transport_fuel_cell_efficiency': 0.5
'transport_internal_combustion_efficiency': 0.3
'shipping_average_efficiency' : 0.4 #For conversion of fuel oil to propulsion in 2011 'shipping_average_efficiency' : 0.4 #For conversion of fuel oil to propulsion in 2011
'time_dep_hp_cop' : True 'time_dep_hp_cop' : True
'space_heating_fraction' : 1.0 #fraction of space heating active 'space_heating_fraction' : 1.0 #fraction of space heating active
@ -93,6 +116,7 @@ sector:
'boilers' : True 'boilers' : True
'oil_boilers': False 'oil_boilers': False
'chp' : True 'chp' : True
'micro_chp' : False
'solar_thermal' : True 'solar_thermal' : True
'solar_cf_correction': 0.788457 # = >>> 1/1.2683 'solar_cf_correction': 0.788457 # = >>> 1/1.2683
'marginal_cost_storage' : 0. #1e-4 'marginal_cost_storage' : 0. #1e-4
@ -112,7 +136,6 @@ sector:
'gas_distribution_grid_cost_factor' : 1.0 #multiplies cost in data/costs.csv 'gas_distribution_grid_cost_factor' : 1.0 #multiplies cost in data/costs.csv
costs: costs:
year: 2030
lifetime: 25 #default lifetime lifetime: 25 #default lifetime
# From a Lion Hirth paper, also reflects average of Noothout et al 2016 # From a Lion Hirth paper, also reflects average of Noothout et al 2016
discountrate: 0.07 discountrate: 0.07
@ -171,7 +194,7 @@ solving:
industry: industry:
'St_primary_fraction' : 0.3 # fraction of steel produced via primary route (DRI + EAF) versus secondary route (EAF); today fraction is 0.6 'St_primary_fraction' : 0.3 # fraction of steel produced via primary route (DRI + EAF) versus secondary route (EAF); today fraction is 0.6
'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2,LHV/ton_Steel from Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279 'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2,LHV/ton_Steel from 51kgH2/tSt in Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279
'elec_DRI' : 0.322 #electricity consumption in Direct Reduced Iron (DRI) shaft, MWh/tSt HYBRIT brochure https://ssabwebsitecdn.azureedge.net/-/media/hybrit/files/hybrit_brochure.pdf 'elec_DRI' : 0.322 #electricity consumption in Direct Reduced Iron (DRI) shaft, MWh/tSt HYBRIT brochure https://ssabwebsitecdn.azureedge.net/-/media/hybrit/files/hybrit_brochure.pdf
'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4 'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4
'MWh_CH4_per_tNH3_SMR' : 10.8 # 2012's demand from https://ec.europa.eu/docsroom/documents/4165/attachments/1/translations/en/renditions/pdf 'MWh_CH4_per_tNH3_SMR' : 10.8 # 2012's demand from https://ec.europa.eu/docsroom/documents/4165/attachments/1/translations/en/renditions/pdf
@ -180,6 +203,7 @@ industry:
'MWh_elec_per_tNH3_electrolysis' : 1.17 # from https://doi.org/10.1016/j.joule.2018.04.017 Table 13 (air separation and HB) 'MWh_elec_per_tNH3_electrolysis' : 1.17 # from https://doi.org/10.1016/j.joule.2018.04.017 Table 13 (air separation and HB)
'NH3_process_emissions' : 24.5 # in MtCO2/a from SMR for H2 production for NH3 from UNFCCC for 2015 for EU28 'NH3_process_emissions' : 24.5 # in MtCO2/a from SMR for H2 production for NH3 from UNFCCC for 2015 for EU28
'petrochemical_process_emissions' : 25.5 # in MtCO2/a for petrochemical and other from UNFCCC for 2015 for EU28 'petrochemical_process_emissions' : 25.5 # in MtCO2/a for petrochemical and other from UNFCCC for 2015 for EU28
'HVC_primary_fraction' : 1.0 #fraction of current non-ammonia basic chemicals produced via primary route
plotting: plotting:
map: map:
@ -286,6 +310,7 @@ plotting:
"Fischer-Tropsch" : "#44DD33" "Fischer-Tropsch" : "#44DD33"
"kerosene for aviation": "#44BB11" "kerosene for aviation": "#44BB11"
"naphtha for industry" : "#44FF55" "naphtha for industry" : "#44FF55"
"land transport fossil" : "#44DD33"
"water tanks" : "#BBBBBB" "water tanks" : "#BBBBBB"
"hot water storage" : "#BBBBBB" "hot water storage" : "#BBBBBB"
"hot water charging" : "#BBBBBB" "hot water charging" : "#BBBBBB"
@ -297,7 +322,6 @@ plotting:
"Ambient" : "k" "Ambient" : "k"
"Electric load" : "b" "Electric load" : "b"
"Heat load" : "r" "Heat load" : "r"
"Transport load" : "grey"
"heat" : "darkred" "heat" : "darkred"
"rural heat" : "#880000" "rural heat" : "#880000"
"central heat" : "#b22222" "central heat" : "#b22222"
@ -312,15 +336,16 @@ plotting:
"building retrofitting" : "purple" "building retrofitting" : "purple"
"BEV charger" : "grey" "BEV charger" : "grey"
"V2G" : "grey" "V2G" : "grey"
"transport" : "grey" "land transport EV" : "grey"
"electricity" : "k" "electricity" : "k"
"gas for industry" : "#333333" "gas for industry" : "#333333"
"solid biomass for industry" : "#555555" "solid biomass for industry" : "#555555"
"industry electricity" : "#222222"
"industry new electricity" : "#222222" "industry new electricity" : "#222222"
"process emissions to stored" : "#444444" "process emissions to stored" : "#444444"
"process emissions to atmosphere" : "#888888" "process emissions to atmosphere" : "#888888"
"process emissions" : "#222222" "process emissions" : "#222222"
"transport fuel cell" : "#AAAAAA" "land transport fuel cell" : "#AAAAAA"
"biogas" : "#800000" "biogas" : "#800000"
"solid biomass" : "#DAA520" "solid biomass" : "#DAA520"
"today" : "#D2691E" "today" : "#D2691E"

View File

@ -1,346 +0,0 @@
version: 0.3.0
logging_level: INFO
results_dir: 'results/'
summary_dir: results
costs_dir: '../technology-data/outputs/'
run: 'your-run-name' # use this to keep track of runs with different settings
foresight: 'myopic' #options are overnight, myopic, perfect (perfect is not yet implemented)
scenario:
sectors: [E] # ignore this legacy setting
simpl: [''] # only relevant for PyPSA-Eur
lv: [1.0,1.5] # allowed transmission line volume expansion, can be any float >= 1.0 (today) or "opt"
clusters: [45,50] # number of nodes in Europe, any integer between 37 (1 node per country-zone) and several hundred
opts: [''] # only relevant for PyPSA-Eur
sector_opts: [Co2L0-3H-H-B-solar3-dist1] # this is where the main scenario settings are
# to really understand the options here, look in scripts/prepare_sector_network.py
# Co2Lx specifies the CO2 target in x% of the 1990 values; default will give default (5%);
# Co2L0p25 will give 25% CO2 emissions; Co2Lm0p05 will give 5% negative emissions
# xH is the temporal resolution; 3H is 3-hourly, i.e. one snapshot every 3 hours
# single letters are sectors: T for land transport, H for building heating,
# B for biomass supply, I for industry, shipping and aviation
# solarx or onwindx changes the available installable potential by factor x
# dist{n} includes distribution grids with investment cost of n times cost in data/costs.csv
planning_horizons : [2020, 2030, 2040, 2050] #investment years for myopic and perfect; or costs year for overnight
co2_budget_name: ['go'] #gives shape of CO2 budgets over planning horizon
# snapshots are originally set in PyPSA-Eur/config.yaml but used again by PyPSA-Eur-Sec
snapshots:
# arguments to pd.date_range
start: "2013-01-01"
end: "2014-01-01"
closed: 'left' # end is not inclusive
atlite:
cutout_dir: '../pypsa-eur/cutouts'
cutout_name: "europe-2013-era5"
# this information is NOT used but needed as an argument for
# pypsa-eur/scripts/add_electricity.py/load_costs in make_summary.py
electricity:
max_hours:
battery: 6
H2: 168
biomass:
year: 2030
scenario: "Med"
classes:
solid biomass: ['Primary agricultural residues', 'Forestry energy residue', 'Secondary forestry residues', 'Secondary Forestry residues sawdust', 'Forestry residues from landscape care biomass', 'Municipal waste']
not included: ['Bioethanol sugar beet biomass', 'Rapeseeds for biodiesel', 'sunflower and soya for Biodiesel', 'Starchy crops biomass', 'Grassy crops biomass', 'Willow biomass', 'Poplar biomass potential', 'Roundwood fuelwood', 'Roundwood Chips & Pellets']
biogas: ['Manure biomass potential', 'Sludge biomass']
# only relevant for foresight = myopic or perfect
existing_capacities:
grouping_years: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019]
threshold_capacity: 10
conventional_carriers: ['lignite', 'coal', 'oil', 'uranium']
sector:
'central' : True
'central_fraction' : 0.6
'dsm_restriction_value' : 0.75 #Set to 0 for no restriction on BEV DSM
'dsm_restriction_time' : 7 #Time at which SOC of BEV has to be dsm_restriction_value
'transport_heating_deadband_upper' : 20.
'transport_heating_deadband_lower' : 15.
'ICE_lower_degree_factor' : 0.375 #in per cent increase in fuel consumption per degree above deadband
'ICE_upper_degree_factor' : 1.6
'EV_lower_degree_factor' : 0.98
'EV_upper_degree_factor' : 0.63
'district_heating_loss' : 0.15
'bev' : True #turns on EV battery
'bev_availability' : 0.5 #How many cars do smart charging
'v2g' : True #allows feed-in to grid from EV battery
'transport_fuel_cell_share' : 0. #0 means all EVs, 1 means all FCs
'shipping_average_efficiency' : 0.4 #For conversion of fuel oil to propulsion in 2011
'time_dep_hp_cop' : True
'space_heating_fraction' : 1.0 #fraction of space heating active
'retrofitting' :
'retro_exogen': True # space heat demand savings exogenously
'dE': [0.0, 0.1, 0.2, 0.5] # reduction of space heat demand per year (applied before losses in DH)
'retro_endogen': False # co-optimise space heat savings
'cost_factor' : 1.0
'interest_rate': 0.04 # for investment in building components
'annualise_cost': True # annualise the investment costs
'tax_weighting': False # weight costs depending on taxes in countries
'construction_index': True # weight costs depending on labour/material costs per ct
'l_strength': ["0.076", "0.197"] # additional insulation thickness[m], determines number of retro steps(=generators per bus) and maximum possible savings
'tes' : True
'tes_tau' : 3.
'boilers' : True
'oil_boilers': False
'chp' : True
'solar_thermal' : True
'solar_cf_correction': 0.788457 # = >>> 1/1.2683
'marginal_cost_storage' : 0. #1e-4
'methanation' : True
'helmeth' : True
'dac' : True
'co2_vent' : True
'SMR' : True
'ccs_fraction' : 0.9
'hydrogen_underground_storage' : True
'use_fischer_tropsch_waste_heat' : True
'use_fuel_cell_waste_heat' : True
'electricity_distribution_grid' : False
'electricity_distribution_grid_cost_factor' : 1.0 #multiplies cost in data/costs.csv
'electricity_grid_connection' : True # only applies to onshore wind and utility PV
'gas_distribution_grid' : True
'gas_distribution_grid_cost_factor' : 1.0 #multiplies cost in data/costs.csv
costs:
year: 2030
lifetime: 25 #default lifetime
# From a Lion Hirth paper, also reflects average of Noothout et al 2016
discountrate: 0.07
# [EUR/USD] ECB: https://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html # noqa: E501
USD2013_to_EUR2013: 0.7532
# Marginal and capital costs can be overwritten
# capital_cost:
# Wind: Bla
marginal_cost: #
solar: 0.01
onwind: 0.015
offwind: 0.015
hydro: 0.
H2: 0.
battery: 0.
emission_prices: # only used with the option Ep (emission prices)
co2: 0.
lines:
length_factor: 1.25 #to estimate offwind connection costs
solving:
#tmpdir: "path/to/tmp"
options:
formulation: kirchhoff
clip_p_max_pu: 1.e-2
load_shedding: false
noisy_costs: true
min_iterations: 1
max_iterations: 1
# nhours: 1
solver:
name: gurobi
threads: 4
method: 2 # barrier
crossover: 0
BarConvTol: 1.e-5
Seed: 123
AggFill: 0
PreDual: 0
GURO_PAR_BARDENSETHRESH: 200
#FeasibilityTol: 1.e-6
#name: cplex
#threads: 4
#lpmethod: 4 # barrier
#solutiontype: 2 # non basic solution, ie no crossover
#barrier_convergetol: 1.e-5
#feasopt_tolerance: 1.e-6
mem: 30000 #memory in MB; 20 GB enough for 50+B+I+H2; 100 GB for 181+B+I+H2
industry:
'St_primary_fraction' : 0.3 # fraction of steel produced via primary route (DRI + EAF) versus secondary route (EAF); today fraction is 0.6
'H2_DRI' : 1.7 #H2 consumption in Direct Reduced Iron (DRI), MWh_H2,LHV/ton_Steel from Vogl et al (2018) doi:10.1016/j.jclepro.2018.08.279
'elec_DRI' : 0.322 #electricity consumption in Direct Reduced Iron (DRI) shaft, MWh/tSt HYBRIT brochure https://ssabwebsitecdn.azureedge.net/-/media/hybrit/files/hybrit_brochure.pdf
'Al_primary_fraction' : 0.2 # fraction of aluminium produced via the primary route versus scrap; today fraction is 0.4
'MWh_CH4_per_tNH3_SMR' : 10.8 # 2012's demand from https://ec.europa.eu/docsroom/documents/4165/attachments/1/translations/en/renditions/pdf
'MWh_elec_per_tNH3_SMR' : 0.7 # same source, assuming 94-6% split methane-elec of total energy demand 11.5 MWh/tNH3
'MWh_H2_per_tNH3_electrolysis' : 6.5 # from https://doi.org/10.1016/j.joule.2018.04.017, around 0.197 tH2/tHN3 (>3/17 since some H2 lost and used for energy)
'MWh_elec_per_tNH3_electrolysis' : 1.17 # from https://doi.org/10.1016/j.joule.2018.04.017 Table 13 (air separation and HB)
'NH3_process_emissions' : 24.5 # in MtCO2/a from SMR for H2 production for NH3 from UNFCCC for 2015 for EU28
'petrochemical_process_emissions' : 25.5 # in MtCO2/a for petrochemical and other from UNFCCC for 2015 for EU28
plotting:
map:
figsize: [7, 7]
boundaries: [-10.2, 29, 35, 72]
p_nom:
bus_size_factor: 5.e+4
linewidth_factor: 3.e+3 # 1.e+3 #3.e+3
costs_max: 1200
costs_threshold: 1
energy_max: 20000.
energy_min: -15000.
energy_threshold: 50.
vre_techs: ["onwind", "offwind-ac", "offwind-dc", "solar", "ror"]
renewable_storage_techs: ["PHS","hydro"]
conv_techs: ["OCGT", "CCGT", "Nuclear", "Coal"]
storage_techs: ["hydro+PHS", "battery", "H2"]
# store_techs: ["Li ion", "water tanks"]
load_carriers: ["AC load"] #, "heat load", "Li ion load"]
AC_carriers: ["AC line", "AC transformer"]
link_carriers: ["DC line", "Converter AC-DC"]
heat_links: ["heat pump", "resistive heater", "CHP heat", "CHP electric",
"gas boiler", "central heat pump", "central resistive heater", "central CHP heat",
"central CHP electric", "central gas boiler"]
heat_generators: ["gas boiler", "central gas boiler", "solar thermal collector", "central solar thermal collector"]
tech_colors:
"onwind" : "b"
"onshore wind" : "b"
'offwind' : "c"
'offshore wind' : "c"
'offwind-ac' : "c"
'offshore wind (AC)' : "c"
'offwind-dc' : "#009999"
'offshore wind (DC)' : "#009999"
'wave' : "#004444"
"hydro" : "#3B5323"
"hydro reservoir" : "#3B5323"
"ror" : "#78AB46"
"run of river" : "#78AB46"
'hydroelectricity' : '#006400'
'solar' : "y"
'solar PV' : "y"
'solar thermal' : 'coral'
'solar rooftop' : '#e6b800'
"OCGT" : "wheat"
"OCGT marginal" : "sandybrown"
"OCGT-heat" : "orange"
"gas boiler" : "orange"
"gas boilers" : "orange"
"gas boiler marginal" : "orange"
"gas-to-power/heat" : "orange"
"gas" : "brown"
"natural gas" : "brown"
"SMR" : "#4F4F2F"
"oil" : "#B5A642"
"oil boiler" : "#B5A677"
"lines" : "k"
"transmission lines" : "k"
"H2" : "m"
"hydrogen storage" : "m"
"battery" : "slategray"
"battery storage" : "slategray"
"home battery" : "#614700"
"home battery storage" : "#614700"
"Nuclear" : "r"
"Nuclear marginal" : "r"
"nuclear" : "r"
"uranium" : "r"
"Coal" : "k"
"coal" : "k"
"Coal marginal" : "k"
"Lignite" : "grey"
"lignite" : "grey"
"Lignite marginal" : "grey"
"CCGT" : "orange"
"CCGT marginal" : "orange"
"heat pumps" : "#76EE00"
"heat pump" : "#76EE00"
"air heat pump" : "#76EE00"
"ground heat pump" : "#40AA00"
"power-to-heat" : "#40AA00"
"resistive heater" : "pink"
"Sabatier" : "#FF1493"
"methanation" : "#FF1493"
"power-to-gas" : "#FF1493"
"power-to-liquid" : "#FFAAE9"
"helmeth" : "#7D0552"
"helmeth" : "#7D0552"
"DAC" : "#E74C3C"
"co2 stored" : "#123456"
"CO2 sequestration" : "#123456"
"CCS" : "k"
"co2" : "#123456"
"co2 vent" : "#654321"
"solid biomass for industry co2 from atmosphere" : "#654321"
"solid biomass for industry co2 to stored": "#654321"
"gas for industry co2 to atmosphere": "#654321"
"gas for industry co2 to stored": "#654321"
"Fischer-Tropsch" : "#44DD33"
"kerosene for aviation": "#44BB11"
"naphtha for industry" : "#44FF55"
"water tanks" : "#BBBBBB"
"hot water storage" : "#BBBBBB"
"hot water charging" : "#BBBBBB"
"hot water discharging" : "#999999"
"CHP" : "r"
"CHP heat" : "r"
"CHP electric" : "r"
"PHS" : "g"
"Ambient" : "k"
"Electric load" : "b"
"Heat load" : "r"
"Transport load" : "grey"
"heat" : "darkred"
"rural heat" : "#880000"
"central heat" : "#b22222"
"decentral heat" : "#800000"
"low-temperature heat for industry" : "#991111"
"process heat" : "#FF3333"
"heat demand" : "darkred"
"electric demand" : "k"
"Li ion" : "grey"
"district heating" : "#CC4E5C"
"retrofitting" : "purple"
"building retrofitting" : "purple"
"BEV charger" : "grey"
"V2G" : "grey"
"transport" : "grey"
"electricity" : "k"
"gas for industry" : "#333333"
"solid biomass for industry" : "#555555"
"industry new electricity" : "#222222"
"process emissions to stored" : "#444444"
"process emissions to atmosphere" : "#888888"
"process emissions" : "#222222"
"transport fuel cell" : "#AAAAAA"
"biogas" : "#800000"
"solid biomass" : "#DAA520"
"today" : "#D2691E"
"shipping" : "#6495ED"
"electricity distribution grid" : "#333333"
nice_names:
# OCGT: "Gas"
# OCGT marginal: "Gas (marginal)"
offwind: "offshore wind"
onwind: "onshore wind"
battery: "Battery storage"
lines: "Transmission lines"
AC line: "AC lines"
AC-AC: "DC lines"
ror: "Run of river"
nice_names_n:
offwind: "offshore\nwind"
onwind: "onshore\nwind"
# OCGT: "Gas"
H2: "Hydrogen\nstorage"
# OCGT marginal: "Gas (marginal)"
lines: "transmission\nlines"
ror: "run of river"

View File

@ -1,8 +0,0 @@
,go,wait
2020,0.7011648746,0.7011648746
2025,0.5241935484,0.6285842294
2030,0.2970430108,0.3503584229
2035,0.1500896057,0.0725806452
2040,0.0712365591,0
2045,0.0322580645,0
2050,0,0
1 go wait
2 2020 0.7011648746 0.7011648746
3 2025 0.5241935484 0.6285842294
4 2030 0.2970430108 0.3503584229
5 2035 0.1500896057 0.0725806452
6 2040 0.0712365591 0
7 2045 0.0322580645 0
8 2050 0 0

View File

@ -78,27 +78,26 @@ For example:
Electricity network: nodal. Electricity network: nodal.
Electricity demand: nodal, distributed in each country based on Electricity demand: nodal, distributed in each country based on
population and GDP. population, GDP and location of industrial facilities.
Building heating demand: nodal, distributed in each country based on Building heating demand: nodal, distributed in each country based on
population. population.
Industry demand: nodal, distributed in each country based on Industry demand: nodal, distributed in each country based on
population (will be corrected to real locations of industry, see locations of industry from `HotMaps database <https://gitlab.com/hotmaps/industrial_sites/industrial_sites_Industrial_Database>`_.
github issue).
Hydrogen network: nodal. Hydrogen network: nodal.
Methane network: copper-plated for Europe, since future demand is so Methane network: single node for Europe, since future demand is so
low and no bottlenecks are expected. low and no bottlenecks are expected.
Solid biomass: copper-plated until transport costs can be Solid biomass: single node for Europe, until transport costs can be
incorporated. incorporated.
CO2: copper-plated (but a transport and storage cost is added for CO2: single node for Europe, but a transport and storage cost is added for
sequestered CO2). sequestered CO2.
Liquid hydrocarbons: copper-plated since transport costs are low. Liquid hydrocarbons: single node for Europe, since transport costs are low.

View File

@ -17,12 +17,14 @@ See also other `outstanding issues <https://github.com/PyPSA/pypsa-eur-sec/issue
Configuration Configuration
================= =================
PyPSA-Eur-Sec has several configuration options which are collected in a config.yaml file located in the root directory. For myopic optimization, users should copy the provided myopic configuration ``config.myopic.yaml`` and make their own modifications and assumptions in the user-specific configuration file (``config.yaml``). PyPSA-Eur-Sec has several configuration options which are collected in a config.yaml file located in the root directory. For myopic optimization, users should copy the provided default configuration ``config.default.yaml`` and make their own modifications and assumptions in the user-specific configuration file (``config.yaml``).
The following options included in the config.yaml file are relevant for the myopic code. The following options included in the config.yaml file are relevant for the myopic code.
To activate the myopic option select ``foresight: 'myopic'`` in ``config.yaml``. To activate the myopic option select ``foresight: 'myopic'`` in ``config.yaml``.
To set the investment years which are sequentially simulated for the myopic investment planning, select for example ``planning_horizons : [2020, 2030, 2040, 2050]`` in ``config.yaml``.
**existing capacities** **existing capacities**

View File

@ -7,3 +7,5 @@ Overnight (greenfield) scenarios
The default is to calculate a rebuilding of the energy system to meet demand, a so-called overnight or greenfield approach. The default is to calculate a rebuilding of the energy system to meet demand, a so-called overnight or greenfield approach.
For this, use ``foresight : 'overnight'`` in ``config.yaml``, like the example in ``config.default.yaml``. For this, use ``foresight : 'overnight'`` in ``config.yaml``, like the example in ``config.default.yaml``.
In this case, the ``planning_horizons : [2030]`` scenario parameter can be set to use the year from which cost and other technology assumptions are set (forecasts for 2030 in this case).

View File

@ -170,10 +170,8 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas
df_agg.Fueltype = df_agg.Fueltype.map(rename_fuel) df_agg.Fueltype = df_agg.Fueltype.map(rename_fuel)
#assign clustered bus #assign clustered bus
busmap_s = pd.read_hdf(snakemake.input.clustermaps, busmap_s = pd.read_csv(snakemake.input.busmap_s, index_col=0).squeeze()
key="/busmap_s") busmap = pd.read_csv(snakemake.input.busmap, index_col=0).squeeze()
busmap = pd.read_hdf(snakemake.input.clustermaps,
key="/busmap")
clustermaps = busmap_s.map(busmap) clustermaps = busmap_s.map(busmap)
clustermaps.index = clustermaps.index.astype(int) clustermaps.index = clustermaps.index.astype(int)
@ -416,7 +414,8 @@ if __name__ == "__main__":
planning_horizons='2020'), planning_horizons='2020'),
input=dict(network='pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc', input=dict(network='pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc',
powerplants='pypsa-eur/resources/powerplants.csv', powerplants='pypsa-eur/resources/powerplants.csv',
clustermaps='pypsa-eur/resources/clustermaps_{network}_s{simpl}_{clusters}.h5', busmap_s='pypsa-eur/resources/busmap_{network}_s{simpl}.csv',
busmap='pypsa-eur/resources/busmap_{network}_s{simpl}_{clusters}.csv',
costs='pypsa-eur-sec/data/costs/costs_{planning_horizons}.csv', costs='pypsa-eur-sec/data/costs/costs_{planning_horizons}.csv',
cop_air_total="pypsa-eur-sec/resources/cop_air_total_{network}_s{simpl}_{clusters}.nc", cop_air_total="pypsa-eur-sec/resources/cop_air_total_{network}_s{simpl}_{clusters}.nc",
cop_soil_total="pypsa-eur-sec/resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc"), cop_soil_total="pypsa-eur-sec/resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc"),
@ -443,7 +442,8 @@ if __name__ == "__main__":
costs = prepare_costs(snakemake.input.costs, costs = prepare_costs(snakemake.input.costs,
snakemake.config['costs']['USD2013_to_EUR2013'], snakemake.config['costs']['USD2013_to_EUR2013'],
snakemake.config['costs']['discountrate'], snakemake.config['costs']['discountrate'],
Nyears) Nyears,
snakemake.config['costs']['lifetime'])
grouping_years=snakemake.config['existing_capacities']['grouping_years'] grouping_years=snakemake.config['existing_capacities']['grouping_years']
add_power_capacities_installed_before_baseyear(n, grouping_years, costs, baseyear) add_power_capacities_installed_before_baseyear(n, grouping_years, costs, baseyear)

View File

@ -378,7 +378,7 @@ def build_energy_totals():
clean_df.loc[missing,"total aviation passenger"] = clean_df.loc[missing,["total domestic aviation passenger","total international aviation passenger"]].sum(axis=1) clean_df.loc[missing,"total aviation passenger"] = clean_df.loc[missing,["total domestic aviation passenger","total international aviation passenger"]].sum(axis=1)
clean_df.loc[missing,"total aviation freight"] = clean_df.loc[missing,["total domestic aviation freight","total international aviation freight"]].sum(axis=1) clean_df.loc[missing,"total aviation freight"] = clean_df.loc[missing,["total domestic aviation freight","total international aviation freight"]].sum(axis=1)
if "BA" in clean_df.index:
#fix missing data for BA (services and road energy data) #fix missing data for BA (services and road energy data)
missing = (clean_df.loc["BA"] == 0.) missing = (clean_df.loc["BA"] == 0.)

View File

@ -22,6 +22,8 @@ fraction_primary_stays_primary = snakemake.config["industry"]["Al_primary_fracti
industrial_production["Aluminium - primary production"] = fraction_primary_stays_primary*industrial_production["Aluminium - primary production"] industrial_production["Aluminium - primary production"] = fraction_primary_stays_primary*industrial_production["Aluminium - primary production"]
industrial_production["Aluminium - secondary production"] = total_aluminium - industrial_production["Aluminium - primary production"] industrial_production["Aluminium - secondary production"] = total_aluminium - industrial_production["Aluminium - primary production"]
industrial_production["Basic chemicals (without ammonia)"] *= snakemake.config["industry"]['HVC_primary_fraction']
industrial_production.to_csv(snakemake.output.industrial_production_per_country_tomorrow, industrial_production.to_csv(snakemake.output.industrial_production_per_country_tomorrow,
float_format='%.2f') float_format='%.2f')

View File

@ -186,14 +186,6 @@ def calculate_costs(n,label,costs):
costs.loc[marginal_costs_grouped.index,label] = marginal_costs_grouped costs.loc[marginal_costs_grouped.index,label] = marginal_costs_grouped
#add back in costs of links if there is a line volume limit
if label[1] != "opt":
costs.loc[("links-added","capital","transmission lines"),label] = ((costs_db.at['HVDC overhead', 'fixed']*n.links.length + costs_db.at['HVDC inverter pair', 'fixed'])*n.links.p_nom_opt)[n.links.carrier == "DC"].sum()
costs.loc[("lines-added","capital","transmission lines"),label] = costs_db.at["HVAC overhead", "fixed"]*(n.lines.length*n.lines.s_nom_opt).sum()
else:
costs.loc[("links-added","capital","transmission lines"),label] = (costs_db.at['HVDC inverter pair', 'fixed']*n.links.p_nom_opt)[n.links.carrier == "DC"].sum()
#add back in all hydro #add back in all hydro
#costs.loc[("storage_units","capital","hydro"),label] = (0.01)*2e6*n.storage_units.loc[n.storage_units.group=="hydro","p_nom"].sum() #costs.loc[("storage_units","capital","hydro"),label] = (0.01)*2e6*n.storage_units.loc[n.storage_units.group=="hydro","p_nom"].sum()
#costs.loc[("storage_units","capital","PHS"),label] = (0.01)*2e6*n.storage_units.loc[n.storage_units.group=="PHS","p_nom"].sum() #costs.loc[("storage_units","capital","PHS"),label] = (0.01)*2e6*n.storage_units.loc[n.storage_units.group=="PHS","p_nom"].sum()
@ -530,7 +522,7 @@ outputs = ["nodal_costs",
def make_summaries(networks_dict): def make_summaries(networks_dict):
columns = pd.MultiIndex.from_tuples(networks_dict.keys(),names=["cluster","lv","opt", "co2_budget_name","planning_horizon"]) columns = pd.MultiIndex.from_tuples(networks_dict.keys(),names=["cluster","lv","opt","planning_horizon"])
df = {} df = {}
@ -579,21 +571,19 @@ if __name__ == "__main__":
for item in outputs: for item in outputs:
snakemake.output[item] = snakemake.config['summary_dir'] + '/{name}/csvs/{item}.csv'.format(name=snakemake.config['run'],item=item) snakemake.output[item] = snakemake.config['summary_dir'] + '/{name}/csvs/{item}.csv'.format(name=snakemake.config['run'],item=item)
networks_dict = {(cluster,lv,opt+sector_opt, co2_budget_name, planning_horizon) : networks_dict = {(cluster, lv, opt+sector_opt, planning_horizon) :
snakemake.config['results_dir'] + snakemake.config['run'] + '/postnetworks/elec_s{simpl}_{cluster}_lv{lv}_{opt}_{sector_opt}_{co2_budget_name}_{planning_horizon}.nc'\ snakemake.config['results_dir'] + snakemake.config['run'] + '/postnetworks/elec_s{simpl}_{cluster}_lv{lv}_{opt}_{sector_opt}_{planning_horizon}.nc'\
.format(simpl=simpl, .format(simpl=simpl,
cluster=cluster, cluster=cluster,
opt=opt, opt=opt,
lv=lv, lv=lv,
sector_opt=sector_opt, sector_opt=sector_opt,
co2_budget_name=co2_budget_name,
planning_horizon=planning_horizon)\ planning_horizon=planning_horizon)\
for simpl in snakemake.config['scenario']['simpl'] \ for simpl in snakemake.config['scenario']['simpl'] \
for cluster in snakemake.config['scenario']['clusters'] \ for cluster in snakemake.config['scenario']['clusters'] \
for opt in snakemake.config['scenario']['opts'] \ for opt in snakemake.config['scenario']['opts'] \
for sector_opt in snakemake.config['scenario']['sector_opts'] \ for sector_opt in snakemake.config['scenario']['sector_opts'] \
for lv in snakemake.config['scenario']['lv'] \ for lv in snakemake.config['scenario']['lv'] \
for co2_budget_name in snakemake.config['scenario']['co2_budget_name'] \
for planning_horizon in snakemake.config['scenario']['planning_horizons']} for planning_horizon in snakemake.config['scenario']['planning_horizons']}
print(networks_dict) print(networks_dict)
@ -602,7 +592,8 @@ if __name__ == "__main__":
costs_db = prepare_costs(snakemake.input.costs, costs_db = prepare_costs(snakemake.input.costs,
snakemake.config['costs']['USD2013_to_EUR2013'], snakemake.config['costs']['USD2013_to_EUR2013'],
snakemake.config['costs']['discountrate'], snakemake.config['costs']['discountrate'],
Nyears) Nyears,
snakemake.config['costs']['lifetime'])
df = make_summaries(networks_dict) df = make_summaries(networks_dict)

View File

@ -324,7 +324,7 @@ def plot_map_without(network):
fig.set_size_inches(7, 6) fig.set_size_inches(7, 6)
# PDF has minimum width, so set these to zero # PDF has minimum width, so set these to zero
line_lower_threshold = 0. line_lower_threshold = 200.
line_upper_threshold = 1e4 line_upper_threshold = 1e4
linewidth_factor = 2e3 linewidth_factor = 2e3
ac_color = "gray" ac_color = "gray"
@ -343,19 +343,19 @@ def plot_map_without(network):
line_widths = n.lines.s_nom_min line_widths = n.lines.s_nom_min
link_widths = n.links.p_nom_min link_widths = n.links.p_nom_min
line_widths[line_widths < line_upper_threshold] = 0. line_widths[line_widths < line_lower_threshold] = 0.
link_widths[link_widths < line_upper_threshold] = 0. link_widths[link_widths < line_lower_threshold] = 0.
line_widths[line_widths > line_upper_threshold] = line_upper_threshold line_widths[line_widths > line_upper_threshold] = line_upper_threshold
link_widths[link_widths > line_upper_threshold] = line_upper_threshold link_widths[link_widths > line_upper_threshold] = line_upper_threshold
n.plot(bus_sizes=10, n.plot(bus_colors="k",
bus_colors="k",
line_colors=ac_color, line_colors=ac_color,
link_colors=dc_color, link_colors=dc_color,
line_widths=line_widths / linewidth_factor, line_widths=line_widths / linewidth_factor,
link_widths=link_widths / linewidth_factor, link_widths=link_widths / linewidth_factor,
ax=ax, boundaries=(-10, 30, 34, 70)) ax=ax, boundaries=(-10, 30, 34, 70),
color_geomap={'ocean': 'lightblue', 'land': "palegoldenrod"})
handles = [] handles = []
labels = [] labels = []

View File

@ -256,7 +256,8 @@ if __name__ == "__main__":
snakemake.input["balances"] = snakemake.config['summary_dir'] + '/test/csvs/supply_energy.csv' snakemake.input["balances"] = snakemake.config['summary_dir'] + '/test/csvs/supply_energy.csv'
snakemake.output["balances"] = snakemake.config['summary_dir'] + '/test/graphs/balances-energy.csv' snakemake.output["balances"] = snakemake.config['summary_dir'] + '/test/graphs/balances-energy.csv'
n_header = 5 n_header = 4
plot_costs() plot_costs()
plot_energy() plot_energy()

View File

@ -68,11 +68,13 @@ def update_wind_solar_costs(n,costs):
#assign clustered bus #assign clustered bus
#map initial network -> simplified network #map initial network -> simplified network
busmap_s = pd.read_hdf(snakemake.input.clustermaps, busmap_s = pd.read_csv(snakemake.input.busmap_s, index_col=0).squeeze()
key="/busmap_s") busmap_s.index = busmap_s.index.astype(str)
busmap_s = busmap_s.astype(str)
#map simplified network -> clustered network #map simplified network -> clustered network
busmap = pd.read_hdf(snakemake.input.clustermaps, busmap = pd.read_csv(snakemake.input.busmap, index_col=0).squeeze()
key="/busmap") busmap.index = busmap.index.astype(str)
busmap = busmap.astype(str)
#map initial network -> clustered network #map initial network -> clustered network
clustermaps = busmap_s.map(busmap) clustermaps = busmap_s.map(busmap)
@ -526,7 +528,7 @@ def prepare_data(network):
dsm_week = np.zeros((24*7,)) dsm_week = np.zeros((24*7,))
dsm_week[(np.arange(0,7,1)*24+options['dsm_restriction_time'])] = options['dsm_restriction_value'] dsm_week[(np.arange(0,7,1)*24+options['bev_dsm_restriction_time'])] = options['bev_dsm_restriction_value']
dsm_profile = generate_periodic_profiles(dt_index=network.snapshots.tz_localize("UTC"), dsm_profile = generate_periodic_profiles(dt_index=network.snapshots.tz_localize("UTC"),
nodes=pop_layout.index, nodes=pop_layout.index,
@ -546,7 +548,7 @@ def prepare_data(network):
def prepare_costs(cost_file, USD_to_EUR, discount_rate, Nyears): def prepare_costs(cost_file, USD_to_EUR, discount_rate, Nyears, lifetime):
#set all asset costs and other parameters #set all asset costs and other parameters
costs = pd.read_csv(cost_file,index_col=list(range(2))).sort_index() costs = pd.read_csv(cost_file,index_col=list(range(2))).sort_index()
@ -564,7 +566,7 @@ def prepare_costs(cost_file, USD_to_EUR, discount_rate, Nyears):
"efficiency" : 1, "efficiency" : 1,
"fuel" : 0, "fuel" : 0,
"investment" : 0, "investment" : 0,
"lifetime" : 25 "lifetime" : lifetime
}) })
costs["fixed"] = [(annuity(v["lifetime"],v["discount rate"])+v["FOM"]/100.)*v["investment"]*Nyears for i,v in costs.iterrows()] costs["fixed"] = [(annuity(v["lifetime"],v["discount rate"])+v["FOM"]/100.)*v["investment"]*Nyears for i,v in costs.iterrows()]
@ -969,10 +971,28 @@ def add_storage(network):
lifetime=costs.at['SMR','lifetime']) lifetime=costs.at['SMR','lifetime'])
def add_transport(network): def add_land_transport(network):
print("adding transport")
print("adding land transport")
fuel_cell_share = get_parameter(options["land_transport_fuel_cell_share"])
electric_share = get_parameter(options["land_transport_electric_share"])
fossil_share = 1 - fuel_cell_share - electric_share
print("shares of FCEV, EV and ICEV are",
fuel_cell_share,
electric_share,
fossil_share)
if fossil_share < 0:
print("Error, more FCEV and EV share than 1.")
sys.exit()
nodes = pop_layout.index nodes = pop_layout.index
if electric_share > 0:
network.add("Carrier","Li ion") network.add("Carrier","Li ion")
network.madd("Bus", network.madd("Bus",
@ -983,12 +1003,12 @@ def add_transport(network):
network.madd("Load", network.madd("Load",
nodes, nodes,
suffix=" transport", suffix=" land transport EV",
bus=nodes + " EV battery", bus=nodes + " EV battery",
carrier="transport", carrier="land transport EV",
p_set=(1-options['transport_fuel_cell_share'])*(transport[nodes]+shift_df(transport[nodes],1)+shift_df(transport[nodes],2))/3.) p_set=electric_share*(transport[nodes]+shift_df(transport[nodes],1)+shift_df(transport[nodes],2))/3.)
p_nom = nodal_transport_data["number cars"]*0.011*(1-options['transport_fuel_cell_share']) #3-phase charger with 11 kW * x% of time grid-connected p_nom = nodal_transport_data["number cars"]*0.011*electric_share #3-phase charger with 11 kW * x% of time grid-connected
network.madd("Link", network.madd("Link",
nodes, nodes,
@ -1019,7 +1039,7 @@ def add_transport(network):
if options["bev"]: if options["bev_dsm"]:
network.madd("Store", network.madd("Store",
nodes, nodes,
@ -1027,21 +1047,30 @@ def add_transport(network):
bus=nodes + " EV battery", bus=nodes + " EV battery",
carrier="battery storage", carrier="battery storage",
e_cyclic=True, e_cyclic=True,
e_nom=nodal_transport_data["number cars"]*0.05*options["bev_availability"]*(1-options['transport_fuel_cell_share']), #50 kWh battery http://www.zeit.de/mobilitaet/2014-10/auto-fahrzeug-bestand e_nom=nodal_transport_data["number cars"]*0.05*options["bev_availability"]*electric_share, #50 kWh battery http://www.zeit.de/mobilitaet/2014-10/auto-fahrzeug-bestand
e_max_pu=1, e_max_pu=1,
e_min_pu=dsm_profile[nodes]) e_min_pu=dsm_profile[nodes])
if options['transport_fuel_cell_share'] != 0: if fuel_cell_share > 0:
network.madd("Load", network.madd("Load",
nodes, nodes,
suffix=" transport fuel cell", suffix=" land transport fuel cell",
bus=nodes + " H2", bus=nodes + " H2",
carrier="transport fuel cell", carrier="land transport fuel cell",
p_set=options['transport_fuel_cell_share']/costs.at["fuel cell","efficiency"]*transport[nodes]) p_set=fuel_cell_share/options['transport_fuel_cell_efficiency']*transport[nodes])
if fossil_share > 0:
network.madd("Load",
nodes,
suffix=" land transport fossil",
bus="Fischer-Tropsch",
carrier="land transport fossil",
p_set=fossil_share/options['transport_internal_combustion_efficiency']*transport[nodes])
def add_heat(network): def add_heat(network):
@ -1269,6 +1298,7 @@ def add_heat(network):
lifetime=costs.at['central gas CHP CCS','lifetime']) lifetime=costs.at['central gas CHP CCS','lifetime'])
else: else:
if options["micro_chp"]:
network.madd("Link", network.madd("Link",
nodes[name] + " " + name + " micro gas CHP", nodes[name] + " " + name + " micro gas CHP",
p_nom_extendable=True, p_nom_extendable=True,
@ -1794,6 +1824,13 @@ def remove_h2_network(n):
carrier="H2 Store", carrier="H2 Store",
capital_cost=h2_capital_cost) capital_cost=h2_capital_cost)
def get_parameter(item):
"""Check whether it depends on investment year"""
if type(item) is dict:
return item[investment_year]
else:
return item
if __name__ == "__main__": if __name__ == "__main__":
@ -1803,10 +1840,8 @@ if __name__ == "__main__":
snakemake = MockSnakemake( snakemake = MockSnakemake(
wildcards=dict(network='elec', simpl='', clusters='37', lv='1.0', wildcards=dict(network='elec', simpl='', clusters='37', lv='1.0',
opts='', planning_horizons='2020', opts='', planning_horizons='2020',
co2_budget_name='go',
sector_opts='Co2L0-168H-T-H-B-I-solar3-dist1'), sector_opts='Co2L0-168H-T-H-B-I-solar3-dist1'),
input=dict( input=dict(network='../pypsa-eur/networks/{network}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc',
network='../pypsa-eur/networks/{network}_s{simpl}_{clusters}_ec_lv{lv}_{opts}.nc',
energy_totals_name='resources/energy_totals.csv', energy_totals_name='resources/energy_totals.csv',
co2_totals_name='resources/co2_totals.csv', co2_totals_name='resources/co2_totals.csv',
transport_name='resources/transport_data.csv', transport_name='resources/transport_data.csv',
@ -1816,7 +1851,6 @@ if __name__ == "__main__":
heat_profile="data/heat_load_profile_BDEW.csv", heat_profile="data/heat_load_profile_BDEW.csv",
costs="../technology-data/outputs/costs_{planning_horizons}.csv", costs="../technology-data/outputs/costs_{planning_horizons}.csv",
h2_cavern = "data/hydrogen_salt_cavern_potentials.csv", h2_cavern = "data/hydrogen_salt_cavern_potentials.csv",
co2_budget="data/co2_budget.csv",
profile_offwind_ac="../pypsa-eur/resources/profile_offwind-ac.nc", profile_offwind_ac="../pypsa-eur/resources/profile_offwind-ac.nc",
profile_offwind_dc="../pypsa-eur/resources/profile_offwind-dc.nc", profile_offwind_dc="../pypsa-eur/resources/profile_offwind-dc.nc",
clustermaps='../pypsa-eur/resources/clustermaps_{network}_s{simpl}_{clusters}.h5', clustermaps='../pypsa-eur/resources/clustermaps_{network}_s{simpl}_{clusters}.h5',
@ -1860,6 +1894,8 @@ if __name__ == "__main__":
opts = snakemake.wildcards.sector_opts.split('-') opts = snakemake.wildcards.sector_opts.split('-')
investment_year=int(snakemake.wildcards.planning_horizons[-4:])
n = pypsa.Network(snakemake.input.network, n = pypsa.Network(snakemake.input.network,
override_component_attrs=override_component_attrs) override_component_attrs=override_component_attrs)
@ -1876,7 +1912,8 @@ if __name__ == "__main__":
costs = prepare_costs(snakemake.input.costs, costs = prepare_costs(snakemake.input.costs,
snakemake.config['costs']['USD2013_to_EUR2013'], snakemake.config['costs']['USD2013_to_EUR2013'],
snakemake.config['costs']['discountrate'], snakemake.config['costs']['discountrate'],
Nyears) Nyears,
snakemake.config['costs']['lifetime'])
remove_elec_base_techs(n) remove_elec_base_techs(n)
@ -1916,7 +1953,7 @@ if __name__ == "__main__":
options["central"] = False options["central"] = False
if "T" in opts: if "T" in opts:
add_transport(n) add_land_transport(n)
if "H" in opts: if "H" in opts:
add_heat(n) add_heat(n)
@ -1944,33 +1981,36 @@ if __name__ == "__main__":
else: else:
logger.info("No resampling") logger.info("No resampling")
#process CO2 limit
limit = get_parameter(snakemake.config["co2_budget"])
print("CO2 limit set to",limit)
if snakemake.config["foresight"] == 'myopic':
co2_limits=pd.read_csv(snakemake.input.co2_budget, index_col=0)
year=snakemake.wildcards.planning_horizons[-4:]
limit=co2_limits.loc[int(year),snakemake.config["scenario"]["co2_budget_name"]]
add_co2limit(n, Nyears, limit)
else:
for o in opts: for o in opts:
if "Co2L" in o: if "Co2L" in o:
limit = o[o.find("Co2L")+4:] limit = o[o.find("Co2L")+4:]
print(o,limit)
if limit == "":
limit = snakemake.config['co2_reduction']
else:
limit = float(limit.replace("p",".").replace("m","-")) limit = float(limit.replace("p",".").replace("m","-"))
print("overriding CO2 limit with scenario limit",limit)
print("adding CO2 budget limit as per unit of 1990 levels of",limit)
add_co2limit(n, Nyears, limit) add_co2limit(n, Nyears, limit)
# add_emission_prices(n, exclude_co2=True)
# if 'Ep' in opts:
# add_emission_prices(n)
for o in opts:
for tech in ["solar","onwind","offwind"]: for tech in ["solar","onwind","offwind"]:
if tech in o: if tech in o:
limit = o[o.find(tech)+len(tech):] limit = o[o.find(tech)+len(tech):]
limit = float(limit.replace("p",".").replace("m","-")) limit = float(limit.replace("p",".").replace("m","-"))
print("changing potential for",tech,"by factor",limit)
restrict_technology_potential(n,tech,limit) restrict_technology_potential(n,tech,limit)
if o[:10] == 'linemaxext':
maxext = float(o[10:])*1e3
print("limiting new HVAC and HVDC extensions to",maxext,"MW")
n.lines['s_nom_max'] = n.lines['s_nom'] + maxext
hvdc = n.links.index[n.links.carrier == 'DC']
n.links.loc[hvdc,'p_nom_max'] = n.links.loc[hvdc,'p_nom'] + maxext
if snakemake.config["sector"]['electricity_distribution_grid']: if snakemake.config["sector"]['electricity_distribution_grid']:
insert_electricity_distribution_grid(n) insert_electricity_distribution_grid(n)
if snakemake.config["sector"]['gas_distribution_grid']: if snakemake.config["sector"]['gas_distribution_grid']:

View File

@ -351,7 +351,7 @@ def solve_network(n, config=None, solver_log=None, opts=None):
# fn = os.path.basename(snakemake.output[0]) # fn = os.path.basename(snakemake.output[0])
# n.export_to_netcdf('/home/vres/data/jonas/playground/pypsa-eur/' + fn) # n.export_to_netcdf('/home/vres/data/jonas/playground/pypsa-eur/' + fn)
status, termination_condition = run_lopf(n, fix_ext_lines=True) status, termination_condition = run_lopf(n, allow_warning_status=True, fix_ext_lines=True)
# Drop zero lines from network # Drop zero lines from network
# zero_lines_i = n.lines.index[(n.lines.s_nom_opt == 0.) & n.lines.s_nom_extendable] # zero_lines_i = n.lines.index[(n.lines.s_nom_opt == 0.) & n.lines.s_nom_extendable]