Simple System tutorial

Welcome to Spine Toolbox's Simple System tutorial.

This tutorial provides a step-by-step guide to setup a simple energy system with Spine Toolbox for SpineOpt. Spine Toolbox is used to create a workflow with databases and tools and SpineOpt is the tool that simulates/optimizes the energy system.

Info

If you haven't yet installed the tools or you are not sure whether you have the latest version, please follow the installation/upgrade guides:

About the simple system

In the simple system:

  • Two power plants take fuel from a source node and release electricity to another node in order to supply a demand.
  • Power plant 'a' has a capacity of 100 MWh, a variable operating cost of 25 euro/fuel unit, and generates 0.7 MWh of electricity per unit of fuel.
  • Power plant 'b' has a capacity of 200 MWh, a variable operating cost of 50 euro/fuel unit, and generates 0.8 MWh of electricity per unit of fuel.
  • The demand at the electricity node is 150 MWh.
  • The fuel node is able to provide infinite energy.

image

Spine Toolbox workflow

The workflow for this tutorial is quite simple: A SpineOpt tool that reads data from an input database, executes the simulation/optimization and writes the results to an output database.

To create the workflow, it is almost as simple as dragging these items (i.e. Data Store and Run SpineOpt) to the Design View and connecting them by dragging arrows between the blocks but there are some things that need to be configured:

  • The databases need to be initialised. Once you select a database you see the properties panel. Select the dialect of the database. Here we choose sqlite. Then press the button 'new spine db' to create and save the database on your computer (Spine Toolbox will suggest a good folder).

  • Connecting tools with (yellow) arrows in the Toolbox does not mean that the tools will use these items. The arrows in the Toolbox view make items (databases) available. To let SpineOpt know we want to use these items, we need to go to the properties panel of Run SpineOpt and drag the available items to the tool arguments. The order of the items is first the input, then the output. See below for how the property window should look.

image

  • (optional) The Spine data stores are quite generic. In order for SpineOpt to be able to read the input database, we need to change its format from the Spine format to the SpineOpt format. Luckily we can use templates for this. One of those templates is made available as an item in Spine Toolbox: Load template. The other option is to load templates into the database using the db editor. The templates can also be used to pre-populate the database with some basic components. Here we briefly explain the use of the Load template block and later we show how to import a template and basic components with the spine db editor. To use the Load template block, drag it to the view and connect it to the input database. Just like the Run SpineOpt block we need to drag the available input database to the tool argument.

The result should look similar to this (+/- the Load template block):

image

That is it for the workflow. Now we can enter the data for the setup of the simple system into the input database, run the workflow and view the results in the output database.

Entering input data

To enter the necessary data for the simple system, we'll use the Spine DB editor. The Spine DB editor is a dedicated interface within Spine Toolbox for visualizing and managing Spine databases. The default view shows tables (see below) but for viewing energy system configurations it is nice to see a graph. Press the graph button in the toolbar. The graph view only shows what you select in the root menu and what your selected entities are connected to.

To open the editor:

  • Double click the input Data Store item (or select the 'input' Data Store item in the Design View, go to Data Store Properties and hit Open editor).

image

In the following we enter the input data for the simple system.

Importing the SpineOpt database template

A SpineOpt database is a spine database but a spine database is not necessarily a SpineOpt database. Therefore we first need to format the database to a SpineOpt database with the SpineOpt template. The SpineOpt template contains the fundamental entity classes and parameter definitions that SpineOpt recognizes and expects. One option to load the template is to use the 'Load template' tool as mentioned before. Another option is to import the template with the Spine DB editor. To that end:

  • Download the SpineOpt database template (right click on the link, then select Save link as...)

  • To import the template to the database, click on File -> Import..., and then select the template file you previously downloaded (spineopt_template.json). The contents of that file will be imported into the current database, and you should then see classes like 'commodity', 'connection' and 'model' under the root menu.

  • To save our changes, press the Commit button in the toolbar. Enter a commit message, e.g. 'Import SpineOpt template', in the popup dialog and click Commit.

image

Model settings

A typical SpineOpt database has two parts: the model settings and the physical system.

The model settings that we need for this tutorial are also available as a template that we can import. The SpineOpt basic model template contains some predefined entities for a common deterministic model with a 'flat' temporal structure.

  • Download the basic SpineOpt model (right click on the link, then select Save link as...)

  • Import the template to the database through File -> Import..., and then select the template file you previously downloaded (basic_model_template.json).

  • Commit (save) the changes through the Commit button in the toolbar.

One of the predefined entities is the report. The report determines which variables of the SpineOpt model show up in the results later on. Currently, there is no output connected to the report. We'll have to do that manually:

  • Locate the Entity tree in the Spine DB editor (typically at the top-left).

  • Press the '+' next to the report__output class. The Add entities dialog will pop up.

  • We'll have to fill in the field for the report and the output. Double click the field to see the options. For the 'report' field we need 'report1' and for the 'output' field we only need 'unit_flow'.

  • Press Ok.

  • Commit (save) the changes through the Commit button in the toolbar.

  • Enter report1 under report, and unit_flow under output, as seen in the image below; then press Ok. This will tell SpineOpt to write the value of the unit_flow optimization variable to the output database, as part of report1.

image

The resulting model structure can then be seen in the picture below (by selecting the model, the stochastic structure and the report in the root menu).

image

Creating nodes and units

As for the physical system, we start with creating nodes and units. As shown before, the simple system contains 2 nodes and 2 units.

Info

In SpineOpt, nodes are points where an energy balance takes place, whereas units are energy conversion devices that can take energy from nodes, and release energy to nodes.

To create the nodes:

  • Locate the Entity tree in the Spine DB editor (typically at the top-left).

  • Right click on the [node] class, and select Add objects from the context menu (or press the '+' icon next to it). The Add entities dialog will pop up.

  • Enter the names for the system nodes as seen in the image below, then press Ok. This will create two entities of class node, called fuel and electricity.

image

To create the units we do the same thing:

  • Press '+' next to the unit class, and add two units called power_plant_a and power_plant_b.

image

Info

To modify an object after you enter it, right click on it and select Edit... from the context menu.

Creating relationships between the nodes and units

For the simple system we need to link the nodes and the units. Intuitively, we know that we need to make flows from the 'fuel' node to the units and to the 'electricity' node. Additionally we'll have to add a 'unit__node_node' entity to be able to add data on properties to the relation between the input and the output of the units.

For the flow from the 'fuel' node to the units:

  • Press '+' next to the unit__from_node class, you'll see a 'unit' field and a 'node' field.

  • Double click the unit or node field to see the options.

  • Select each unit once and the 'fuel' node twice, resulting in the combinations 'power_plant_a'-'fuel' and 'power_plant_b'-'fuel'.

Info

Alternatively right click the objects in the graph view and add relationships will show the available relationships. You can then make the desired relations visually. Note that this only works when the involved units/nodes/... are visible in the graph view. To make an object visible, simply click on the object in the list of objects/object classes. You can select multiple objects with ctrl or shift.

image

For the flow from the units to the 'electricity' node, we do the same:

  • Press '+' next to the unit__to_node class and choose each unit once and the 'electricity' node twice, resulting in the combinations 'power_plant_a'-'electricity' and 'power_plant_b'-'electricity'

image

These flows so far only determine what happens between the node and the unit. However, we also need to determine what happens between the input and output of the unit. As there can be multiple inputs and outputs, we'll have to define which flows exactly contribute to the input/output behaviour. To that end we use a unit__node__node class.

  • Press '+' next to the unit__node__node class and choose the unit, its output node and its input node, resulting in the combinations 'power_plant_a'-'electricity'-'fuel' and 'power_plant_b'-'electricity'-'fuel'

image

Info

The unit__node__node relationship is necessary to limit the flow (flows are unbound by default) and to define an efficiency. The order of the nodes is important for that definition (see later on). It may seem unintuitive to define an efficiency through a three-way relationship instead of a property of a unit, but this approach allows you to define efficiencies between any flow(s) coming in and out of the unit (e.g. CHP).

The resulting system can be seen in the picture below (by selecting the node in the root menu).

image

Adding parameter values

With the system in place, we can now enter the data as described in the beginning of this tutorial, i.e. the capacities, efficiencies, demand, etc. To enter the data we'll be using the table (typically in the center or below the graph view).

Info

The table view has three tabs below the table. We use the parameter value tab to enter values and the parameter definition tab to get an overview of the available parameters and their default values.

Let's start with adding an electricity demand of 150 at the electricity node.

  • Select the 'electricity' node in the root menu, in the graph view or in the list after double clicking the entity_by_name field in the table.

  • Double click the parameter_name field and select demand.

  • Double click the alternativet_name field and select Base.

  • Double click the value field and enter 150.

image

Info

The alternative name is not optional. If you don't select Base (or another name) you will not be able to save your data. Speaking of which, when is the last time you saved/committed?

For the fuel node we want an infinite supply. Since the default behaviour of a node is to balance all incoming and outgoing flows, we'll have to take that balance away.

In the table, select

  • entity_by_name: 'fuel' node

  • parameter_name: balance_type

  • alternative_name: Base

  • value: balance_type_none

image

For the power plants we want to specify the variable operation and maintenance (VOM) cost, the capacity and the efficiency. Each of these parameters are defined in different parts of the system. That is, again, because it is possible to define multiple inputs and outputs. To pinpoint the correct flows, the parameters are therefore related to the flows rather than the unit. In particular, the VOM cost is related to the input flow and as such to unit__from_node between the unit and the 'fuel' node. The capacity is related to the output flow and as such to unit__to_node between the unit and the 'electricity' node. The efficiency is related to the relation between the input and the output and as such to unit__node_node between the unit, the 'electricity' node and the 'fuel' node.

We enter these values again in the table.

For the VOM cost of the power plants:

  • select the unit__from_node entity class

  • entity_by_name: 'power_plant_a|fuel'

  • parameter_name: vom_cost

  • alternative_name: Base

  • value: 25.0

  • Do the same for 'power_plant_b' with a value of 50.0

image

For the capacity of the power plants:

  • select the unit__to_node entity class

  • entity_by_name: 'power_plant_a|electricity'

  • parameter_name: unit_capacity

  • alternative_name: Base

  • value: 100.0

  • Do the same for 'power_plant_b' with a value of 200.0

image

For the efficiency of the power plants:

  • select the unit__node_node entity class

  • entity_by_name: 'power_plant_a|electricity|fuel'

  • parameter_name: fix_ratio_out_in_unit_flow

  • alternative_name: Base

  • value: 0.7

  • Do the same for 'power_plant_b' with a value of 0.8

image

Info

The order of the nodes is important for the fix_ratio_out_in_unit_flow parameter. If you have swapped the nodes or inverted the efficiency values, the Run SpineOpt tool will run into errors.

When you're ready, save/commit all changes to the database.

Select the root in the entity tree to see an overview of all parameters in the table.

image

Executing the workflow

With the input database ready, we are ready to run SpineOpt.

  • Go back to Spine Toolbox's main window, and hit the Execute project button from the tool bar. You should see 'Executing All Directed Acyclic Graphs' printed in the Event log (at the bottom left by default).

  • Select the 'Run SpineOpt' Tool. You should see the output from SpineOpt in the Julia Console (after clicking the object activity control in older versions).

Examining the results

If everything went well, the output should be written to the output database. Opening the output database in the Spine DB editor, we can inspect its values. Note that the entity tree looks different as there is no SpineOpt template loaded here. Regardless, the output is available in the displayed tables.

By default all runs are shown in the tables. By selecting a specific run in the the alternatives (typically on the right), you can instead view the results of a single run.

Typically there will be Time Series in the values. Double click these to view the values.

For 'power_plant_a' you should see a value of 100 and for 'power_plant_b' a value of 50.