Skip to content

Commit 95f4ad1

Browse files
gnawinabelsiqueira
andauthored
[Multi-year Part II] Add low sum limit for transport vintage outgoing flows for semi-compact method (#1326)
* Add con indices * Update con indices and create con * Update constraints and add tests * Remove the other lower bound to leave on this new one for semi-compact * Refactor the tranport constraints * Update src/sql/create-constraints.sql Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com> * Update src/sql/create-constraints.sql Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com> * Update src/sql/create-constraints.sql Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com> * Update src/sql/create-constraints.sql Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com> * Update src/sql/create-constraints.sql Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com> * Update src/sql/create-constraints.sql Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com> * Update src/sql/create-constraints.sql Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com> * Apply review suggestions to other applicable places --------- Co-authored-by: Abel Soares Siqueira <nepper271@gmail.com>
1 parent 5a42dd1 commit 95f4ad1

File tree

5 files changed

+145
-30
lines changed

5 files changed

+145
-30
lines changed

src/constraints/create.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ function compute_constraints_indices(connection)
2929
:max_energy_over_clustered_year,
3030
:transport_flow_limit_simple_method,
3131
:min_outgoing_flow_for_transport_flows_without_unit_commitment,
32+
:min_outgoing_flow_for_transport_vintage_flows,
3233
:min_incoming_flow_for_transport_flows,
3334
:group_max_investment_limit,
3435
:group_min_investment_limit,

src/constraints/transport.jl

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,44 @@ function add_transport_constraints!(
1212
expressions,
1313
constraints,
1414
profiles,
15+
)
16+
# - Capacity limits for transport flows including lower bounds and upper bounds
17+
add_capacity_limits_transport_flows!(
18+
connection,
19+
model,
20+
variables,
21+
expressions,
22+
constraints,
23+
profiles,
24+
)
25+
26+
# - Minimum output flows limit if any of the flows is transport flow
27+
# - This allows some negative flows but not all negative flows, so transport flows can pass
28+
# - through this asset
29+
# - Holds for producers, conversion and storage assets
30+
add_min_outgoing_flow_for_transport_flows_without_unit_commitment(model, constraints)
31+
32+
# - Minimum output vintage flows limit if any of the flows is transport flow
33+
# - Since regular flow is a special case of the vintage_flow, vintage_flow has to have the same
34+
# - constraint as the regular flow above
35+
add_min_outgoing_flow_for_transport_vintage_flows(model, constraints)
36+
37+
# - Minimum input flows limit if any of the flows is transport flow
38+
# - This allows some negative flows but not all negative flows, so transport flows can pass
39+
# - through this asset
40+
# - Holds for conversion and storage assets
41+
add_min_incoming_flow_for_transport_flows(model, constraints)
42+
43+
return
44+
end
45+
46+
function add_capacity_limits_transport_flows!(
47+
connection,
48+
model,
49+
variables,
50+
expressions,
51+
constraints,
52+
profiles,
1553
)
1654
## unpack from model
1755
expr_avail = expressions[:available_flow_units_simple_method]
@@ -89,10 +127,9 @@ function add_transport_constraints!(
89127
],
90128
)
91129
end
130+
end
92131

93-
# - Minimum output flows limit if any of the flows is transport flow
94-
# - This allows some negative flows but not all negative flows, so transport flows can pass through this asset
95-
# - Holds for producers, conversion and storage assets
132+
function add_min_outgoing_flow_for_transport_flows_without_unit_commitment(model, constraints)
96133
let table_name = :min_outgoing_flow_for_transport_flows_without_unit_commitment,
97134
cons_name = Symbol("min_output_flows_limit_for_transport_flows_without_unit_commitment")
98135

@@ -110,10 +147,29 @@ function add_transport_constraints!(
110147
],
111148
)
112149
end
150+
end
113151

114-
# - Minimum input flows limit if any of the flows is transport flow
115-
# - This allows some negative flows but not all negative flows, so transport flows can pass through this asset
116-
# - Holds for conversion and storage assets
152+
function add_min_outgoing_flow_for_transport_vintage_flows(model, constraints)
153+
let table_name = :min_outgoing_flow_for_transport_vintage_flows,
154+
cons_name = Symbol("min_output_flows_limit_for_transport_vintage_flows")
155+
156+
attach_constraint!(
157+
model,
158+
constraints[table_name],
159+
cons_name,
160+
[
161+
@constraint(
162+
model,
163+
outgoing_flow 0,
164+
base_name = "$cons_name[$(row.asset),$(row.milestone_year),$(row.commission_year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
165+
) for (row, outgoing_flow) in
166+
zip(constraints[table_name].indices, constraints[table_name].expressions[:outgoing])
167+
],
168+
)
169+
end
170+
end
171+
172+
function add_min_incoming_flow_for_transport_flows(model, constraints)
117173
let table_name = :min_incoming_flow_for_transport_flows,
118174
cons_name = Symbol("min_input_flows_limit_for_transport_flows")
119175

@@ -131,8 +187,6 @@ function add_transport_constraints!(
131187
],
132188
)
133189
end
134-
135-
return
136190
end
137191

138192
function _append_transport_data_to_indices(connection)

src/model-preparation.jl

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -519,16 +519,19 @@ function add_expressions_to_constraints!(connection, variables, constraints)
519519
multiply_by_duration = false,
520520
)
521521

522-
@timeit to "add_expression_terms_rep_period_constraints!" add_expression_terms_rep_period_constraints!(
523-
connection,
524-
constraints[:capacity_outgoing_semi_compact_method],
525-
variables[:vintage_flow],
526-
workspace;
527-
use_highest_resolution = true,
528-
multiply_by_duration = false,
529-
multiply_by_capacity_coefficient = true,
530-
include_commission_year = true,
531-
)
522+
for table_name in
523+
(:capacity_outgoing_semi_compact_method, :min_outgoing_flow_for_transport_vintage_flows)
524+
@timeit to "add_expression_terms_rep_period_constraints! for $table_name" add_expression_terms_rep_period_constraints!(
525+
connection,
526+
constraints[table_name],
527+
variables[:vintage_flow],
528+
workspace;
529+
use_highest_resolution = true,
530+
multiply_by_duration = false,
531+
multiply_by_capacity_coefficient = true,
532+
include_commission_year = true,
533+
)
534+
end
532535

533536
for table_name in (
534537
:capacity_incoming_simple_method,

src/sql/create-constraints.sql

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -272,22 +272,24 @@ drop table if exists cons_min_outgoing_flow_for_transport_flows_without_unit_com
272272

273273
create table cons_min_outgoing_flow_for_transport_flows_without_unit_commitment as
274274
-- We want to check if the outgoing flows of an asset have transport flows
275+
-- Note we assume that the this property does not change across the years
276+
-- In other words, we assume the underlying graph does not change
275277
-- This information is gathered from the flow table
276278
-- COALESCE is used to handle the case where there are no outgoing flows
277279
with
278-
transport_flow_info as (
280+
cte_transport_flow_info as (
279281
select
280282
asset.asset,
281283
coalesce(
282284
(
283285
select
284-
bool_or(flow.is_transport)
286+
bool_or(flow.is_transport) -- true if any outgoing flow is transport
285287
from
286288
flow
287289
where
288290
flow.from_asset = asset.asset
289291
),
290-
false
292+
false -- coalescing to false in case there are no outgoing flows
291293
) as outgoing_flows_have_transport_flows,
292294
from
293295
asset
@@ -298,12 +300,67 @@ select
298300
from
299301
t_highest_out_flows as t_high
300302
left join asset on t_high.asset = asset.asset
301-
left join transport_flow_info on t_high.asset = transport_flow_info.asset
303+
left join cte_transport_flow_info on t_high.asset = cte_transport_flow_info.asset
302304
where
303305
asset.type in ('producer', 'storage', 'conversion')
304-
and transport_flow_info.outgoing_flows_have_transport_flows
306+
and cte_transport_flow_info.outgoing_flows_have_transport_flows
305307
-- Assets with unit commitment already have a minimum outgoing flow constraints
306308
and not asset.unit_commitment
309+
and asset.investment_method in ('compact', 'simple', 'none')
310+
;
311+
312+
drop sequence id
313+
;
314+
315+
create sequence id start 1
316+
;
317+
318+
drop table if exists cons_min_outgoing_flow_for_transport_vintage_flows
319+
;
320+
321+
-- This constraint is very similar to cons_min_outgoing_flow_for_transport_flows_without_unit_commitment
322+
-- but it applies to vintage flows instead of regular flows
323+
create table cons_min_outgoing_flow_for_transport_vintage_flows as
324+
with
325+
cte_transport_flow_info as (
326+
select
327+
asset.asset,
328+
coalesce(
329+
(
330+
select
331+
bool_or(flow.is_transport) -- true if any outgoing flow is transport
332+
from
333+
flow
334+
where
335+
flow.from_asset = asset.asset
336+
),
337+
false -- coalescing to false in case there are no outgoing flows
338+
) as outgoing_flows_have_transport_flows,
339+
from
340+
asset
341+
)
342+
select
343+
nextval('id') as id,
344+
t_high.asset as asset,
345+
t_high.year as milestone_year,
346+
asset_both.commission_year as commission_year,
347+
t_high.rep_period,
348+
t_high.time_block_start,
349+
t_high.time_block_end
350+
from
351+
t_highest_out_flows as t_high
352+
left join asset on t_high.asset = asset.asset
353+
left join cte_transport_flow_info on t_high.asset = cte_transport_flow_info.asset
354+
left join asset_both on t_high.asset = asset_both.asset
355+
and t_high.year = asset_both.milestone_year
356+
where
357+
asset.type in ('producer', 'storage', 'conversion')
358+
and asset.investment_method = 'semi-compact'
359+
and cte_transport_flow_info.outgoing_flows_have_transport_flows
360+
-- Note we do not exclude UC here, because UC only guarantees
361+
-- the minimum point of flow, instead of vintage flow
362+
-- For the same reason, we cannot reuse cons_min_outgoing_flow_for_transport_flows_without_unit_commitment
363+
-- directly
307364
;
308365

309366
drop sequence id
@@ -319,20 +376,20 @@ create table cons_min_incoming_flow_for_transport_flows as
319376
-- Similar to the previous query, but for incoming flows
320377
-- Also for assets with unit commitment
321378
with
322-
transport_flow_info as (
379+
cte_transport_flow_info as (
323380
select
324381
asset.asset,
325382
coalesce(
326383
(
327384
select
328-
bool_or(flow.is_transport)
385+
bool_or(flow.is_transport) -- true if any incoming flow is transport
329386
from
330387
flow
331388
where
332389
flow.to_asset = asset.asset
333390
),
334-
false
335-
) as incoming_flows_have_transport_flows,
391+
false -- coalescing to false in case there are no incoming flows
392+
) as incoming_flows_have_transport_flows
336393
from
337394
asset
338395
)
@@ -342,10 +399,11 @@ select
342399
from
343400
t_highest_out_flows as t_high
344401
left join asset on t_high.asset = asset.asset
345-
left join transport_flow_info on t_high.asset = transport_flow_info.asset
402+
left join cte_transport_flow_info on t_high.asset = cte_transport_flow_info.asset
346403
where
347404
asset.type in ('storage', 'conversion')
348-
and transport_flow_info.incoming_flows_have_transport_flows
405+
and cte_transport_flow_info.incoming_flows_have_transport_flows
406+
and asset.investment_method in ('compact', 'simple', 'none')
349407
;
350408

351409
drop sequence id

test/inputs/Multi-year Investments/flow-commission.csv

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ battery,demand,2030,0.0,350.0,,1,1.0
33
wind,demand,2020,0.0,350.0,,1,1.0
44
wind,demand,2030,0.0,350.0,,1,1.0
55
ens,demand,2050,0.0,350.0,,1,1.0
6-
ccgt,demand,2028,1.0,350.0,,1,1.0
76
ccgt,demand,2030,2.0,350.0,100.0,1,1.0
87
ocgt,demand,2030,0.0,350.0,,1,1.0
98
solar,demand,2050,0.0,350.0,,1,1.0

0 commit comments

Comments
 (0)