Skip to content

Commit 96a53a5

Browse files
Merge pull request #231 from OSeMOSYS/max-capacity
RES generation and capacity target updates
2 parents 69ef3ac + 8694bf6 commit 96a53a5

29 files changed

+1266
-951
lines changed

config/config.yaml

+31-31
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ timeshift: 0 # value between -11 and 12
2020

2121
# Spatial Parameters
2222
geographic_scope:
23+
- "BTN"
2324
- "IND"
2425

2526
crossborderTrade: True
@@ -133,19 +134,6 @@ nodes_to_remove:
133134
#- "AAAXX" where AAA is a 3-letter country code, and XX is a 2-letter
134135
# sub-national code
135136

136-
powerplant_build_rates:
137-
# [TECHNOLOGY, COUNTRY, METHOD, VALUE, START_YEAR, END_YEAR]
138-
# where TECHNOLOGY_TYPE is, for example, all coal powerplants and is in the
139-
# format COA.
140-
# COUNTRY is the 3-letter country code. E.g. "IND" for "Indonesia"
141-
# METHOD specifies how the build rate is applied: absolute ("ABS" or as a
142-
# percentage ("PCT") of the maximum capacity for a TECHNOLOGY_TYPE.
143-
# VALUE is the value - either absolute or percentage - by which the capacity
144-
# of the associated TECHNOLOGY can increase. It is applied from the START_YEAR
145-
# to the END_YEAR.
146-
# E.g. - ["SPV", "IND", "ABS", 0, 2020, 2025]
147-
- ["SPV", "IND", "PCT", 25, 2020, 2025]
148-
149137
reserve_margin:
150138
# RESERVE_MARGIN: [PERCENTAGE, START_YEAR, END_YEAR]
151139
# Years for which there is no PERCENTAGE value will be interpolated
@@ -178,27 +166,39 @@ reserve_margin_technologies:
178166
LDS : 77
179167

180168
emission_limit:
181-
# - [EMISSION, COUNTRY, YEAR, VALUE]
169+
# - [EMISSION, COUNTRY, TYPE, YEAR, VALUE]
182170
# where VALUE is emissions in million tonnes of CO2-equivalent and YEAR is
183171
# when that constraint must be adhered to. All years between multiple emission
184-
# constraints will be interpolated.
185-
- ["CO2", "IND", 2040, 1]
186-
187-
fuel_limits:
188-
# FUEL: [VALUE, COUNTRY/INTERNATIONAL, YEAR]
189-
# Where FUEL is the fuel on which a limit is being applied (e.g. COA), VALUE is
190-
# the value in Petajoules (PJ), COUNTRY/INTERNATIONAL specific which domestic
191-
# fuel (e.g. IND) or international fuel ("INT") the limit is being applied to,
192-
# and YEAR is the year for which the limit is applied. All years between multiple
193-
# fuel extraction constraints will be interpolated.
194-
172+
# constraints will be interpolated if TYPE is set to "LINEAR". If "POINT" is used
173+
# it means that a singular year value is set without interpolation occuring in
174+
# previous target years. A combination of TYPE targets can be set per EMISSION and
175+
# COUNTRY yet only a single target per YEAR.
176+
- ["CO2", "IND", "POINT", 2048, 0]
177+
- ["CO2", "IND", "LINEAR", 2040, 1]
178+
- ["CO2", "IND", "LINEAR", 2028, 400]
179+
- ["CO2", "IND", "POINT", 2030, 300]
195180

196181
calibration:
197-
# OCG1: [50, "IND", 2021]
182+
# TECHNOLOGY: [VALUE, COUNTRY, YEAR]
183+
# where VALUE is percentage (%) availability of a given technology. This can be used
184+
# to constrain power plant output (generation).
185+
OCG1: [50, "IND", 2021]
198186

199187
re_targets:
200-
# E.g. - ["IND", 2030, 2040, 30]
201-
# where "IND" is the country code; 2030, 2040 are the start and end years
202-
# respectively; and 30 is the target between the start and end years (inclusive)
203-
# in %
204-
- ["IND", 2030, 2040, 30]
188+
# TARGET: [COUNTRY/NODE, [TECHNOLOGY], START_YEAR, END_YEAR, VALUE]
189+
# E.g. TO1: ["IND", [], "PCT", 2030, 2040, 60]
190+
# E.g. TO2: ["INDSO", ['WOF', 'WON'], "PCT", 2025, 2045, 15]
191+
# E.g. TO3: ["INDSO", ['WOF'], "ABS", 2040, 2050, 200]
192+
# Targets can be set in absolute terms ("ABS", VALUE = GW) or in relative terms
193+
# ("PCT", VALUE = %) where targets in relative terms represent the share of generation.
194+
# For "PCT", targets can be set at national (e.g. "IND") and nodal levels (e.g. "INDSO")
195+
# whereas "ABS" can only be set at nodal levels. For "PCT", a single technology can
196+
# be set for the target (e.g. ["WOF"]) a technology subset can be set (e.g. ['WOF', 'WON'])
197+
# or the TECHNOLOGY list can be left empty (e.g. []) as such that all renewable
198+
# technologies contribute to the target. For "ABS", only one technology can be
199+
# selected per target. Note that a combination of targets can be set that affect
200+
# the same countries/nodes/technologies. This can be computationally intensive.
201+
T01: ["", [], "PCT", 2048, 2050, 95]
202+
T02: ["IND", [], "PCT", 2030, 2040, 60]
203+
T03: ["INDSO", ['WOF','WON'], "PCT", 2025, 2045, 15]
204+
T04: ["INDSO", ['WOF'], "ABS", 2040, 2050, 200]

resources/data/transmission_build_rates.csv

-2
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,6 @@ TRNINDEAINDWE,0,2021,2024
428428
TRNINDEANPLXX,0,2021,2024
429429
TRNINDNEINDNO,0,2021,2024
430430
TRNINDNEMMRXX,0,2021,2024
431-
TRNINDNOINDSO,0,2021,2024
432431
TRNINDNOINDWE,0,2021,2024
433432
TRNINDNONPLXX,0,2021,2024
434433
TRNINDNOPAKXX,0,2021,2024
@@ -1043,7 +1042,6 @@ TRNINDEAINDWE,3,2025,2050
10431042
TRNINDEANPLXX,3,2025,2050
10441043
TRNINDNEINDNO,3,2025,2050
10451044
TRNINDNEMMRXX,3,2025,2050
1046-
TRNINDNOINDSO,3,2025,2050
10471045
TRNINDNOINDWE,3,2025,2050
10481046
TRNINDNONPLXX,3,2025,2050
10491047
TRNINDNOPAKXX,3,2025,2050

workflow/rules/model.smk

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ rule geographic_filter:
99
input:
1010
csv_files = expand('results/data/{csv}.csv', csv = OTOOLE_PARAMS),
1111
params:
12-
geographic_scope = config['geographic_scope']
12+
geographic_scope = config['geographic_scope'],
13+
res_targets = config['re_targets']
1314
output:
1415
csv_files = expand('results/{{scenario}}/data/{csv}.csv', csv = OTOOLE_PARAMS),
1516
# conda:

workflow/rules/preprocess.smk

+62-64
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ power_plant_files = [
2929
'powerplant/ResidualCapacity',
3030
'powerplant/TECHNOLOGY',
3131
'YEAR',
32-
'AvailabilityFactor'
32+
'AvailabilityFactor',
33+
'TotalAnnualMaxCapacity',
34+
'AccumulatedAnnualDemand',
35+
'TotalAnnualMinCapacity'
3336
]
3437

3538
transmission_files = [
@@ -100,11 +103,6 @@ emission_files = [
100103
'AnnualEmissionLimit'
101104
]
102105

103-
max_capacity_files = [
104-
'TotalAnnualMaxCapacity',
105-
'AccumulatedAnnualDemand',
106-
]
107-
108106
user_capacity_files = [
109107
'TotalAnnualMinCapacityInvestment',
110108
'TotalAnnualMaxCapacityInvestment'
@@ -116,7 +114,8 @@ fuel_limit_files = [
116114

117115
GENERATED_CSVS = (
118116
power_plant_files + transmission_files + storage_files + timeslice_files \
119-
+ reserves_files + demand_files + emission_files + max_capacity_files + fuel_limit_files
117+
+ reserves_files + demand_files + emission_files + fuel_limit_files
118+
120119
)
121120
GENERATED_CSVS = [Path(x).stem for x in GENERATED_CSVS]
122121
EMPTY_CSVS = [x for x in OTOOLE_PARAMS if x not in GENERATED_CSVS]
@@ -127,37 +126,78 @@ rule make_data_dir:
127126
output: directory('results/data')
128127
shell: 'mkdir -p {output}'
129128

129+
def demand_custom_csv() -> str:
130+
if config["nodes_to_add"]:
131+
return "resources/data/custom_nodes/specified_annual_demand.csv"
132+
else:
133+
return []
134+
135+
rule demand_projections:
136+
message:
137+
"Generating demand data..."
138+
input:
139+
plexos = "resources/data/PLEXOS_World_2015_Gold_V1.1.xlsx",
140+
plexos_demand = "resources/data/All_Demand_UTC_2015.csv",
141+
iamc_gdp ="resources/data/iamc_db_GDPppp_Countries.xlsx",
142+
iamc_pop = "resources/data/iamc_db_POP_Countries.xlsx",
143+
iamc_urb = "resources/data/iamc_db_URB_Countries.xlsx",
144+
iamc_missing = "resources/data/iamc_db_POP_GDPppp_URB_Countries_Missing.xlsx",
145+
td_losses = "resources/data/T&D Losses.xlsx",
146+
ember = "resources/data/ember_yearly_electricity_data.csv",
147+
custom_nodes = demand_custom_csv()
148+
params:
149+
start_year = config['startYear'],
150+
end_year = config['endYear'],
151+
custom_nodes = config["nodes_to_add"]
152+
output:
153+
csv_files = 'results/data/SpecifiedAnnualDemand.csv',
154+
log:
155+
log = 'results/logs/demand_projections.log'
156+
script:
157+
"../scripts/osemosys_global/demand/main.py"
130158

131159
def powerplant_cap_custom_csv() -> str:
132160
if config["nodes_to_add"]:
133161
return "resources/data/custom_nodes/residual_capacity.csv"
134162
else:
135-
return []
163+
return []
164+
165+
def powerplant_res_potentials_custom_csv() -> str:
166+
if config["nodes_to_add"]:
167+
return "resources/data/custom_nodes/RE_potentials.csv"
168+
else:
169+
return []
136170

137171
rule powerplant:
138172
message:
139173
"Generating powerplant data..."
140174
input:
175+
rules.demand_projections.output.csv_files,
141176
plexos = 'resources/data/PLEXOS_World_2015_Gold_V1.1.xlsx',
177+
res_limit = 'resources/data/PLEXOS_World_MESSAGEix_GLOBIOM_Softlink.xlsx',
178+
fuel_limit = 'resources/data/fuel_limits.csv',
179+
build_rates = 'resources/data/powerplant_build_rates.csv',
142180
weo_costs = 'resources/data/weo_2020_powerplant_costs.csv',
143181
weo_regions = 'resources/data/weo_region_mapping.csv',
144182
default_op_life = 'resources/data/operational_life.csv',
145183
naming_convention_tech = 'resources/data/naming_convention_tech.csv',
146184
default_av_factors = 'resources/data/availability_factors.csv',
147185
custom_res_cap = powerplant_cap_custom_csv(),
148-
cmo_forecasts = 'resources/data/CMO-October-2024-Forecasts.xlsx',
149-
fuel_prices = 'resources/data/fuel_prices.csv',
186+
custom_res_potentials = powerplant_res_potentials_custom_csv(),
150187
params:
151188
start_year = config['startYear'],
152189
end_year = config['endYear'],
153190
region_name = 'GLOBAL',
191+
geographic_scope = config['geographic_scope'],
154192
custom_nodes = config['nodes_to_add'],
193+
remove_nodes = config['nodes_to_remove'],
155194
user_defined_capacity = config['user_defined_capacity'],
156195
no_investment_techs = config['no_invest_technologies'],
196+
res_targets = config['re_targets'],
197+
calibration = config['calibration'],
157198
output_data_dir = 'results/data',
158199
input_data_dir = 'resources/data',
159200
powerplant_data_dir = 'results/data/powerplant',
160-
161201
output:
162202
csv_files = expand('results/data/{output_file}.csv', output_file = power_plant_files)
163203
log:
@@ -298,36 +338,6 @@ rule reserves:
298338
script:
299339
"../scripts/osemosys_global/reserves/main.py"
300340

301-
def demand_custom_csv() -> str:
302-
if config["nodes_to_add"]:
303-
return "resources/data/custom_nodes/specified_annual_demand.csv"
304-
else:
305-
return []
306-
307-
rule demand_projections:
308-
message:
309-
"Generating demand data..."
310-
input:
311-
plexos = "resources/data/PLEXOS_World_2015_Gold_V1.1.xlsx",
312-
plexos_demand = "resources/data/All_Demand_UTC_2015.csv",
313-
iamc_gdp ="resources/data/iamc_db_GDPppp_Countries.xlsx",
314-
iamc_pop = "resources/data/iamc_db_POP_Countries.xlsx",
315-
iamc_urb = "resources/data/iamc_db_URB_Countries.xlsx",
316-
iamc_missing = "resources/data/iamc_db_POP_GDPppp_URB_Countries_Missing.xlsx",
317-
td_losses = "resources/data/T&D Losses.xlsx",
318-
ember = "resources/data/ember_yearly_electricity_data.csv",
319-
custom_nodes = demand_custom_csv()
320-
params:
321-
start_year = config['startYear'],
322-
end_year = config['endYear'],
323-
custom_nodes = config["nodes_to_add"]
324-
output:
325-
csv_files = 'results/data/SpecifiedAnnualDemand.csv',
326-
log:
327-
log = 'results/logs/demand_projections.log'
328-
script:
329-
"../scripts/osemosys_global/demand/main.py"
330-
331341
rule demand_projection_figures:
332342
message:
333343
"Generating demand figures..."
@@ -350,36 +360,24 @@ rule emissions:
350360
message:
351361
'Generating emission data...'
352362
input:
353-
'resources/data/emission_factors.csv',
354-
'results/data/InputActivityRatio.csv',
363+
ember = 'resources/data/ember_yearly_electricity_data.csv',
364+
emissions_factors = 'resources/data/emission_factors.csv',
365+
iar = 'results/data/InputActivityRatio.csv',
366+
oar = 'results/data/OutputActivityRatio.csv',
355367
params:
356368
start_year = config['startYear'],
357369
end_year = config['endYear'],
358-
emission = config['emission_penalty'],
359-
storage_parameters = config['storage_parameters']
370+
region_name = 'GLOBAL',
371+
output_data_dir = 'results/data',
372+
input_data_dir = 'resources/data',
373+
emission_penalty = config['emission_penalty'],
374+
emission_limit = config['emission_limit'],
360375
output:
361376
csv_files = expand('results/data/{output_file}.csv', output_file = emission_files),
362377
log:
363378
log = 'results/logs/emissions.log'
364-
shell:
365-
'python workflow/scripts/osemosys_global/emissions.py 2> {log}'
366-
367-
rule max_capacity:
368-
message:
369-
'Generating capacity limits...'
370-
input:
371-
'resources/data/PLEXOS_World_MESSAGEix_GLOBIOM_Softlink.xlsx',
372-
'results/data/ResidualCapacity.csv',
373-
'results/data/SpecifiedAnnualDemand.csv'
374-
params:
375-
start_year = config['startYear'],
376-
end_year = config['endYear'],
377-
output:
378-
csv_files = expand('results/data/{output_file}.csv', output_file = max_capacity_files),
379-
log:
380-
log = 'results/logs/max_capacity.log'
381-
shell:
382-
'python workflow/scripts/osemosys_global/max_capacity.py 2> {log}'
379+
script:
380+
"../scripts/osemosys_global/emissions/main.py"
383381

384382
rule create_missing_csv:
385383
message:

0 commit comments

Comments
 (0)