Make directory for costs files configurable
Default to parallel directory for technology_data repository.
This commit is contained in:
parent
ece21bfdfa
commit
b57a6c18f8
68
Snakefile
Executable file → Normal file
68
Snakefile
Executable file → Normal file
@ -15,13 +15,13 @@ subworkflow pypsaeur:
|
||||
workdir: "../pypsa-eur"
|
||||
snakefile: "../pypsa-eur/Snakefile"
|
||||
configfile: "../pypsa-eur/config.yaml"
|
||||
|
||||
|
||||
rule all:
|
||||
input:
|
||||
input:
|
||||
config['summary_dir'] + '/' + config['run'] + '/graphs/costs.pdf'
|
||||
|
||||
|
||||
|
||||
|
||||
rule solve_all_elec_networks:
|
||||
input:
|
||||
expand(config['results_dir'] + config['run'] + "/postnetworks/elec_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}.nc",
|
||||
@ -174,7 +174,7 @@ rule build_industrial_demand:
|
||||
threads: 1
|
||||
resources: mem_mb=1000
|
||||
script: 'scripts/build_industrial_demand.py'
|
||||
|
||||
|
||||
|
||||
rule prepare_sector_network:
|
||||
input:
|
||||
@ -185,7 +185,7 @@ rule prepare_sector_network:
|
||||
biomass_potentials='data/biomass_potentials.csv',
|
||||
timezone_mappings='data/timezone_mappings.csv',
|
||||
heat_profile="data/heat_load_profile_BDEW.csv",
|
||||
costs="data/costs/costs_{planning_horizons}.csv", #"data/costs.csv"
|
||||
costs=config['costs_dir'] + "costs_{planning_horizons}.csv", #"data/costs.csv"
|
||||
co2_budget="data/co2_budget.csv",
|
||||
clustered_pop_layout="resources/pop_layout_{network}_s{simpl}_{clusters}.csv",
|
||||
industrial_demand="resources/industrial_demand_{network}_s{simpl}_{clusters}.csv",
|
||||
@ -265,7 +265,7 @@ rule make_summary:
|
||||
resources: mem_mb=10000
|
||||
script:
|
||||
'scripts/make_summary.py'
|
||||
|
||||
|
||||
|
||||
rule plot_summary:
|
||||
input:
|
||||
@ -282,13 +282,13 @@ rule plot_summary:
|
||||
'scripts/plot_summary.py'
|
||||
|
||||
if config["foresight"] == "overnight":
|
||||
|
||||
|
||||
rule solve_network:
|
||||
input:
|
||||
network=config['results_dir'] + config['run'] + "/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc",
|
||||
costs="data/costs/costs_{planning_horizons}.csv",
|
||||
|
||||
output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc"
|
||||
costs=config['costs_dir'] + "costs_{planning_horizons}.csv",
|
||||
|
||||
output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc"
|
||||
shadow: "shallow"
|
||||
log:
|
||||
solver="logs/" + config['run'] + "/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log",
|
||||
@ -297,51 +297,51 @@ if config["foresight"] == "overnight":
|
||||
benchmark: "benchmarks/solve_network/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}"
|
||||
threads: 4
|
||||
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
|
||||
script: "scripts/solve_network.py"
|
||||
|
||||
|
||||
if config["foresight"] == "myopic":
|
||||
|
||||
|
||||
if config["foresight"] == "myopic":
|
||||
|
||||
rule add_existing_baseyear:
|
||||
input:
|
||||
network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc',
|
||||
costs="data/costs/costs_{}.csv".format(config['scenario']['planning_horizons'][0]),
|
||||
cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc",
|
||||
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_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}_{co2_budget_name}_{planning_horizons}.nc'
|
||||
wildcard_constraints:
|
||||
planning_horizons=config['scenario']['planning_horizons'][0] #only applies to baseyear
|
||||
threads: 1
|
||||
resources: mem_mb=2000
|
||||
resources: mem_mb=2000
|
||||
script: "scripts/add_existing_baseyear.py"
|
||||
|
||||
|
||||
def process_input(wildcards):
|
||||
i = config["scenario"]["planning_horizons"].index(wildcards.planning_horizons)
|
||||
return config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_" + config["scenario"]["planning_horizons"][i-1] + ".nc"
|
||||
|
||||
|
||||
return config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_" + config["scenario"]["planning_horizons"][i-1] + ".nc"
|
||||
|
||||
|
||||
rule add_brownfield:
|
||||
input:
|
||||
network=config['results_dir'] + config['run'] + '/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc',
|
||||
network_p=process_input, #solved network at previous time step
|
||||
costs="data/costs/costs_{planning_horizons}.csv",
|
||||
cop_soil_total="resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc",
|
||||
costs=config['costs_dir'] + "costs_{planning_horizons}.csv",
|
||||
cop_soil_total="resources/cop_soil_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}_{co2_budget_name}_{planning_horizons}.nc"
|
||||
threads: 4
|
||||
resources: mem_mb=2000
|
||||
resources: mem_mb=2000
|
||||
script: "scripts/add_brownfield.py"
|
||||
|
||||
ruleorder: add_existing_baseyear > add_brownfield
|
||||
|
||||
ruleorder: add_existing_baseyear > add_brownfield
|
||||
|
||||
rule solve_network_myopic:
|
||||
input:
|
||||
network=config['results_dir'] + config['run'] + "/prenetworks_brownfield/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc",
|
||||
costs="data/costs/costs_{planning_horizons}.csv",
|
||||
|
||||
output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc"
|
||||
costs=config['costs_dir'] + "costs_{planning_horizons}.csv",
|
||||
|
||||
output: config['results_dir'] + config['run'] + "/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}.nc"
|
||||
shadow: "shallow"
|
||||
log:
|
||||
solver="logs/" + config['run'] + "/{network}_s{simpl}_{clusters}_lv{lv}_{opts}_{sector_opts}_{co2_budget_name}_{planning_horizons}_solver.log",
|
||||
@ -351,7 +351,3 @@ if config["foresight"] == "myopic":
|
||||
threads: 4
|
||||
resources: mem_mb=config['solving']['mem']
|
||||
script: "scripts/solve_network.py"
|
||||
|
||||
|
||||
|
||||
|
||||
|
7
config.default.yaml
Executable file → Normal file
7
config.default.yaml
Executable file → Normal file
@ -2,6 +2,7 @@ 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
|
||||
|
||||
@ -21,8 +22,8 @@ scenario:
|
||||
# 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'] #timesteps for myopic and perfect
|
||||
co2_budget_name: ['go']
|
||||
planning_horizons : ['2020', '2030', '2040', '2050'] #timesteps for myopic and perfect
|
||||
co2_budget_name: ['go']
|
||||
|
||||
# snapshots are originally set in PyPSA-Eur/config.yaml but used again by PyPSA-Eur-Sec
|
||||
snapshots:
|
||||
@ -49,7 +50,7 @@ biomass:
|
||||
existing_capacities:
|
||||
grouping_years: ['1980', '1985', '1990', '1995', '2000','2005','2010','2015', '2019']
|
||||
threshold_capacity: 10
|
||||
|
||||
|
||||
sector:
|
||||
'central' : True
|
||||
'central_fraction' : 0.6
|
||||
|
@ -41,16 +41,16 @@ override_component_attrs["Generator"].loc["build_year"] = ["integer","year",np.n
|
||||
override_component_attrs["Generator"].loc["lifetime"] = ["float","years",np.nan,"build year","Input (optional)"]
|
||||
override_component_attrs["Store"].loc["build_year"] = ["integer","year",np.nan,"build year","Input (optional)"]
|
||||
override_component_attrs["Store"].loc["lifetime"] = ["float","years",np.nan,"build year","Input (optional)"]
|
||||
|
||||
|
||||
def add_brownfield(n, n_p, year):
|
||||
print("adding brownfield")
|
||||
|
||||
|
||||
#first, remove generators, links and stores that track CO2 or global EU values
|
||||
n_p.mremove("Generator", [index for index in n_p.generators.index.to_list() if 'ror' in index])
|
||||
n_p.mremove("Generator", [index for index in n_p.generators.index.to_list() if 'ror' in index])
|
||||
n_p.mremove("Generator", ['EU fossil gas', 'fossil oil'] )
|
||||
n_p.mremove("Store", ['co2 atmosphere', 'co2 stored', 'EU gas Store'] )
|
||||
n_p.mremove("Link", ['co2 vent'] )
|
||||
|
||||
|
||||
if "H" in opts:
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list() if 'water tanks charger' in index])
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list() if 'water tanks discharger' in index])
|
||||
@ -64,31 +64,31 @@ def add_brownfield(n, n_p, year):
|
||||
n_p.mremove("Store", [index for index in n_p.stores.index.to_list() if 'battery storage' in index])
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list() if 'BEV charger' in index])
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list() if 'V2G' in index])
|
||||
|
||||
|
||||
previous_timestep=snakemake.config['scenario']['planning_horizons'][snakemake.config['scenario']['planning_horizons'].index(year)-1]
|
||||
previous_timesteps=snakemake.config['scenario']['planning_horizons'][0:snakemake.config['scenario']['planning_horizons'].index(year)]
|
||||
grouping_years=snakemake.config['existing_capacities']['grouping_years']
|
||||
|
||||
|
||||
|
||||
|
||||
### GENERATORS ###
|
||||
# generators whose build_year + lifetime < year are removed
|
||||
n_p.mremove("Generator", [index for index in n_p.generators.index.to_list()
|
||||
n_p.mremove("Generator", [index for index in n_p.generators.index.to_list()
|
||||
if (n_p.generators.loc[index, 'build_year']+n_p.generators.loc[index, 'lifetime'] < int(year))])
|
||||
|
||||
|
||||
# remove generators if their optimized nominal capacity is lower than a threshold
|
||||
n_p.mremove("Generator", [index for index in n_p.generators.index.to_list()
|
||||
n_p.mremove("Generator", [index for index in n_p.generators.index.to_list()
|
||||
if (n_p.generators.loc[index, 'p_nom_opt'] < snakemake.config['existing_capacities']['threshold_capacity'])])
|
||||
|
||||
|
||||
|
||||
# generators whose capacity was optimized in the previous year are renamed and build year is added
|
||||
n_p.generators.index=np.where(n_p.generators.index.str[-4:].isin(previous_timesteps+grouping_years)==False,
|
||||
n_p.generators.index + '-' + previous_timestep,
|
||||
n_p.generators.index + '-' + previous_timestep,
|
||||
n_p.generators.index)
|
||||
n_p.generators.loc[[index for index in n_p.generators.index.to_list()
|
||||
if previous_timestep in index], 'build_year']=int(previous_timestep)
|
||||
|
||||
#add generators from previous step
|
||||
n.madd("Generator",
|
||||
|
||||
#add generators from previous step
|
||||
n.madd("Generator",
|
||||
n_p.generators.index,
|
||||
bus=n_p.generators.bus,
|
||||
carrier=n_p.generators.carrier,
|
||||
@ -99,24 +99,24 @@ def add_brownfield(n, n_p, year):
|
||||
p_max_pu=n_p.generators_t.p_max_pu,
|
||||
build_year=n_p.generators.build_year,
|
||||
lifetime=n_p.generators.lifetime)
|
||||
|
||||
|
||||
### STORES ###
|
||||
# stores whose installationYear + lifetime < year are removed
|
||||
n_p.mremove("Store", [index for index in n_p.stores.index.to_list()
|
||||
if (n_p.stores.loc[index, 'build_year']+n_p.stores.loc[index, 'lifetime'] < int(year))])
|
||||
|
||||
n_p.mremove("Store", [index for index in n_p.stores.index.to_list()
|
||||
if (n_p.stores.loc[index, 'build_year']+n_p.stores.loc[index, 'lifetime'] < int(year))])
|
||||
|
||||
# remove stores if their optimized nominal capacity is lower than a threshold
|
||||
n_p.mremove("Store", [index for index in n_p.stores.index.to_list()
|
||||
n_p.mremove("Store", [index for index in n_p.stores.index.to_list()
|
||||
if (n_p.stores.loc[index, 'e_nom_opt'] < snakemake.config['existing_capacities']['threshold_capacity'])])
|
||||
|
||||
|
||||
# stores whose capacity was optimized in the previous year are renamed and the build year is added
|
||||
n_p.stores.index=np.where(n_p.stores.index.str[-4:].isin(previous_timesteps+grouping_years)==False,
|
||||
n_p.stores.index + '-' + previous_timestep,
|
||||
n_p.stores.index + '-' + previous_timestep,
|
||||
n_p.stores.index)
|
||||
n_p.stores.loc[[index for index in n_p.stores.index.to_list()
|
||||
if previous_timestep in index], 'build_year']=int(previous_timestep)
|
||||
#add stores from previous steps
|
||||
n.madd("Store",
|
||||
n.madd("Store",
|
||||
n_p.stores.index,
|
||||
bus=n_p.stores.bus,
|
||||
carrier=n_p.stores.carrier,
|
||||
@ -125,27 +125,27 @@ def add_brownfield(n, n_p, year):
|
||||
capital_cost=n_p.stores.capital_cost,
|
||||
build_year=n_p.stores.build_year,
|
||||
lifetime=n_p.stores.lifetime)
|
||||
|
||||
### LINKS ###
|
||||
# TODO: add_chp_constraint() in solve_network needs to be adjusted
|
||||
|
||||
### LINKS ###
|
||||
# TODO: add_chp_constraint() in solve_network needs to be adjusted
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list() if 'CHP' in index])
|
||||
|
||||
|
||||
# links whose installationYear + lifetime < year are removed
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list()
|
||||
if (n_p.links.loc[index, 'build_year']+n_p.links.loc[index, 'lifetime'] < int(year))])
|
||||
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list()
|
||||
if (n_p.links.loc[index, 'build_year']+n_p.links.loc[index, 'lifetime'] < int(year))])
|
||||
|
||||
# delete links if their optimized nominal capacity is lower than a threshold
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list()
|
||||
n_p.mremove("Link", [index for index in n_p.links.index.to_list()
|
||||
if (n_p.links.loc[index, 'p_nom_opt'] < snakemake.config['existing_capacities']['threshold_capacity'])])
|
||||
|
||||
|
||||
# links whose capacity was optimized in the previous year are renamed and the build year is added
|
||||
n_p.links.index=np.where(n_p.links.index.str[-4:].isin(previous_timesteps+grouping_years)==False,
|
||||
n_p.links.index + '-' + previous_timestep,
|
||||
n_p.links.index + '-' + previous_timestep,
|
||||
n_p.links.index)
|
||||
n_p.links.loc[[index for index in n_p.links.index.to_list()
|
||||
if previous_timestep in index], 'build_year']=int(previous_timestep)
|
||||
#add links from previous steps
|
||||
n.madd("Link",
|
||||
n.madd("Link",
|
||||
n_p.links.index,
|
||||
bus0=n_p.links.bus0,
|
||||
bus1=n_p.links.bus1,
|
||||
@ -158,23 +158,23 @@ def add_brownfield(n, n_p, year):
|
||||
efficiency2=n_p.links.efficiency2,
|
||||
build_year=n_p.links.build_year,
|
||||
lifetime=n_p.links.lifetime)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Detect running outside of snakemake and mock snakemake for testing
|
||||
if 'snakemake' not in globals():
|
||||
from vresutils.snakemake import MockSnakemake
|
||||
snakemake = MockSnakemake(
|
||||
wildcards=dict(network='elec', simpl='', clusters='37', lv='1.0',
|
||||
wildcards=dict(network='elec', simpl='', clusters='37', lv='1.0',
|
||||
sector_opts='Co2L0-168H-T-H-B-I-solar3-dist1',
|
||||
co2_budget_name='go',
|
||||
planning_horizons='2030'),
|
||||
input=dict(network='pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc',
|
||||
network_p='pypsa-eur-sec/results/test/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_2020.nc',
|
||||
input=dict(network='pypsa-eur-sec/results/test/prenetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_{planning_horizons}.nc',
|
||||
network_p='pypsa-eur-sec/results/test/postnetworks/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{co2_budget_name}_2020.nc',
|
||||
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_soil_total="pypsa-eur-sec/resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc"),
|
||||
output=['pypsa-eur-sec/results/test/prenetworks_brownfied/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc']
|
||||
cop_soil_total="pypsa-eur-sec/resources/cop_soil_total_{network}_s{simpl}_{clusters}.nc"),
|
||||
output=['pypsa-eur-sec/results/test/prenetworks_brownfield/{network}_s{simpl}_{clusters}_lv{lv}__{sector_opts}_{planning_horizons}.nc']
|
||||
)
|
||||
import yaml
|
||||
with open('config.yaml') as f:
|
||||
@ -185,28 +185,25 @@ if __name__ == "__main__":
|
||||
|
||||
options = snakemake.config["sector"]
|
||||
opts = snakemake.wildcards.sector_opts.split('-')
|
||||
|
||||
|
||||
year=snakemake.wildcards.planning_horizons
|
||||
|
||||
n = pypsa.Network(snakemake.input.network,
|
||||
override_component_attrs=override_component_attrs)
|
||||
|
||||
|
||||
n_p = pypsa.Network(snakemake.input.network_p,
|
||||
override_component_attrs=override_component_attrs)
|
||||
#%%
|
||||
add_brownfield(n, n_p, year)
|
||||
|
||||
|
||||
Nyears = n.snapshot_weightings.sum()/8760.
|
||||
|
||||
|
||||
costs = prepare_costs(snakemake.input.costs,
|
||||
snakemake.config['costs']['USD2013_to_EUR2013'],
|
||||
snakemake.config['costs']['discountrate'],
|
||||
Nyears)
|
||||
|
||||
baseyear = snakemake.config['scenario']["planning_horizons"][0]
|
||||
|
||||
|
||||
|
||||
|
||||
n.export_to_netcdf(snakemake.output[0])
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user