Library

Documentation for SpineOpt.jl.

Contents

Index

Public interface

SpineOpt.@fetchMacro
@fetch x, y, ... = d

Assign mapping of :x and :y in d to x and y respectively

source
SpineOpt.active_stochastic_pathsFunction
active_stochastic_paths(
    m; stochastic_structure::Union{Object,Vector{Object}}, t::Union{TimeSlice,Vector{TimeSlice}}
)

An Array of stochastic paths, where each path is itself an Array of stochastic_scenario Objects.

The paths are obtained as follows.

  1. Start with the stochastic DAG associated to model m.
  2. Remove all the scenarios that are not in the given stochastic_structure.
  3. Remove scenarios that don't overlap the given t.
  4. Return all the paths from root to leaf in the remaining sub-DAG.
source
SpineOpt.add_event_handler!Function
add_event_handler!(fn, m, event)

Add an event handler for given model. event must be a Symbol corresponding to an event. fn must be a function callable with the arguments corresponding to that event. Below is a table of events, arguments, and when do they fire.

eventargumentswhen does it fire
:model_builtmRight after model m is built.
:model_about_to_solvemRight before model m is solved.
:model_solvedmRight after model m is solved.
:window_about_to_solve(m, k)Right before window k for model m is solved.
:window_solved(m, k)Right after window k for model m is solved.
:window_failed(m, k)Right after window k for model m fails to solve.

Example

run_spineopt("sqlite:///path-to-input-db", "sqlite:///path-to-output-db") do m
    add_event_handler!(println, m, :model_built)  # Print the model right after it's built
end
source
SpineOpt.build_model!Function
build_model!(m; log_level)

Build given SpineOpt model:

  • create temporal and stochastic structures
  • add variables
  • add expressions
  • add constraints
  • set objective
  • initialize outputs

Arguments

  • log_level::Int: an integer to control the log level.
source
SpineOpt.connection_flow_indicesFunction
connection_flow_indices(
    connection=anything,
    node=anything,
    direction=anything,
    t=anything
)

A list of NamedTuples corresponding to indices of the connection_flow variable. The keyword arguments act as filters for each dimension.

source
SpineOpt.create_modelFunction
create_model(mip_solver, lp_solver, use_direct_model, use_model_names, add_bridges)

A JuMP.Model extended to be used with SpineOpt. mip_solver and lp_solver are 'optimizer factories' to be passed to JuMP.Model or JuMP.direct_model; use_direct_model is a Bool indicating whether JuMP.Model or JuMP.direct_model should be used. use_model_names is a Bool indicating whether the names in the model should be used. add_bridges is a Bool indicating whether bridges from JuMP to the solver should be added to the model.

source
SpineOpt.generate_forced_outagesFunction
generate_forced_outages(url_in, url_out; <keyword arguments>)

Generate forced outages from the contents of url_in and write them to url_out. At least url_in must point to a valid Spine database. A new Spine database is created at url_out if one doesn't exist.

To generate forced outages for a unit, specify mean_time_to_failure and optionally mean_time_to_repair for that unit as a duration in the input DB.

Parameter out_of_service_count_fix will be written for those units in the output DB holding a time series.

Arguments

  • alternative::String="": if non empty, write results to the given alternative in the output DB.

  • filters::Dict{String,String}=Dict("tool" => "object_activity_control"): a dictionary to specify filters. Possible keys are "tool" and "scenario". Values should be a tool or scenario name in the input DB.

Example

using SpineOpt
m = generate_forced_outages(
    raw"sqlite:///C:\path\to\your\input_db.sqlite", 
    raw"sqlite:///C:\path\to\your\output_db.sqlite"
)
source
SpineOpt.generate_stochastic_structure!Function
generate_stochastic_structure(m::Model)

Generate the stochastic structure for given SpineOpt model.

The stochastic structure is a directed acyclic graph (DAG) where the vertices are the stochastic_scenario objects, and the edges are given by the parent_stochastic_scenario__child_stochastic_scenario relationships.

After this, you can call active_stochastic_paths to slice the generated structure.

source
SpineOpt.node_state_indicesFunction
node_state_indices(filtering_options...)

A set of tuples for indexing the node_state variable where filtering options can be specified for node, s, and t.

source
SpineOpt.prepare_spineoptFunction
prepare_spineopt(url_in; <keyword arguments>)

A SpineOpt model from the contents of url_in - ready to be passed to run_spineopt!. The argument url_in must be either a String pointing to a valid Spine database, or a Dict (e.g. manually created or parsed from a json file).

Arguments

  • log_level
  • upgrade
  • filters
  • templates
  • mip_solver
  • lp_solver
  • use_direct_model
  • use_model_names
  • add_bridges

See run_spineopt for the description of the keyword arguments.

source
SpineOpt.roll_temporal_structure!Function
roll_temporal_structure!(m[, window_number=1]; rev=false)

Roll the temporal structure of given SpineOpt model forward a period of time equal to the value of the roll_forward parameter. If roll_forward is an array, then window_number can be given either as an Integer or a UnitRange indicating the position or successive positions in that array.

If rev is true, then the structure is rolled backwards instead of forward.

source
SpineOpt.run_spineoptFunction
run_spineopt(url_in, url_out; <keyword arguments>)

Run SpineOpt using the contents of url_in and write report(s) to url_out. The argument url_in must be either a String pointing to a valid Spine database, or a Dict (e.g. manually created or parsed from a json file). A new Spine database is created at url_out if one doesn't exist.

Arguments

  • log_level::Int=3: an integer to control the log level.
  • upgrade::Bool=false: whether or not to automatically upgrade the data structure in url_in to latest.
  • filters::Dict{String,String}=Dict("tool" => "object_activity_control"): a dictionary to specify filters. Possible keys are "tool" and "scenario". Values should be a tool or scenario name in the input DB.
  • templates: a collection of templates to load on top of the SpineOpt template. Each template must be a Dict with the same structure as the one returned by SpineOpt.template().
  • mip_solver=nothing: a MIP solver to use if no MIP solver specified in the DB.
  • lp_solver=nothing: a LP solver to use if no LP solver specified in the DB.
  • use_direct_model::Bool=false: whether or not to use JuMP.direct_model to build the Model object.
  • use_model_names::Bool=true: whether or not to use the names in the model.
  • add_bridges::Bool=true whether or not bridges from JuMP to the solver should be added to the model.
  • optimize::Bool=true: whether or not to optimise the model (useful for running tests).
  • update_names::Bool=false: whether or not to update variable and constraint names after the model rolls (expensive).
  • alternative::String="": if non empty, write results to the given alternative in the output DB.
  • write_as_roll::Int=0: if greater than 0 and the run has a rolling horizon, then write results every that many windows.
  • log_file_path::String=nothing: if not nothing, log all console output to a file at the given path. The file is overwritten at each call.
  • resume_file_path::String=nothing: only relevant in rolling horizon optimisations with write_as_roll greater or equal than one. If the file at given path contains resume data from a previous run, start the run from that point. Also, save resume data to that same file as the model rolls and results are written to the output database.

Example

using SpineOpt
m = run_spineopt(
    raw"sqlite:///C:\path\to\your\input_db.sqlite", 
    raw"sqlite:///C:\path\to\your\output_db.sqlite";
    filters=Dict("tool" => "object_activity_control", "scenario" => "scenario_to_run"),
    alternative="alternative_to_write_results"
)
source
run_spineopt(f, url_in, url_out; <keyword arguments>)

Same as run_spineopt(url_in, url_out; kwargs...) but call function f with the SpineOpt model as argument right after its creation (but before building and solving it).

This is intended to be called using do block syntax.

run_spineopt(url_in, url_out) do m
    # Do something with m after its creation
end  # Building and solving begins after quiting this block
source
SpineOpt.run_spineopt!Function
run_spineopt!(m, url_out; <keyword arguments>)

Build SpineOpt on the given m and solve it; write report(s) to url_out. A new Spine database is created at url_out if one doesn't exist.

Arguments

  • log_level
  • optimize
  • update_names
  • alternative
  • write_as_roll
  • log_file_path
  • resume_file_path

See run_spineopt for the description of the keyword arguments.

source
SpineOpt.solve_model!Function
solve_model!(m; <keyword arguments>)

Solve given SpineOpt model and save outputs.

Arguments

  • log_level::Int=3: an integer to control the log level.
  • update_names::Bool=false: whether or not to update variable and constraint names after the model rolls (expensive).
  • write_as_roll::Int=0: if greater than 0 and the run has a rolling horizon, then write results every that many windows.
  • resume_file_path::String=nothing: only relevant in rolling horizon optimisations with write_as_roll greater or equal than one. If the file at given path contains resume data from a previous run, start the run from that point. Also, save resume data to that same file as the model rolls and results are written to the output database.
  • calculate_duals::Bool=false: whether or not to calculate duals after the model solve.
  • output_suffix::NamedTuple=(;): to add to the outputs.
  • log_prefix::String="": to prepend to log messages.
source
SpineOpt.SpineOptExtType
SpineOptExt

The struct storing SpineOpt data inside <JuMP.Model>.ext[:spineopt].

You can inspect the fields via the following promt:

julia> fieldnames(SpineOptExt)
source
SpineOpt.t_before_tFunction
t_before_t(m; t_before=anything, t_after=anything)

An Array where each element is a Tuple of two consecutive TimeSlices in model m, i.e., the second starting when the first ends.

Arguments

  • t_before: if given, return an Array of TimeSlices that start when t_before ends.
  • t_after: if given, return an Array of TimeSlices that end when t_after starts.
source
SpineOpt.t_in_tFunction
t_in_t(m; t_short=anything, t_long=anything)

An Array where each element is a Tuple of two TimeSlices in model m, the second containing the first.

Keyword arguments

  • t_short: if given, return an Array of TimeSlices that contain t_short.
  • t_long: if given, return an Array of TimeSlices that are contained in t_long.
source
SpineOpt.t_in_t_exclFunction
t_in_t_excl(m; t_short=anything, t_long=anything)

Same as t_in_t but exclude tuples of the same TimeSlice.

Keyword arguments

  • t_short: if given, return an Array of TimeSlices that contain t_short (other than t_short itself).
  • t_long: if given, return an Array of TimeSlices that are contained in t_long (other than t_long itself).
source
SpineOpt.t_overlaps_tFunction
t_overlaps_t(m; t)

An Array of TimeSlices in model m that overlap the given t, where t must be in m.

source
SpineOpt.time_sliceFunction
time_slice(m; temporal_block=anything, t=anything)

An Array of TimeSlices in model m.

Arguments

  • temporal_block::Union{Object,Vector{Object}}: only return TimeSlices in these blocks.
  • t::Union{TimeSlice,Vector{TimeSlice}}: only return TimeSlices that are also in this collection.
source
SpineOpt.to_time_sliceFunction
to_time_slice(m; t)

An Array of TimeSlices in model m overlapping the given TimeSlice (where t may not be in m).

source
SpineOpt.unit_flow_indicesFunction
unit_flow_indices(
    unit=anything,
    node=anything,
    direction=anything,
    s=anything
    t=anything
)

A list of NamedTuples corresponding to indices of the unit_flow variable where the keyword arguments act as filters for each dimension.

source
SpineOpt.unit_flow_op_indicesFunction
unit_flow_op_indices(
    unit=anything,
    node=anything,
    direction=anything,
    operating_point=anything,
    s=anything
    t=anything
)

A list of NamedTuples corresponding to indices of the unit_flow variable. The keyword arguments act as filters for each dimension.

source
SpineOpt.units_invested_available_indicesFunction
units_invested_available_indices(unit=anything, t=anything)

A list of NamedTuples corresponding to indices of the units_invested_available variable where the keyword arguments act as filters for each dimension.

source
SpineOpt.units_on_indicesFunction
units_on_indices(unit=anything, stochastic_scenario=anything, t=anything)

A list of NamedTuples corresponding to indices of the units_on variable where the keyword arguments act as filters for each dimension.

source
SpineOpt.upgrade_dbFunction
upgrade_db(url_in; log_level=3, version=nothing, force::Bool=false)

Upgrade the data structure in url_in to latest.

The version (Int) keyword forces the migration to start at a specific number if given, while force=true suppresses some errors and warnings in migration to try and force output.

source
SpineOpt.write_reportFunction
write_report(m, url_out; <keyword arguments>)

Write report(s) from given SpineOpt model to url_out. A new Spine database is created at url_out if one doesn't exist.

Arguments

  • alternative::String="": if non empty, write results to the given alternative in the output DB.

  • log_level::Int=3: an integer to control the log level.

source
SpineOpt.write_report_from_intermediate_resultsFunction
write_report_from_intermediate_results(intermediate_results_folder, default_url; <keyword arguments>)

Collect results generated on a previous, unsuccessful SpineOpt run from intermediate_results_folder, and write the corresponding report(s) to url_out. A new Spine database is created at url_out if one doesn't exist.

Arguments

  • alternative::String="": if non empty, write results to the given alternative in the output DB.

  • log_level::Int=3: an integer to control the log level.

source

Internals

SpineOpt.add_expression_capacity_margin!Function
add_expression_capacity_margin!(m::Model)

Create an expression for capacity_margin. This represents the available production capacity (considering variations in variable renewables) after demand has been fulfilled and after the contribution of actual storage operation has been taken into account. It is used in the minimum capacity margin constraint

\[\begin{aligned} expr^{capacity\_margin}_{n,s,t} = \\ & + \sum_{u\in{U_{n\_to}}}(p^{capacity\_per\_unit}_{u,s,t} \cdot p^{availability\_factor}_{u,s,t} \cdot v^{units\_available}_{u,s,t}) \\ & + \sum_{u\in{U_{storage_n}}}(v^{unit\_flow}_{u,n,to,s,t}) \\ & - \sum_{u\in{U_{storage_n}}}(v^{unit\_flow}_{u,n,from,s,t}) \\ & - p^{demand}_{n,s,t} \\ & - p^{demand\_fraction}_{n,s,t} \cdot p^{group\_demand}_{n_{group},s,t} \\ & \forall n \in node: p^{capacity\_margin\_min} \\ \end{aligned}\]

where math U_{storage_n} is the set of all storage units connected to node n and math U_{n\_to} is the set of all non-storage units connected to node n

See also capacity_margin_min, capacity_margin_penalty, node__to_unit, unit__to_node, demand, demand_fraction, storage_active

source
SpineInterface.indicesFunction
indices(p::Parameter, [c::EntityClass]; kwargs...)

An iterator over all objects and relationships where the value of p is different than nothing.

Arguments

  • For each object class where p is defined, there is a keyword argument named after it; similarly, for each relationship class where p is defined, there is a keyword argument named after each object class in it. The purpose of these arguments is to filter the result by an object or list of objects of an specific class, or to accept all objects of that class by specifying anything for the corresponding argument.

Examples

julia> using SpineInterface;


julia> url = "sqlite:///" * joinpath(dirname(pathof(SpineInterface)), "..", "examples/data/example.sqlite");


julia> using_spinedb(url)


julia> collect(indices(tax_net_flow))
1-element Vector{@NamedTuple{node::Object, commodity::Object}}:
 (node = Sthlm, commodity = water)

julia> collect(indices(demand))
5-element Vector{Object}:
 Dublin
 Espoo
 Leuven
 Nimes
 Sthlm
source