Skip to content

Commit

Permalink
Create constraints with new TulipaConstraint object (#928)
Browse files Browse the repository at this point in the history
* Create constraints with new TulipaConstraint object

Update highest resolution table computation to use union tables and move highest_... out of dataframes
Create TulipaConstraint structure.
Instead of incoming and outgoing expressions, create a dictionary of
expressions inside TulipaConstraint.
This is necessary at the moment because some additional expressions were
being created in addition to incoming_flow and outgoing_flow.
Create TulipaConstraint objects for all other constraints, including the
ones that are copies of variables.
Remove the dataframes variable completely.
Clean up add_..._constraints signatures and related places

* Remove file time-resolution

* Rename add_expressions_to_dataframe

* Better document the lowest resolution computation
  • Loading branch information
abelsiqueira authored Dec 4, 2024
1 parent 0b6b646 commit f7440b9
Show file tree
Hide file tree
Showing 21 changed files with 538 additions and 994 deletions.
1 change: 0 additions & 1 deletion src/TulipaEnergyModel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const to = TimerOutput()

# Definitions and auxiliary files
include("utils.jl")
include("time-resolution.jl")
include("run-scenario.jl")
include("model-parameters.jl")
include("structures.jl")
Expand Down
103 changes: 57 additions & 46 deletions src/constraints/capacity.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,7 @@ add_capacity_constraints!(model, graph,...)
Adds the capacity constraints for all asset types to the model
"""

function add_capacity_constraints!(
model,
graph,
dataframes,
sets,
variables,
accumulated_initial_units,
accumulated_investment_units_using_simple_method,
accumulated_units,
accumulated_units_compact_method,
outgoing_flow_highest_out_resolution,
incoming_flow_highest_in_resolution,
)
function add_capacity_constraints!(model, variables, constraints, graph, sets)
## unpack from sets
Acv = sets[:Acv]
Ai = sets[:Ai]
Expand All @@ -34,10 +22,21 @@ function add_capacity_constraints!(
sets[:decommissionable_assets_using_compact_method]
decommissionable_assets_using_simple_method = sets[:decommissionable_assets_using_simple_method]

## unpack from model
accumulated_initial_units = model[:accumulated_initial_units]
accumulated_investment_units_using_simple_method =
model[:accumulated_investment_units_using_simple_method]
accumulated_units = model[:accumulated_units]
accumulated_units_compact_method = model[:accumulated_units_compact_method]

## unpack from variables
flows_indices = variables[:flow].indices
flow = variables[:flow].container

## unpack from constraints
incoming_flow_highest_in_resolution = constraints[:highest_in].expressions[:incoming]
outgoing_flow_highest_out_resolution = constraints[:highest_out].expressions[:outgoing]

## Expressions used by capacity constraints
# - Create capacity limit for outgoing flows
assets_profile_times_capacity_out =
Expand All @@ -52,7 +51,7 @@ function add_capacity_constraints!(
row.year,
v,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) *
accumulated_units_compact_method[accumulated_set_using_compact_method_lookup[(
Expand All @@ -72,13 +71,13 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) *
graph[row.asset].capacity *
accumulated_units[accumulated_units_lookup[(row.asset, row.year)]]
)
end for row in eachrow(dataframes[:highest_out])
end for row in eachrow(constraints[:highest_out].indices)
]

# - Create accumulated investment limit for the use of binary storage method with investments
Expand All @@ -100,14 +99,14 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) *
(
graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year] +
accumulated_investment_limit[row.year, row.asset]
) *
(1 - row.is_charging)
(1 - is_charging)
)
else
@expression(
Expand All @@ -118,13 +117,16 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) *
(graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year]) *
(1 - row.is_charging)
(1 - is_charging)
)
end for row in eachrow(dataframes[:highest_out])
end for (row, is_charging) in zip(
eachrow(constraints[:highest_out].indices),
constraints[:highest_out].expressions[:is_charging],
)
]

assets_profile_times_capacity_out_with_binary_part2 =
Expand All @@ -138,16 +140,19 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) * (
graph[row.asset].capacity * (
accumulated_initial_units[row.asset, row.year] * (1 - row.is_charging) +
accumulated_initial_units[row.asset, row.year] * (1 - is_charging) +
accumulated_investment_units_using_simple_method[row.asset, row.year]
)
)
)
end for row in eachrow(dataframes[:highest_out])
end for (row, is_charging) in zip(
eachrow(constraints[:highest_out].indices),
constraints[:highest_out].expressions[:is_charging],
)
]

# - Create capacity limit for incoming flows
Expand All @@ -161,12 +166,12 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) *
graph[row.asset].capacity *
accumulated_units[accumulated_units_lookup[(row.asset, row.year)]]
) for row in eachrow(dataframes[:highest_in])
) for row in eachrow(constraints[:highest_in].indices)
]

# - Create capacity limit for incoming flows with binary is_charging for storage assets
Expand All @@ -181,14 +186,14 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) *
(
graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year] +
accumulated_investment_limit[row.year, row.asset]
) *
row.is_charging
is_charging
)
else
@expression(
Expand All @@ -199,13 +204,16 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) *
(graph[row.asset].capacity * accumulated_initial_units[row.asset, row.year]) *
row.is_charging
is_charging
)
end for row in eachrow(dataframes[:highest_in])
end for (row, is_charging) in zip(
eachrow(constraints[:highest_in].indices),
constraints[:highest_in].expressions[:is_charging],
)
]

assets_profile_times_capacity_in_with_binary_part2 =
Expand All @@ -219,16 +227,19 @@ function add_capacity_constraints!(
row.year,
row.year,
("availability", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) * (
graph[row.asset].capacity * (
accumulated_initial_units[row.asset, row.year] * row.is_charging +
accumulated_initial_units[row.asset, row.year] * is_charging +
accumulated_investment_units_using_simple_method[row.asset, row.year]
)
)
)
end for row in eachrow(dataframes[:highest_in])
end for (row, is_charging) in zip(
eachrow(constraints[:highest_in].indices),
constraints[:highest_in].expressions[:is_charging],
)
]

## Capacity limit constraints (using the highest resolution)
Expand All @@ -238,8 +249,8 @@ function add_capacity_constraints!(
model,
outgoing_flow_highest_out_resolution[row.index]
assets_profile_times_capacity_out[row.index],
base_name = "max_output_flows_limit[$(row.asset),$(row.year),$(row.rep_period),$(row.timesteps_block)]"
) for row in eachrow(dataframes[:highest_out]) if
base_name = "max_output_flows_limit[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(constraints[:highest_out].indices) if
outgoing_flow_highest_out_resolution[row.index] != 0
]

Expand All @@ -249,8 +260,8 @@ function add_capacity_constraints!(
model,
incoming_flow_highest_in_resolution[row.index]
assets_profile_times_capacity_in[row.index],
base_name = "max_input_flows_limit[$(row.asset),$(row.rep_period),$(row.timesteps_block)]"
) for row in eachrow(dataframes[:highest_in]) if
base_name = "max_input_flows_limit[$(row.asset),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(constraints[:highest_in].indices) if
incoming_flow_highest_in_resolution[row.index] != 0
]

Expand All @@ -261,8 +272,8 @@ function add_capacity_constraints!(
model,
outgoing_flow_highest_out_resolution[row.index]
assets_profile_times_capacity_out_with_binary_part1[row.index],
base_name = "max_output_flows_limit_with_binary_part1[$(row.asset),$(row.rep_period),$(row.timesteps_block)]"
) for row in eachrow(dataframes[:highest_out]) if
base_name = "max_output_flows_limit_with_binary_part1[$(row.asset),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(constraints[:highest_out].indices) if
row.asset Asb && outgoing_flow_highest_out_resolution[row.index] != 0
]

Expand All @@ -271,8 +282,8 @@ function add_capacity_constraints!(
model,
outgoing_flow_highest_out_resolution[row.index]
assets_profile_times_capacity_out_with_binary_part2[row.index],
base_name = "max_output_flows_limit_with_binary_part2[$(row.asset),$(row.rep_period),$(row.timesteps_block)]"
) for row in eachrow(dataframes[:highest_out]) if row.asset Ai[row.year] &&
base_name = "max_output_flows_limit_with_binary_part2[$(row.asset),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(constraints[:highest_out].indices) if row.asset Ai[row.year] &&
row.asset Asb &&
outgoing_flow_highest_out_resolution[row.index] != 0
]
Expand All @@ -283,17 +294,17 @@ function add_capacity_constraints!(
model,
incoming_flow_highest_in_resolution[row.index]
assets_profile_times_capacity_in_with_binary_part1[row.index],
base_name = "max_input_flows_limit_with_binary_part1[$(row.asset),$(row.rep_period),$(row.timesteps_block)]"
) for row in eachrow(dataframes[:highest_in]) if
base_name = "max_input_flows_limit_with_binary_part1[$(row.asset),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(constraints[:highest_in].indices) if
row.asset Asb && incoming_flow_highest_in_resolution[row.index] != 0
]
model[:max_input_flows_limit_with_binary_part2] = [
@constraint(
model,
incoming_flow_highest_in_resolution[row.index]
assets_profile_times_capacity_in_with_binary_part2[row.index],
base_name = "max_input_flows_limit_with_binary_part2[$(row.asset),$(row.rep_period),$(row.timesteps_block)]"
) for row in eachrow(dataframes[:highest_in]) if row.asset Ai[row.year] &&
base_name = "max_input_flows_limit_with_binary_part2[$(row.asset),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(constraints[:highest_in].indices) if row.asset Ai[row.year] &&
row.asset Asb &&
incoming_flow_highest_in_resolution[row.index] != 0
]
Expand Down
18 changes: 7 additions & 11 deletions src/constraints/consumer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,13 @@ add_consumer_constraints!(model,
Adds the consumer asset constraints to the model.
"""

function add_consumer_constraints!(
model,
graph,
dataframes,
sets,
incoming_flow_highest_in_out_resolution,
outgoing_flow_highest_in_out_resolution,
)
function add_consumer_constraints!(model, constraints, graph, sets)
Ac = sets[:Ac]
incoming_flow_highest_in_out_resolution = constraints[:highest_in_out].expressions[:incoming]
outgoing_flow_highest_in_out_resolution = constraints[:highest_in_out].expressions[:outgoing]

# - Balance constraint (using the lowest temporal resolution)
df = filter(:asset => (Ac), dataframes[:highest_in_out]; view = true)
df = filter(:asset => (Ac), constraints[:highest_in_out].indices; view = true)
model[:consumer_balance] = [
@constraint(
model,
Expand All @@ -34,11 +30,11 @@ function add_consumer_constraints!(
row.year,
row.year,
("demand", row.rep_period),
row.timesteps_block,
row.time_block_start:row.time_block_end,
1.0,
) * graph[row.asset].peak_demand[row.year] in
graph[row.asset].consumer_balance_sense,
base_name = "consumer_balance[$(row.asset),$(row.year),$(row.rep_period),$(row.timesteps_block)]"
base_name = "consumer_balance[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(df)
]
end
17 changes: 6 additions & 11 deletions src/constraints/conversion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,17 @@ add_conversion_constraints!(model,
Adds the conversion asset constraints to the model.
"""

function add_conversion_constraints!(
model,
dataframes,
sets,
incoming_flow_lowest_resolution,
outgoing_flow_lowest_resolution,
)
function add_conversion_constraints!(model, constraints, sets)
Acv = sets[:Acv]
# - Balance constraint (using the lowest temporal resolution)
df = filter(:asset => (Acv), dataframes[:lowest]; view = true)
df = filter(:asset => (Acv), constraints[:lowest].indices; view = true)
incoming = constraints[:lowest].expressions[:incoming]
outgoing = constraints[:lowest].expressions[:outgoing]
model[:conversion_balance] = [
@constraint(
model,
incoming_flow_lowest_resolution[row.index] ==
outgoing_flow_lowest_resolution[row.index],
base_name = "conversion_balance[$(row.asset),$(row.year),$(row.rep_period),$(row.timesteps_block)]"
incoming[row.index] == outgoing[row.index],
base_name = "conversion_balance[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
) for row in eachrow(df)
]
end
Loading

0 comments on commit f7440b9

Please sign in to comment.