Skip to content

Commit

Permalink
Store a table name inside TulipaVariable and TulipaConstraint
Browse files Browse the repository at this point in the history
With the table_name, we use a different constructor, based only on
the connection and table name.
  • Loading branch information
abelsiqueira committed Dec 6, 2024
1 parent f6b1613 commit 8a8e51f
Show file tree
Hide file tree
Showing 5 changed files with 393 additions and 356 deletions.
306 changes: 157 additions & 149 deletions src/constraints/create.jl
Original file line number Diff line number Diff line change
@@ -1,174 +1,182 @@
export compute_constraints_indices

function compute_constraints_indices(connection)
constraints = Dict{Symbol,TulipaConstraint}()
# TODO: Format SQL queries consistently (is there a way to add a linter/formatter?)
_create_constraints_tables(connection)

constraints[:lowest] = TulipaConstraint(
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
SELECT
nextval('id') AS index,
asset.asset,
t_low.year,
t_low.rep_period,
t_low.time_block_start,
t_low.time_block_end,
FROM t_lowest_all_flows AS t_low
LEFT JOIN asset
ON t_low.asset = asset.asset
WHERE
asset.type in ('conversion', 'producer')
ORDER BY
asset.asset,
t_low.year,
t_low.rep_period,
t_low.time_block_start
",
) |> DataFrame,
constraints = Dict{Symbol,TulipaConstraint}(
key => TulipaConstraint(connection, "cons_$key") for key in (
:lowest,
:highest_in_out,
:highest_in,
:highest_out,
:units_on_and_outflows,
:storage_level_intra_rp,
:storage_level_inter_rp,
:min_energy_inter_rp,
:max_energy_inter_rp,
)
)

constraints[:highest_in_out] = TulipaConstraint(
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_all_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('hub', 'consumer')",
) |> DataFrame,
return constraints
end

function _create_constraints_tables(connection)
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE cons_lowest AS
SELECT
nextval('id') AS index,
asset.asset,
t_low.year,
t_low.rep_period,
t_low.time_block_start,
t_low.time_block_end,
FROM t_lowest_all_flows AS t_low
LEFT JOIN asset
ON t_low.asset = asset.asset
WHERE
asset.type in ('conversion', 'producer')
ORDER BY
asset.asset,
t_low.year,
t_low.rep_period,
t_low.time_block_start
",
)

constraints[:highest_in] = TulipaConstraint(
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_in_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('storage')",
) |> DataFrame,
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE cons_highest_in_out AS
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_all_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('hub', 'consumer')",
)

constraints[:highest_out] = TulipaConstraint(
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_out_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('producer', 'storage', 'conversion')",
) |> DataFrame,
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE cons_highest_in AS
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_in_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('storage')",
)

constraints[:units_on_and_outflows] = TulipaConstraint(
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE units_on_and_outflows AS
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_assets_and_out_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('producer', 'conversion')
AND asset.unit_commitment = true;
SELECT * FROM units_on_and_outflows
",
) |> DataFrame,
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE cons_highest_out AS
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_out_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('producer', 'storage', 'conversion')",
)

constraints[:storage_level_intra_rp] = TulipaConstraint(
DuckDB.query(
connection,
"SELECT * FROM storage_level_intra_rp
",
) |> DataFrame,
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE cons_units_on_and_outflows AS
SELECT
nextval('id') AS index,
t_high.*
FROM t_highest_assets_and_out_flows AS t_high
LEFT JOIN asset
ON t_high.asset = asset.asset
LEFT JOIN asset_both
ON t_high.asset = asset_both.asset
AND t_high.year = asset_both.milestone_year
AND t_high.year = asset_both.commission_year
WHERE
asset_both.active = true
AND asset.type in ('producer', 'conversion')
AND asset.unit_commitment = true;
",
)

constraints[:storage_level_inter_rp] = TulipaConstraint(
DuckDB.query(
connection,
"SELECT * FROM storage_level_inter_rp
",
) |> DataFrame,
DuckDB.query(
connection,
"CREATE OR REPLACE TABLE cons_storage_level_intra_rp AS
SELECT * FROM var_storage_level_intra_rp
",
)

constraints[:min_energy_inter_rp] = TulipaConstraint(
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
SELECT
nextval('id') AS index,
attr.asset,
attr.year,
attr.period_block_start,
attr.period_block_end,
FROM asset_timeframe_time_resolution AS attr
LEFT JOIN asset_milestone
ON attr.asset = asset_milestone.asset
AND attr.year = asset_milestone.milestone_year
WHERE
asset_milestone.min_energy_timeframe_partition IS NOT NULL
",
) |> DataFrame,
DuckDB.query(
connection,
"CREATE OR REPLACE TABLE cons_storage_level_inter_rp AS
SELECT * FROM var_storage_level_inter_rp
",
)

DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE cons_min_energy_inter_rp AS
SELECT
nextval('id') AS index,
attr.asset,
attr.year,
attr.period_block_start,
attr.period_block_end,
FROM asset_timeframe_time_resolution AS attr
LEFT JOIN asset_milestone
ON attr.asset = asset_milestone.asset
AND attr.year = asset_milestone.milestone_year
WHERE
asset_milestone.min_energy_timeframe_partition IS NOT NULL
",
)

# a -> any(!ismissing, values(a.max_energy_timeframe_partition)),

constraints[:max_energy_inter_rp] = TulipaConstraint(
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
SELECT
nextval('id') AS index,
attr.asset,
attr.year,
attr.period_block_start,
attr.period_block_end,
FROM asset_timeframe_time_resolution AS attr
LEFT JOIN asset_milestone
ON attr.asset = asset_milestone.asset
AND attr.year = asset_milestone.milestone_year
WHERE
asset_milestone.max_energy_timeframe_partition IS NOT NULL
",
) |> DataFrame,
DuckDB.query(
connection,
"CREATE OR REPLACE TEMP SEQUENCE id START 1;
CREATE OR REPLACE TABLE cons_max_energy_inter_rp AS
SELECT
nextval('id') AS index,
attr.asset,
attr.year,
attr.period_block_start,
attr.period_block_end,
FROM asset_timeframe_time_resolution AS attr
LEFT JOIN asset_milestone
ON attr.asset = asset_milestone.asset
AND attr.year = asset_milestone.milestone_year
WHERE
asset_milestone.max_energy_timeframe_partition IS NOT NULL
",
)

return constraints
return
end
7 changes: 6 additions & 1 deletion src/create-model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function create_model!(energy_problem; kwargs...)
years = energy_problem.years
sets = create_sets(graph, years)
energy_problem.model = @timeit to "create_model" create_model(
energy_problem.db_connection,
graph,
sets,
variables,
Expand Down Expand Up @@ -44,6 +45,7 @@ end
Create the energy model given the `graph`, `representative_periods`, dictionary of `dataframes` (created by [`construct_dataframes`](@ref)), timeframe, and groups.
"""
function create_model(
connection,
graph,
sets,
variables,
Expand All @@ -57,7 +59,10 @@ function create_model(
enable_names = true,
)
# Maximum timestep
Tmax = maximum(last(rp.timesteps) for year in sets.Y for rp in representative_periods[year])
Tmax = only(
row[1] for
row in DuckDB.query(connection, "SELECT MAX(num_timesteps) FROM rep_periods_data")
)

expression_workspace = Vector{JuMP.AffExpr}(undef, Tmax)

Expand Down
19 changes: 15 additions & 4 deletions src/structures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,31 @@ Structure to hold the JuMP variables for the TulipaEnergyModel
"""
mutable struct TulipaVariable
indices::DataFrame
table_name::String
container::Vector{JuMP.VariableRef}
lookup::OrderedDict # TODO: This is probably not type stable so it's only used for strangling

function TulipaVariable(indices, container = JuMP.VariableRef[])
return new(indices, container, Dict())
function TulipaVariable(connection, table_name::String)
return new(
DuckDB.query(connection, "SELECT * FROM $table_name") |> DataFrame,
table_name,
JuMP.VariableRef[],
Dict(),
)
end
end

mutable struct TulipaConstraint
indices::DataFrame
table_name::String
expressions::Dict{Symbol,Vector{JuMP.AffExpr}}

function TulipaConstraint(indices)
return new(indices, Dict())
function TulipaConstraint(connection, table_name::String)
return new(
DuckDB.query(connection, "SELECT * FROM $table_name") |> DataFrame,
table_name,
Dict(),
)
end
end

Expand Down
Loading

0 comments on commit 8a8e51f

Please sign in to comment.