forked from NREL/ReEDS-2.0
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathB1_osprey.gms
480 lines (367 loc) · 13.6 KB
/
B1_osprey.gms
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
$title 'Optimize Transmission Flows and Storage Dispatch'
*Setting the default directory separator
$setglobal ds \
*Change the default slash if in UNIX
$ifthen.unix %system.filesys% == UNIX
$setglobal ds /
$endif.unix
$eolcom \\
* --- supress .lst file printing ---
* equations listed per block
option limrow = 0 ;
* variables listed per block
option limcol = 0 ;
* solver's solution output printed
option solprint = off ;
* solver's system output printed
option sysout = off ;
*** Print to log file when running in parallel
* option AsyncSolLst = 1
option profile = 3
option profiletol = 0
*========================
* ---- Model Options ----
*========================
scalar
Sw_Solve "switch to choose solve method: 1 is loop, 2 is GUSS, 3 is grid" / 3 /
;
*========================
* -- Set Declarations --
*========================
set i, v, r, rfeas, szn, routes, storage_standalone, hydro_d, hydro_nd, geo, nuclear, trtype, notvsc, Sw_VSC ;
*Load sets from ReEDS
$gdxin ReEDS_Augur%ds%augur_data%ds%reeds_data_%prev_year%.gdx
$loadr geo
$loadr hydro_d
$loadr hydro_nd
$loadr i
$loadr notvsc
$loadr nuclear
$loadr r
$loadr rfeas
$loadr storage_standalone
$loadr szn
$loadr trtype
$loadr v
$loadr Sw_VSC
$gdxin
Set hr "hours in a modeled period" / hr001*hr%hoursperperiod% / ;
alias (hr,hh) ;
set nexth(hr,hh) "next hour"
priorh(hr,hh) "previous hour" ;
nexth(hr,hh)$(ord(hr) = ord(hh)-1) = yes ;
nexth(hr,hh)$[(ord(hr) = card(hr))$(ord(hh) = 1)] = yes ;
priorh(hr,hh)$(ord(hr) = ord(hh)+1) = yes ;
priorh(hr,hh)$[(ord(hh) = card(hh))$(ord(hr) = 1)] = yes ;
$onOrder
set d "day"
/
$offlisting
$include inputs_case%ds%d_osprey.csv
$onlisting
/ ;
$offOrder
set d_szn(d,szn) "mapping of days to seasons" /
$offlisting
$ondelim
$include inputs_case%ds%d_szn.csv
$offdelim
$onlisting
/ ;
alias (r, rr) ;
alias (trtype, intype, outtype) ;
*==============================
* -- Parameter Declarations --
*==============================
Parameter
avail_day(d,i,v) "--fraction-- Fraction of nameplate capacity available"
avail(i,v) "--fraction-- Fraction of nameplate capacity available for modeled day"
cap_converter(r) "--MW-- VSC AC/DC converter capacity"
cap_prod(r) "--MW-- capacity for production activities"
cap_trans(r,rr,trtype) "--MW-- transmission line capacities",
cap(i,v,r) "--MW-- Nameplate non-VRE generation capacity"
converter_efficiency_vsc "--fraction-- VSC AC/DC converter efficiency"
cost_dropped_load "--$/MWh-- Cost for dropped load"
cost_flow "--$/MW-- Cost for using transmission lines"
duration(i) "--h-- storage duration in hours"
energy_budget_feas(i,v,r) "--MW-- Filter instances where energy budget applies"
energy_budget(i,v,r) "--MWh-- Energy budget for dispatchable hydro and hybrid resources for a given day"
gen_cost(i,v,r) "--$/MWh-- total variable generation costs (fuel + VOM)",
net_load(hr,r) "--MW-- Net load for a given day"
prod_load_day(d,r) "--MWh-- demand for production activities (H2, DAC) by day"
prod_load(r) "--MWh-- demand for production (used in model)"
storage_eff(i) "--fraction-- round-trip efficiency of storage technologies",
tranloss(r,rr,trtype) "--fraction-- transmission losses between r and rr"
;
* Load values from ReEDS
$gdxin ReEDS_Augur%ds%augur_data%ds%osprey_inputs_%prev_year%.gdx
$loadr avail_day
$loadr cap
$loadr cap_converter
$loadr cap_trans = trancap
$loadr converter_efficiency_vsc
$loadr duration
$loadr gen_cost
$loadr cap_prod
$loadr prod_load_day = prod_load
$loadr routes
$loadr storage_eff
$loadr tranloss
$gdxin
* Pare down a few
tranloss(r,rr,trtype)$(not routes(r,rr,trtype)) = 0 ;
$onempty
Parameter energy_budget_day(d,i,v,r) "--MWh-- Energy budget for dispatchable hydro and hybrid resources"
/
$offlisting
$ondelim
$include ReEDS_Augur%ds%augur_data%ds%daily_energy_budget_%prev_year%.csv
$offdelim
$onlisting
/ ;
$offempty
Table net_load_day(d,hr,r) "--MW-- Net load for 24-hour horizon"
$offlisting
$ondelim
$include ReEDS_Augur%ds%augur_data%ds%net_load_%prev_year%.csv
$offdelim
$onlisting
;
* Initialize parameters
set firstd(d) "first modeled period" ;
firstd(d) = yes$(ord(d) = 1) ;
avail(i,v) = sum{d$firstd(d), avail_day(d,i,v) } ;
net_load(hr,r) = sum{d$firstd(d), net_load_day(d,hr,r) } ;
energy_budget(i,v,r) = sum{d$firstd(d), energy_budget_day(d,i,v,r) } ;
energy_budget_feas(i,v,r) = sum{d$firstd(d), energy_budget_day(d,i,v,r) } ;
prod_load(r) = sum{d$firstd(d), prod_load_day(d,r) } ;
*The small value of cost_flow is used to reduce degeneracy in where curtailment occurs
cost_flow = 0.001 ;
* Add small cost for discharging storage in order to prevent degeneracy between storage losses and curtailment
* Use the same as used for cost_flow
gen_cost(i,v,r)$[cap(i,v,r)$storage_standalone(i)$(gen_cost(i,v,r) = 0)] = cost_flow ;
*Use the maximum cost and increase it by a fixed amount so that it is always higher than the highest generator cost
cost_dropped_load = smax((i,v,r)$cap(i,v,r), gen_cost(i,v,r) ) + 10000 ;
*=============================
* -- Variable Declarations --
*=============================
positive variables
GEN(hr,i,v,r) "--MW-- Electricity generation in hour h"
PRODUCE(hr,r) "--MW-- electricity generation for meeting production activities demand"
STORAGE_IN(hr,i,v,r) "--MW-- Energy going into storage in hour h"
STORAGE_LEVEL(hr,i,v,r) "--MWh-- storage level in hour h"
FLOW(hr,r,rr,trtype) "--MW-- Electricity flow on transmission lines in hour h"
CONVERSION(hr,r,intype,outtype) "--MW-- conversion of AC->DC_VSC or DC_VSC->AC"
DROPPED_LOAD(hr,r) "--MW-- Dropped load"
;
* initialize the upper bound
PRODUCE.up(hr,r)$cap_prod(r) = cap_prod(r) ;
Variable Z "--$-- Objective function value" ;
*=============================
* -- Equation Declarations --
*=============================
Equation
* objective function calculation
eq_ObjFn "--$-- Objective function calculation"
* other equations
eq_daily_load_balance(r) "--MWh-- daily production balance for H2 and DAC"
eq_energy_budget_balance(i,v,r) "--MWh-- daily energy balance for hydropower resources"
eq_flow_cap(hr,r,rr,trtype) "--MW-- Transmission flows must not exceed max capacity"
eq_gen_cap(hr,i,v,r) "--MW-- Generation must not exceed max capacity"
eq_load_balance(hr,r) "--MW-- Load must be served"
eq_storage_duration(hr,i,v,r) "--MWh-- limit STORAGE_LEVEL based on hours of storage available"
eq_storage_level(hr,i,v,r) "--MWh-- Storage level inventory balance from one time-slice to the next"
eq_vsc_flow(hr,r) "--MW-- VSC DC power flow"
eq_conversion_limit(hr,r) "--MW-- AC/DC energy conversion is limited to converter capacity"
;
* --- Capacity limits ---
eq_gen_cap(hr,i,v,r)$cap(i,v,r)..
GEN(hr,i,v,r) + STORAGE_IN(hr,i,v,r)$[storage_standalone(i)]
=l=
cap(i,v,r) * avail(i,v)
;
eq_flow_cap(hr,r,rr,trtype)$routes(r,rr,trtype)..
FLOW(hr,r,rr,trtype)
=l=
cap_trans(r,rr,trtype)
;
* --- Load balance ---
eq_load_balance(hr,r)$rfeas(r)..
+ sum{(i,v)$cap(i,v,r), GEN(hr,i,v,r) }
+ sum{(rr,trtype)$[routes(rr,r,trtype)$notvsc(trtype)],
(1-tranloss(rr,r,trtype)) * FLOW(hr,rr,r,trtype) }
- sum{(rr,trtype)$[routes(r,rr,trtype)$notvsc(trtype)],
FLOW(hr,r,rr,trtype) }
+ (CONVERSION(hr,r,"VSC","AC") * converter_efficiency_vsc)$[cap_converter(r)$Sw_VSC]
- (CONVERSION(hr,r,"AC","VSC") / converter_efficiency_vsc)$[cap_converter(r)$Sw_VSC]
- sum{(i,v)$[storage_standalone(i)$cap(i,v,r)], STORAGE_IN(hr,i,v,r) }
+ DROPPED_LOAD(hr,r)
=g=
net_load(hr,r) + PRODUCE(hr,r)$cap_prod(r)
;
* --- VSC HVDC macrogrid ---
eq_vsc_flow(hr,r)$[rfeas(r)$Sw_VSC]..
* [plus] net VSC DC transmission with imports reduced by losses
+ sum{rr$routes(rr,r,"VSC"), (1-tranloss(rr,r,"VSC")) * FLOW(hr,rr,r,"VSC") }
- sum{rr$routes(r,rr,"VSC"), FLOW(hr,r,rr,"VSC") }
* [plus] net VSC AC/DC conversion
+ (CONVERSION(hr,r,"AC","VSC") * converter_efficiency_vsc)$cap_converter(r)
- (CONVERSION(hr,r,"VSC","AC") / converter_efficiency_vsc)$cap_converter(r)
=e=
* no direct consumption of VSC
0
;
eq_conversion_limit(hr,r)$[rfeas(r)$cap_converter(r)$Sw_VSC]..
CONVERSION(hr,r,"AC","VSC") + CONVERSION(hr,r,"VSC","AC")
=l=
cap_converter(r)
;
* --- Hydrogen ---
eq_daily_load_balance(r)$[rfeas(r)$cap_prod(r)]..
sum{hr, PRODUCE(hr,r) }
=e=
prod_load(r)
;
* --- Dispatchable hydro and hybrids ---
eq_energy_budget_balance(i,v,r)$[energy_budget_feas(i,v,r)]..
sum{hr, GEN(hr,i,v,r) }
=l=
energy_budget(i,v,r)
;
* --- Storage ---
eq_storage_level(hr,i,v,r)$[storage_standalone(i)$cap(i,v,r)]..
sum{hh$[nexth(hr,hh)], STORAGE_LEVEL(hh,i,v,r) }
=e=
+ STORAGE_LEVEL(hr,i,v,r)
+ storage_eff(i) * STORAGE_IN(hr,i,v,r)
- GEN(hr,i,v,r)$[storage_standalone(i)$cap(i,v,r)]
;
eq_storage_duration(hr,i,v,r)$[storage_standalone(i)$cap(i,v,r)]..
cap(i,v,r) * duration(i) * avail(i,v)
=g=
STORAGE_LEVEL(hr,i,v,r)
;
* --------------------------
* --- Objective function ---
* --------------------------
eq_ObjFn..
Z
=e=
+ sum{(hr,i,v,r)$[gen_cost(i,v,r)$cap(i,v,r)], gen_cost(i,v,r) * GEN(hr,i,v,r) }
+ sum{(hr,r)$rfeas(r), DROPPED_LOAD(hr,r) * cost_dropped_load }
+ sum{(hr,r,rr,trtype)$routes(r,rr,trtype), cost_flow * FLOW(hr,r,rr,trtype) }
;
* --------------------------
Model osprey /all/ ;
option lp=%solver%;
osprey.optfile = 1 ;
OPTION RESLIM = 500000 ;
*=============================
* ---- Output Parameters -----
*=============================
Parameter
cf_output(i,r) "--fraction-- capacity factor of dispatchable generators"
CONVERSION_output(d,hr,r,intype,outtype) "--MW-- conversion of AC->DC_VSC or DC_VSC->AC"
dropped_load_output(d,hr,r) "--MW-- Dropped load"
flows_output(d,hr,r,rr,trtype) "--MW-- transmission flows"
gen_output(d,hr,i,v,r) "--MW-- generation"
prices(d,hr,r) "--$/MWh-- energy prices"
PRODUCE_output(d,hr,r) "--MW-- additional generation for the production of produce"
storage_in_output(d,hr,i,v,r) "--MW-- Energy going into storage"
storage_level_output(d,hr,i,v,r) "--MWh-- storage level"
;
*=============================
* ------- Loop Solution ------
*=============================
if(Sw_Solve = 1,
Loop(d,
net_load(hr,r) = net_load_day(d,hr,r) ;
avail(i,v) = avail_day(d,i,v) ;
energy_budget(i,v,r) = energy_budget_day(d,i,v,r) ;
prod_load(r) = prod_load_day(d,r) ;
Solve osprey using LP minimizing Z ;
prices(d,hr,r) = eq_load_balance.m(hr,r) ;
flows_output(d,hr,r,rr,trtype)$routes(r,rr,trtype) = FLOW.l(hr,r,rr,trtype) ;
gen_output(d,hr,i,v,r) = GEN.l(hr,i,v,r) ;
storage_in_output(d,hr,i,v,r) = STORAGE_IN.l(hr,i,v,r) ;
storage_level_output(d,hr,i,v,r) = STORAGE_LEVEL.l(hr,i,v,r) ;
dropped_load_output(d,hr,r) = DROPPED_LOAD.l(hr,r) ;
PRODUCE_output(d,hr,r) = PRODUCE.l(hr,r) ;
CONVERSION_output(d,hr,r,intype,outtype) = CONVERSION.l(hr,r,intype,outtype) ;
) ;
) ;
*=============================
* ------- GUSS Solution ------
*=============================
set gd(d) "days per GUSS run" ;
set dict / gd. scenario. ''
net_load. param. net_load_day
avail. param. avail_day
energy_budget. param. energy_budget_day
prod_load. param. prod_load_day
eq_load_balance. marginal. prices
FLOW. level. flows_output
GEN. level. gen_output
STORAGE_IN. level. storage_in_output
STORAGE_LEVEL. level. storage_level_output
DROPPED_LOAD. level. dropped_load_output
PRODUCE. level. PRODUCE_output
CONVERSION. level. CONVERSION_output
/ ;
if(Sw_Solve = 2,
gd(d) = yes ;
Solve osprey using LP minimizing Z scenario dict ;
) ;
*=============================
* ------- Grid Solution ------
*=============================
set thread "grid jobs to run - only used if Sw_Solve=3" / 1*%threads% /
thread_days(thread,d) "map days to threads"
/
$offlisting
$ondelim
$include inputs_case%ds%threads.csv
$offdelim
$onlisting
/ ;
parameter h(thread) "model handles" ;
if(Sw_Solve = 3,
osprey.solveLink = %solveLink.AsyncThreads% ;
loop(thread,
gd(d) = thread_days(thread,d) ;
Solve osprey using LP minimizing Z scenario dict ;
h(thread) = osprey.handle ;
) ;
* Collect the solutions
repeat
loop(thread$handlecollect(h(thread)),
display$handledelete(h(thread)) "trouble deleting handles" ;
h(thread) = 0 ;
) ;
display$sleep(card(h)*5/%threads%) "waiting for solver" ;
until card(h) = 0 or timeelapsed > 7200 ;
) ;
*=============================
* ------- Write results ------
*=============================
cf_output(i,r)$sum{v, cap(i,v,r) } =
sum{(d,hr,v), gen_output(d,hr,i,v,r) }
/ (sum{v, cap(i,v,r) } * 24 * sum{d, 1} ) ;
execute_unload "ReEDS_Augur%ds%augur_data%ds%osprey_outputs_%prev_year%.gdx"
* prices
* flows_output
* gen_output
* storage_in_output
* dr_inc_output
* net_load_day
* dropped_load_output
* PRODUCE_output
* storage_level_output
* energy_budget_day
* gen_cost
* cap_feas
* cost_dropped_load
* energy_budget_feas
* CONVERSION_output
* cf_output
;