Reference
TulipaEnergyModel.EnergyProblem
TulipaEnergyModel.ModelParameters
TulipaEnergyModel.ProfileLookup
TulipaEnergyModel.TulipaConstraint
TulipaEnergyModel.TulipaExpression
TulipaEnergyModel.TulipaVariable
TulipaEnergyModel._profile_aggregate
TulipaEnergyModel.add_capacity_constraints!
TulipaEnergyModel.add_consumer_constraints!
TulipaEnergyModel.add_conversion_constraints!
TulipaEnergyModel.add_energy_constraints!
TulipaEnergyModel.add_expression_is_charging_terms_rep_period_constraints!
TulipaEnergyModel.add_expression_terms_over_clustered_year_constraints!
TulipaEnergyModel.add_expression_terms_rep_period_constraints!
TulipaEnergyModel.add_expression_units_on_terms_rep_period_constraints!
TulipaEnergyModel.add_flow_variables!
TulipaEnergyModel.add_group_constraints!
TulipaEnergyModel.add_hub_constraints!
TulipaEnergyModel.add_investment_variables!
TulipaEnergyModel.add_ramping_constraints!
TulipaEnergyModel.add_storage_constraints!
TulipaEnergyModel.add_storage_variables!
TulipaEnergyModel.add_transport_constraints!
TulipaEnergyModel.add_unit_commitment_variables!
TulipaEnergyModel.attach_coefficient!
TulipaEnergyModel.attach_constraint!
TulipaEnergyModel.attach_expression!
TulipaEnergyModel.compute_dual_variables!
TulipaEnergyModel.create_internal_tables!
TulipaEnergyModel.create_model
TulipaEnergyModel.create_model!
TulipaEnergyModel.create_unrolled_partition_tables!
TulipaEnergyModel.default_parameters
TulipaEnergyModel.export_solution_to_csv_files
TulipaEnergyModel.export_solution_to_csv_files
TulipaEnergyModel.read_parameters_from_file
TulipaEnergyModel.run_scenario
TulipaEnergyModel.save_solution!
TulipaEnergyModel.save_solution!
TulipaEnergyModel.solve_model
TulipaEnergyModel.solve_model!
TulipaEnergyModel.EnergyProblem
— TypeEnergyProblem
Structure to hold all parts of an energy problem. It is a wrapper around various other relevant structures. It hides the complexity behind the energy problem, making the usage more friendly, although more verbose.
Fields
db_connection
: A DuckDB connection to the input tables in the model.variables
: A dictionary of TulipaVariables containing the variables of the model.expressions
: A dictionary of TulipaExpressions containing the expressions of the model attached to tables.constraints
: A dictionary of TulipaConstraints containing the constraints of the model.profiles
: Holds the profiles perrep_period
orover_clustered_year
in dictionary format. See ProfileLookup.model_parameters
: A ModelParameters structure to store all the parameters that are exclusive of the model.model
: A JuMP.Model object representing the optimization model.solved
: A boolean indicating whether themodel
has been solved or not.objective_value
: The objective value of the solved problem (Float64).termination_status
: The termination status of the optimization model.
Constructor
EnergyProblem(connection)
: Constructs a newEnergyProblem
object with the given connection.
The constraints_partitions
field is computed from the representative_periods
, and the other fields are initialized with default values.
See the basic example tutorial to see how these can be used.
TulipaEnergyModel.ModelParameters
— TypeModelParameters(;key = value, ...)
ModelParameters(path; ...)
ModelParameters(connection; ...)
ModelParameters(connection, path; ...)
Structure to hold the model parameters. Some values are defined by default and some required explicit definition.
If path
is passed, it is expected to be a string pointing to a TOML file with a key = value
list of parameters. Explicit keyword arguments take precedence.
If connection
is passed, the default discount_year
is set to the minimum of all milestone years. In other words, we check for the table year_data
for the column year
where the column is_milestone
is true. Explicit keyword arguments take precedence.
If both are passed, then path
has preference. Explicit keyword arguments take precedence.
Parameters
discount_rate::Float64 = 0.0
: The model discount rate.discount_year::Int
: The model discount year.
TulipaEnergyModel.ProfileLookup
— TypeStructure to hold the dictionaries of profiles.
TulipaEnergyModel.TulipaConstraint
— TypeStructure to hold the JuMP constraints for the TulipaEnergyModel
TulipaEnergyModel.TulipaExpression
— TypeStructure to hold some JuMP expressions that are not attached to constraints but are attached to a table.
TulipaEnergyModel.TulipaVariable
— TypeStructure to hold the JuMP variables for the TulipaEnergyModel
TulipaEnergyModel._profile_aggregate
— Method_profile_aggregate(profiles, tuple_key, time_block, agg_functions, default_value)
Aggregates the profiles[tuple_key]
over the time_block
using the agg_function
function. If the profile does not exist, uses default_value
instead of each profile value.
profiles
should be a dictionary of profiles, and tuple_key
should be either (profile_name, year, rep_period)
for the profiles of representative periods or (profile_name, year)
for the profiles over clustered years.
If profiles[tuple_key]
exists, then this function computes the aggregation of V = profiles[tuple_key]
over the range time_block
using the aggregator agg_function
, i.e., agg_function(V[time_block])
. If it does not exist, then V[time_block]
is substituted by a vector of the corresponding size and default_value
.
TulipaEnergyModel.add_capacity_constraints!
— Methodadd_capacity_constraints!(connection, model, expressions, constraints, profiles)
Adds the capacity constraints for all asset types to the model
TulipaEnergyModel.add_consumer_constraints!
— Methodadd_consumer_constraints!(connection, model, constraints, profiles)
Adds the consumer asset constraints to the model.
TulipaEnergyModel.add_conversion_constraints!
— Methodaddconversionconstraints!(model, dataframes, Acv, incomingflowlowestresolution, outgoingflowlowestresolution, )
Adds the conversion asset constraints to the model.
TulipaEnergyModel.add_energy_constraints!
— Methodadd_energy_constraints!(connection, model, constraints, profiles)
Adds the energy constraints for assets within the period blocks of the timeframe (inter-temporal) to the model.
TulipaEnergyModel.add_expression_is_charging_terms_rep_period_constraints!
— Methodadd_expression_is_charging_terms_rep_period_constraints!(
cons,
is_charging,
workspace,
)
Computes the is_charging
expressions per row of cons
for the constraints that are within (intra) the representative periods.
This function is only used internally in the model.
This strategy is based on the replies in this discourse thread:
- https://discourse.julialang.org/t/help-improving-the-speed-of-a-dataframes-operation/107615/23
TulipaEnergyModel.add_expression_terms_over_clustered_year_constraints!
— Methodadd_expression_terms_over_clustered_year_constraints!(
connection,
cons,
flow,
profiles;
is_storage_level = false,
)
Computes the incoming and outgoing expressions per row of df_inter for the constraints that are between (inter) the representative periods.
This function is only used internally in the model.
TulipaEnergyModel.add_expression_terms_rep_period_constraints!
— Methodadd_expression_terms_rep_period_constraints!(
connection,
cons,
flow;
use_highest_resolution = true,
multiply_by_duration = true,
add_min_outgoing_flow_duration = false,
)
Computes the incoming and outgoing expressions per row of cons
for the constraints that are within (intra) the representative periods.
This function is only used internally in the model.
This strategy is based on the replies in this discourse thread:
- https://discourse.julialang.org/t/help-improving-the-speed-of-a-dataframes-operation/107615/23
Implementation
This expression computation uses a workspace to store all variables defined for each timestep. The idea of this algorithm is to append all variables defined at time timestep
in workspace[timestep]
and then aggregate then for the constraint time block.
The algorithm works like this:
- Loop over each group of (asset, year, rep_period)
1.1. Loop over each variable in the group: (varidx, vartimeblockstart, vartimeblockend) 1.1.1. Loop over each timestep in vartimeblockstart:vartimeblockend 1.1.1.1. Compute the coefficient of the variable based on the repperiod resolution and the variable efficiency 1.1.1.2. Store (varidx, coefficient) in workspace[timestep] 1.2. Loop over each constraint in the group: (considx, constimeblockstart, constimeblockend) 1.2.1. Aggregate all variables in workspace[timestep] for timestep in the time block to create a list of variable indices and their coefficients [(var_idx1, coef1), ...] 1.2.2. Compute the expression using the variable container, the indices and coefficients
Notes:
- On step 1.2.1, the aggregation can be either by uniqueness of not, i.e., if the variable happens in more that one
workspace[timestep]
, should we add up the coefficients or not. This is defined by the keyword
multiply_by_duration
TulipaEnergyModel.add_expression_units_on_terms_rep_period_constraints!
— Methodadd_expression_units_on_terms_rep_period_constraints!(
cons,
units_on,
workspace,
)
Computes the units_on
expressions per row of cons
for the constraints that are within (intra) the representative periods.
This function is only used internally in the model.
This strategy is based on the replies in this discourse thread:
- https://discourse.julialang.org/t/help-improving-the-speed-of-a-dataframes-operation/107615/23
TulipaEnergyModel.add_flow_variables!
— Methodadd_flow_variables!(connection, model, variables)
Adds flow variables to the optimization model
based on data from the variables
. The flow variables are created using the @variable
macro for each row in the :flows
dataframe.
TulipaEnergyModel.add_group_constraints!
— Methodadd_group_constraints!(connection, model, ...)
Adds group constraints for assets that share a common limits or bounds
TulipaEnergyModel.add_hub_constraints!
— Methodadd_hub_constraints!(model, constraints)
Adds the hub asset constraints to the model.
TulipaEnergyModel.add_investment_variables!
— Methodadd_investment_variables!(model, variables)
Adds investment, decommission, and energy-related variables to the optimization model
, and sets integer constraints on selected variables based on the input data.
TulipaEnergyModel.add_ramping_constraints!
— Methodadd_ramping_and_unit_commitment_constraints!(
connection,
model,
variables,
expressions,
constraints,
profiles
)
Adds the ramping constraints for producer and conversion assets where ramping = true in assets_data
TulipaEnergyModel.add_storage_constraints!
— Methodadd_storage_constraints!(connection, model, variables, expressions, constraints, profiles)
Adds the storage asset constraints to the model.
TulipaEnergyModel.add_storage_variables!
— Methodadd_storage_variables!(connection, model, variables)
Adds storage-related variables to the optimization model
, including storage levels for both intra-representative periods and inter-representative periods, as well as charging state variables. The function also optionally sets binary constraints for certain charging variables based on storage methods.
TulipaEnergyModel.add_transport_constraints!
— Methodadd_transport_constraints!(connection, model, variables, expressions, constraints, profiles)
Adds the transport flow constraints to the model.
TulipaEnergyModel.add_unit_commitment_variables!
— Methodadd_unit_commitment_variables!(model, variables)
Adds unit commitment variables to the optimization model
based on the :units_on
indices. Additionally, variables are constrained to be integers based on the unit_commitment_integer
property.
TulipaEnergyModel.attach_coefficient!
— Methodattach_coefficient!(cons, name, container)
Attach a coefficient named name
stored in container
. This checks that the container
length matches the stored indices
number of rows.
TulipaEnergyModel.attach_constraint!
— Methodattach_constraint!(model, cons, name, container)
Attach a constraint named name
stored in container
, and set model[name] = container
. This checks that the container
length matches the stored indices
number of rows.
TulipaEnergyModel.attach_expression!
— Methodattach_expression!(cons_or_expr, name, container)
attach_expression!(model, cons_or_expr, name, container)
Attach a expression named name
stored in container
, and optionally set model[name] = container
. This checks that the container
length matches the stored indices
number of rows.
TulipaEnergyModel.compute_dual_variables!
— Methodcompute_dual_variables!(model)
Compute the dual variables for the given model.
If the model does not have dual variables, this function fixes the discrete variables, optimizes the model, and then computes the dual variables.
Arguments
model
: The model for which to compute the dual variables.
Returns
A named tuple containing the dual variables of selected constraints.
TulipaEnergyModel.create_internal_tables!
— Methodcreate_internal_tables!(connection)
Creates internal tables.
TulipaEnergyModel.create_model!
— Methodcreate_model!(energy_problem; kwargs...)
Create the internal model of an TulipaEnergyModel.EnergyProblem
. Any keyword argument will be passed to the underlyting create_model
.
TulipaEnergyModel.create_model
— Methodmodel = create_model(
connection,
variables,
expressions,
constraints,
profiles,
model_parameters;
write_lp_file = false,
enable_names = true
)
Create the energy model manually. We recommend using create_model!
instead.
TulipaEnergyModel.create_unrolled_partition_tables!
— Methodcreate_unrolled_partition_table!(connection)
Create unrolled partitions tables from existing DuckDB tables, i.e., adds the time block start and end information.
Input
The following tables are expected to exist in the connection
, containing the partition of some, or all, assets or flows, with their respective time information.
assets_rep_periods_partitions
flows_rep_periods_partitions
assets_timeframe_partitions
Output
The generated tables are the unrolled version of the tables above. It transforms each row in (possibly) multiple rows. The columns specification
and partition
are used to determine the time blocks, and are replaced by columns time_block_start
and time_block_end
.
asset_time_resolution_rep_period
flow_time_resolution_rep_period
asset_time_resolution_over_clustered_year
TulipaEnergyModel.default_parameters
— Methoddefault_parameters(Val(optimizer_name_symbol))
default_parameters(optimizer)
default_parameters(optimizer_name_symbol)
default_parameters(optimizer_name_string)
Returns the default parameters for a given JuMP optimizer. Falls back to Dict()
for undefined solvers.
Arguments
There are four ways to use this function:
Val(optimizer_name_symbol)
: This uses type dispatch with the specialVal
type. Pass the solver name as a Symbol (e.g.,Val(:HiGHS)
).optimizer
: The JuMP optimizer type (e.g.,HiGHS.Optimizer
).optimizer_name_symbol
oroptimizer_name_string
: Pass the name in Symbol or String format and it will be converted toVal
.
Using Val
is necessary for the dispatch. All other cases will convert the argument and call the Val
version, which might lead to type instability.
Examples
using HiGHS
default_parameters(HiGHS.Optimizer)
# output
Dict{String, Any} with 1 entry:
"output_flag" => false
Another case
default_parameters(Val(:Cbc))
# output
Dict{String, Any} with 1 entry:
"logLevel" => 0
default_parameters(:Cbc) == default_parameters("Cbc") == default_parameters(Val(:Cbc))
# output
true
TulipaEnergyModel.export_solution_to_csv_files
— Methodexport_solution_to_csv_files(output_file, connection, variables, constraints)
Saves the solution in CSV files inside output_folder
. Notice that this assumes that the solution has been computed by save_solution!
.
TulipaEnergyModel.export_solution_to_csv_files
— Methodexport_solution_to_csv_files(output_folder, energy_problem)
Saves the solution from energy_problem
in CSV files inside output_file
. Notice that this assumes that the solution has been computed by save_solution!
.
TulipaEnergyModel.read_parameters_from_file
— Methodread_parameters_from_file(filepath)
Parse the parameters from a file into a dictionary. The keys and values are NOT checked to be valid parameters for any specific solvers.
The file should contain a list of lines of the following type:
key = value
The file is parsed as TOML, which is intuitive. See the example below.
Example
# Creating file
filepath, io = mktemp()
println(io,
"""
true_or_false = true
integer_number = 5
real_number1 = 3.14
big_number = 6.66E06
small_number = 1e-8
string = "something"
"""
)
close(io)
# Reading
read_parameters_from_file(filepath)
# output
Dict{String, Any} with 6 entries:
"string" => "something"
"integer_number" => 5
"small_number" => 1.0e-8
"true_or_false" => true
"real_number1" => 3.14
"big_number" => 6.66e6
TulipaEnergyModel.run_scenario
— Methodenergy_problem = run_scenario(connection; optimizer, parameters, write_lp_file, log_file, show_log)
Run the scenario in the given connection
and return the energy problem.
The optimizer
and parameters
keyword arguments can be used to change the optimizer (the default is HiGHS) and its parameters. The variables are passed to the solve_model
function.
Set write_lp_file = true
to export the problem that is sent to the solver to a file for viewing. Set enable_names = false
to turn off variable and constraint names (faster model creation). Set show_log = false
to silence printing the log while running. Specify a log_file
name to export the log to a file.
TulipaEnergyModel.save_solution!
— Methodsave_solution!(connection, model, variables, constraints; compute_duals = true)
Saves the primal and dual variables values, in the following way:
- For each variable in
variables
, get the solution value and save it in a
column named solution
in the corresponding dataset.
- For each constraint in
constraints
, get the dual of each attached
constraint listed in constraint.constraint_names
and save it to the dictionary constraint.duals
with the key given by the name.
Notice that the duals are only computed if compute_duals
is true.
TulipaEnergyModel.save_solution!
— Methodsave_solution!(energy_problem; compute_duals = true)
TulipaEnergyModel.solve_model
— Functionsolve_model(model[, optimizer; parameters])
Solve the JuMP model. The optimizer
argument should be an MILP solver from the JuMP list of supported solvers. By default we use HiGHS.
The keyword argument parameters
should be passed as a list of key => value
pairs. These can be created manually, obtained using default_parameters
, or read from a file using read_parameters_from_file
.
Examples
parameters = Dict{String,Any}("presolve" => "on", "time_limit" => 60.0, "output_flag" => true)
solve_model(model, HiGHS.Optimizer; parameters = parameters)
TulipaEnergyModel.solve_model!
— Functionsolve_model!(energy_problem[, optimizer; parameters, save_solution = true])
Solve the internal model of an energy_problem
. If save_solution
, then the solution and dual variables are computed and saved by save_solution!
.