Skip to content

Commit

Permalink
Remove graph dependency from src/constraints/consumer.jl
Browse files Browse the repository at this point in the history
Part of #942
Closes #943
  • Loading branch information
abelsiqueira committed Dec 6, 2024
1 parent 9233ff4 commit f6e89c8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 29 deletions.
72 changes: 51 additions & 21 deletions src/constraints/consumer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,59 @@ add_consumer_constraints!(model,
Adds the consumer asset constraints to the model.
"""

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]
function add_consumer_constraints!(connection, model, constraints)
cons = constraints[:highest_in_out]

# TODO: Store the name of the table in the TulipaConstraint
table = _create_consumer_table(connection, "cons_highest_in_out")

# - Balance constraint (using the lowest temporal resolution)
df = filter(:asset => (Ac), constraints[:highest_in_out].indices; view = true)
model[:consumer_balance] = [
@constraint(
model,
incoming_flow_highest_in_out_resolution[row.index] -
outgoing_flow_highest_in_out_resolution[row.index] -
profile_aggregation(
Statistics.mean,
graph[row.asset].rep_periods_profiles,
row.year,
row.year,
("demand", row.rep_period),
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.time_block_start):$(row.time_block_end)]"
) for row in eachrow(df)
begin
consumer_balance_sense = if ismissing(row.consumer_balance_sense)
MathOptInterface.EqualTo(0.0)
else
MathOptInterface.GreaterThan(0.0)
end
@constraint(
model,
incoming_flow - outgoing_flow - row.demand_agg * row.peak_demand in
consumer_balance_sense,
base_name = "consumer_balance[$(row.asset),$(row.year),$(row.rep_period),$(row.time_block_start):$(row.time_block_end)]"
)
end for (row, incoming_flow, outgoing_flow) in
zip(table, cons.expressions[:incoming], cons.expressions[:outgoing]) if
row.type == "consumer" # The length of the table must be the same as the expressions, so we filter here instead of earlier
]
end

function _create_consumer_table(connection, cons::String)
return DuckDB.query(
connection,
"SELECT
cons.*,
ANY_VALUE(asset.type) AS type,
ANY_VALUE(asset.consumer_balance_sense) AS consumer_balance_sense,
ANY_VALUE(asset_milestone.peak_demand) AS peak_demand,
COALESCE(MEAN(profile.value), 1) AS demand_agg
FROM $cons AS cons
LEFT JOIN asset
ON cons.asset = asset.asset
LEFT JOIN asset_milestone
ON cons.asset = asset_milestone.asset
AND cons.year = asset_milestone.milestone_year
LEFT JOIN assets_profiles
ON cons.asset = assets_profiles.asset
AND cons.year = assets_profiles.commission_year
AND assets_profiles.profile_type = 'demand'
LEFT JOIN profiles_rep_periods AS profile
ON profile.profile_name = assets_profiles.profile_name
AND cons.year = profile.year
AND cons.rep_period = profile.rep_period
AND cons.time_block_start <= profile.timestep
AND profile.timestep <= cons.time_block_end
GROUP BY cons.*
ORDER BY cons.index -- order is important
",
)
end
9 changes: 2 additions & 7 deletions src/create-model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function create_model!(energy_problem; kwargs...)
end

"""
model = create_model(graph, representative_periods, dataframes, timeframe, groups; write_lp_file = false, enable_names = true)
model = create_model(connection, graph, representative_periods, dataframes, timeframe, groups; write_lp_file = false, enable_names = true)
Create the energy model given the `graph`, `representative_periods`, dictionary of `dataframes` (created by [`construct_dataframes`](@ref)), timeframe, and groups.
"""
Expand Down Expand Up @@ -114,12 +114,7 @@ function create_model(

@timeit to "add_energy_constraints!" add_energy_constraints!(model, constraints, graph)

@timeit to "add_consumer_constraints!" add_consumer_constraints!(
model,
constraints,
graph,
sets,
)
@timeit to "add_consumer_constraints!" add_consumer_constraints!(connection, model, constraints)

@timeit to "add_storage_constraints!" add_storage_constraints!(
model,
Expand Down
10 changes: 9 additions & 1 deletion test/test-case-studies.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,16 @@ end
dir = joinpath(INPUT_FOLDER, "Tiny")
connection = DBInterface.connect(DuckDB.DB)
_read_csv_folder(connection, dir)
DuckDB.execute( # Make it infeasible
connection,
"UPDATE asset_milestone
SET peak_demand = -1
WHERE
asset = 'demand'
AND milestone_year = 2030
",
)
energy_problem = EnergyProblem(connection)
energy_problem.graph["demand"].peak_demand[2030] = -1 # make it infeasible
create_model!(energy_problem)
@test_logs (:warn, "Model status different from optimal") solve_model!(energy_problem)
@test energy_problem.termination_status == JuMP.INFEASIBLE
Expand Down

0 comments on commit f6e89c8

Please sign in to comment.