Basics of the model structure
In SpineOpt.jl, the model structure is generated based on the input data, allowing it to be used for a multitude of different problems. Here, we aim to provide you with a basic understanding of the SpineOpt.jl model and data structure, while the Object Classes, Relationship Classes, Parameters, and Parameter Value Lists sections provide more in-depth explanations of each concept.
Introduction to object classes
Essentially, Object Classes represents different types of objects
or entities that make up the model. For example, every power plant in the model is represented as an object
of the object class
unit, every power line as an object
of the object class
connection, and so forth. In order to add any new entity to a model, a new object
has to be added to desired object class
in the input data.
Each object class
has a very specific purpose in SpineOpt.jl, so understanding their differences is key. The Object Classes can be roughly divided into three distinctive groups, namely Systemic object classes, Structural object classes, and Meta object classes.
Systemic object classes
As the name implies, system Object Classes are used to describe the system to be modelled. Essentially, they define what you want to model. These include:
- commodity represents different goods to be generated, consumed, transported, etc.
- connection handles the transfer of
commodities
betweennodes
. - node ensures the balance of the commodity flows, and can be used to store
commodities
as well. - unit handles the generation and consumption of
commodities
.
Structural object classes
Structural Object Classes are used to define the temporal and stochastic structure of the modelled problem, as well as custom User Constraints. Unlike the above system Object Classes, the structural Object Classes are more about how you want to model, instead of strictly what you want to model. These include:
- stochastic_scenario represents a different forecast or another type of an alternative time period.
- stochastic_structure acts as a handle for a group of
stochastic_scenarios
with set properties. - temporal_block defines a period of time with the desired temporal resolution.
- user_constraint is an optional custom constraint generated based on the input data.
Meta object classes
Meta Object Classes are used for defining things on the level of models
or above, like model output and even multiple models
for problem decompositions. These include:
- model represents an individual model, grouping together all the things relevant for itself.
- output defines which Variables are output from the model.
- report groups together multiple output
objects
.
Introduction to relationship classes
While Object Classes define all the objects
or entities that make up a model, Relationship Classes define how those entities are related to each other. Thus, Relationship Classes hold no meaning on their own, and always include at least one object class
.
Similar to Object Classes, each relationship class
has a very specific purpose in SpineOpt.jl, and understanding the purpose of each relationship class
is paramount. The Relationship Classes can be roughly divided into Systemic relationship classes, Structural relationship classes, and Meta relationship classes, again similar to Object Classes.
Systemic relationship classes
Systemic Relationship Classes define how Systemic object classes are related to each other, thus helping define the system to be modelled. Most of these relationships deal with which units
and connections
interact with which nodes
, and how those interactions work. This essentially defines the possible commodity flows to be modelled. Systemic Relationship Classes include:
- connection__from_node defines which node the connection can transfer a commodity from.
- connection__to_node defines which node the connection can transfer a commodity to.
- connection__node__node holds Parameters for
connections
between twonodes
. - node__commodity defines which node holds which commodity.
- node__node holds parameters for direct node-node interactions, like diffusion of
commodities
. - unit__commodity defines which commodity the unit handles.
- unit__from_node defines which node the unit can take an input commodity from.
- unit__to_node defines which node the unit can output a commodity to.
- unit__node__node holds parameters for unit interactions between two
nodes
.
Structural relationship classes
Structural Relationship Classes primarily relate Structural object classes to Systemic object classes, defining what structures the individual parts of the system use. These are mostly used to determine the temporal and stochastic structures to be used in different parts of the modelled system, or custom User Constraints.
SpineOpt.jl has a very flexible temporal and stochastic structure, explained in detail in the Temporal Framework and Stochastic Framework sections of the documentation. Unfortunately, this flexibility requires quite a few different structural Relationship Classes, the most important of which are the following basic structural Relationship Classes:
- node__stochastic_structure defines the stochastic_structure used for the node balance.
- node__temporal_block defines the
temporal blocks
used for the node balance. - parent_stochastic_scenario__child_stochastic_scenario defines the stochastic directed acyclic graph (DAG) of the Stochastic Framework.
- stochastic_structure__stochastic_scenario holds parameters for
stochastic scenarios
in the stochastic_structure. - units_on__stochastic_structure defines the stochastic_structure used for the online variable of the unit.
- units_on__temporal_block defines the
temporal blocks
used for the online variable of the unit.
Furthermore, there are also a number of advanced structural Relationship Classes, which are only necessary when using some of the optional features of SpineOpt.jl. For Investment Optimization, the following relationships control the stochastic and temporal structures of the investment variables:
- connection__investment_stochastic_structure defines the stochastic_structure used for the investment Variables for the connection.
- connection__investment_temporal_block defines the
temporal blocks
used for the investment Variables for the connection.user_constraint. - node__investment_stochastic_structure defines the stochastic_structure used for the investment Variables for the node.
- node__investment_temporal_block defines the stochastic_structure used for the investment Variables for the node.
- unit__investment_stochastic_structure defines the stochastic_structure used for the investment Variables for the unit.
- unit__investment_temporal_block defines the
temporal blocks
used for the investment Variables for the unit.(@ref).
For User Constraints, which are essentially generic data-driven custom constraints, the following relationships are used to control which variables are included and with what coefficients:
- connection__from_node__user_constraint holds Parameters for the connection_flow variable from the node in question in the custom user_constraint.
- connection__to_node__user_constraint holds Parameters for the connection_flow variable to the node in question in the custom user_constraint.
- node__user_constraint holds Parameters for the node_state variable in the custom user_constraint.
- unit__from_node__user_constraint holds Parameters for the unit_flow variable from the node in question in the custom user_constraint.
- unit__to_node__user_constraint holds Parameters for the unit_flow variable to the node in question in the custom user_constraint.
Meta relationship classes
Meta Relationship Classes are used for defining model-level settings, like which temporal blocks
or stochastic structures
are active, and what the model output is. These include:
- model__default_investment_stochastic_structure defines a default stochastic_structure to be used for investment Variables when no other definitions exist.
- model__default_investment_temporal_block defines a default temporal_block to be used for investment Variables when no other definitions exist.
- model__default_stochastic_structure defines a default stochastic_structure to be used for
nodes
andunits
when no other definitions exist. - model__default_temporal_block defines a default temporal_block to be used for
nodes
andunits
when no other definitions exist. - model__report connects each report to the desired model.
- model__stochastic_structure defines which
stochastic structures
are active in whichmodels
. - model__temporal_block defines which
temporal blocks
are active in whichmodels
. - report__output defines which
outputs
are part of which report.
Introduction to parameters
While the primary function of Object Classes and Relationship Classes is to define the system to be modelled and it's structure, Parameters exist to constrain them. Every parameter
is attributed to at least one object class
or relationship class
, but some appear in many classes whenever they serve a similar purpose.
Parameters accept different types of values depending on their purpose, e.g. whether they act as a flag for some specific functionality or appear as a coefficient in Constraints, so understanding each parameter
is key. Most coefficient-type Parameters accept constant, time series, and even stochastic time series form input, but there are some exceptions. Most flag-type Parameters, on the other hand, have a restricted list of acceptable values defined by their Parameter Value Lists.
The existence of some Constraints is controlled based on if the relevant Parameters are defined. As a rule-of-thumb, a constraint
only gets generated if at least one of the Parameters appearing in it is defined, but one should refer to the appropriate Constraints and Parameters sections when in doubt.
Introduction to groups of objects
Groups of objects are used within SpineOpt for different purposes. To create a group of objects, simply right-click the corresponding Object Class in the Spine Toolbox database editor and select Add object group
. Groups are essentially special objects
, that act as a single handle for all of its members.
On the one hand, groups can be used in order to impose constraints on the aggregation of a variable, e.g. on the sum of multiple unit_flow variables. Constraints based on parameters associated with the unit__node__node, unit__to_node, unit__from_node, connection__node__node, connection__to_node, connection__from_node can generally be used for this kind of flow aggregation by defining the parameters on groups of objects, typically node groups. (with the exception of variable fixing parameters, e.g. fix_unit_flow, fix_connection_flow etc.). See for instance constraint_unit_flow_capacity.
On the other hand, a node group can be used to for PTDF based powerflows. Here a node group is used to enforce a nodal balance on system level, while suppressing the node balances at individual nodes. See also balance_type and the node balance constraint.