Skip to content

Commit

Permalink
address PR requests + adding table with results
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Garcia Reolid <victor@seita.nl>
  • Loading branch information
victorgarcia98 committed Aug 2, 2023
1 parent 19ca0d4 commit e5444ce
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 59 deletions.
2 changes: 1 addition & 1 deletion documentation/tut/toy-example-expanded.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,4 @@ Second, charging of the battery is also changed a bit (around 10am), as less can

We hope this part of the tutorial shows how to incorporate a limited grid connection rather easily with FlexMeasures. There are more ways to model such settings, but this is a straightforward one.

This tutorial showed the fastest way to a schedule. In :ref:`_tut_toy_schedule_process`, we'll go further into settings with more realistic ingredients: solar panels and a limited grid connection.
This tutorial showed a quick way to add an inflexible load (like solar power) and a grid connection. In :ref:`tut_toy_schedule_process`, we'll turn to something different: the optimal timing of processes with fixed energy work and duration.
19 changes: 8 additions & 11 deletions documentation/tut/toy-example-from-scratch.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,26 @@ Toy example: Scheduling a battery, from scratch

Let's walk through an example from scratch! We'll optimize a 12h-schedule for a battery that is half full.

What do you need? Your own computer, with one of two situations: either you have `Docker <https://www.docker.com/>`_ or your computer supports Python 3.8+, pip and PostgresDB. The former might be easier, see the installation step below. But you choose.
Okay, let's get started!

Below are the ``flexmeasures`` CLI commands we'll run, and which we'll explain step by step. There are some other crucial steps for installation and setup, so this becomes a complete example from scratch, but this is the meat:
.. note:: You can copy the commands by hovering on the top right corner of code examples. You'll copy only the commands, not the output!

.. code-block:: bash
Setup
------

# make the schedule
$ flexmeasures add schedule for-storage --sensor-id 1 --consumption-price-sensor 2 \
--start ${TOMORROW}T07:00+01:00 --duration PT12H \
--soc-at-start 50% --roundtrip-efficiency 90%
.. note:: If you haven't run through :ref:`tut_install_load_data` yet, do that first. There, we added power prices for a 24h window.

For this tutorial, we'll setup a battery asset and a (dis)charging sensor (ID 2) where the schedule will be stored into.

Okay, let's get started!


.. note:: You can copy the commands by hovering on the top right corner of code examples. You'll copy only the commands, not the output!

Make a schedule
---------------------------------------

Finally, we can create the schedule, which is the main benefit of FlexMeasures (smart real-time control).
After going through the setup, we can finally create the schedule, which is the main benefit of FlexMeasures (smart real-time control).

We'll ask FlexMeasures for a schedule for our discharging sensor (ID 2). We also need to specify what to optimize against. Here we pass the Id of our market price sensor (ID 1).
We'll ask FlexMeasures for a schedule for our (dis)charging sensor (ID 2). We also need to specify what to optimize against. Here we pass the Id of our market price sensor (ID 1).
To keep it short, we'll only ask for a 12-hour window starting at 7am. Finally, the scheduler should know what the state of charge of the battery is when the schedule starts (50%) and what its roundtrip efficiency is (90%).

.. code-block:: bash
Expand Down
70 changes: 42 additions & 28 deletions documentation/tut/toy-example-process.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
.. _tut_toy_schedule_process:



Toy example III: Computing schedules for processes
====================================================================
====================================================

Until this point we've been using a static battery, one of the most flexible energy assets, to reduce electricity bills.

However, in some settings, we can reduce electricity bills by *just* consuming energy smartly. In other words, if the process can be displaced, by breaking it into smaller consumption periods or shifting its start time, the process run can match the lower price hours better.

For example, we could have a load that consumes energy at a constant rate (e.g. 100kW) for a fixed duration (e.g. 3h), but there's some flexibility in the start time. In that case, we could find the optimal start time in order to minimize the energy cost.
For example, we could have a load that consumes energy at a constant rate (e.g. 200kW) for a fixed duration (e.g. 4h), but there's some flexibility in the start time. In that case, we could find the optimal start time in order to minimize the energy cost.

Examples of flexible processes are:
- Water irrigation in agriculture
Expand All @@ -36,14 +34,7 @@ Before moving forward, we'll add the `process` asset and three sensors to store
.. code-block:: bash
$ flexmeasures add toy-account --kind process
Asset type solar already exists.
Asset type wind already exists.
Asset type one-way_evse already exists.
Asset type two-way_evse already exists.
Asset type battery already exists.
Asset type building already exists.
Asset type process already exists.
Account '<Account Toy Account (ID:1)>' already exists. Skipping account creation. Use `flexmeasures delete account --id 1` if you need to remove it.
User with email toy-user@flexmeasures.io already exists in account Toy Account.
The sensor recording day-ahead prices is day-ahead prices (ID: 1).
Expand All @@ -60,51 +51,74 @@ Before moving forward, we'll add the `process` asset and three sensors to store
Trigger an updated schedule
----------------------------
In this example, we are planning to consume 200kW for a period of 4h, tomorrow.
In this example, we are planning to consume at a 200kW constant power for a period of 4h.
This load is to be schedule for tomorrow, except from the period from 3pm to 4pm (imposed using the ``--forbid`` flag).
In addition, we'll add a time period in which the scheduler won't be able to run the process.
Now we are ready to schedule a process. Let's start with the INFLEXIBLE policy, the simplest. The scheduler
cannot schedule the process to run within the first hour after midnight.
Now we are ready to schedule a process. Let's start with the INFLEXIBLE policy, the simplest.
.. code-block:: bash
flexmeasures add schedule for-process --sensor-id 4 --consumption-price-sensor 1\
--start ${TOMORROW}T00:00:00+02:00 --duration PT24H --process-duration PT4H \
--process-power 0.2MW --process-type INFLEXIBLE \
--forbid "{\"start\" : \"${TOMORROW}T00:00:00+02:00\", \"duration\" : \"PT1H\"}"
--forbid "{\"start\" : \"${TOMORROW}T15:00:00+02:00\", \"duration\" : \"PT1H\"}"
This policy consist of scheduling the process as soon as possible. That is from 1am to 5am, as the time restriction from 12am to 1am makes the scheduler unable to start at 12am.
Under the INFLEXIBLE policy, the process starts as soon as possible, in this case, coinciding with the start of the planning window.
Following the INFLEXIBLE policy, we'll schedule the same 4h block using a BREAKABLE policy.
In this other case, will restrict the period from 2pm to 3pm from scheduling any process. This block corresponds to the lowest price of the day.
.. code-block:: bash
flexmeasures add schedule for-process --sensor-id 5 --consumption-price-sensor 1\
--start ${TOMORROW}T00:00:00+02:00 --duration PT24H --process-duration PT4H \
--process-power 0.2MW --process-type BREAKABLE \
--forbid "{\"start\" : \"${TOMORROW}T14:00:00+02:00\", \"duration\" : \"PT1H\"}"
--forbid "{\"start\" : \"${TOMORROW}T15:00:00+02:00\", \"duration\" : \"PT1H\"}"
The BREAKABLE policy splits or breaks the process into blocks that can be scheduled discontinuously.
Finally, we'll schedule the process using the SHIFTABLE policy. We'll keep the same time restrictions as in the BREAKABLE process.
The BREAKABLE policy splits or breaks the process into blocks that can be scheduled discontinuously. The smallest possible unit is (currently) determined by the sensor's resolution.
Finally, we'll schedule the process using the SHIFTABLE policy.
.. code-block:: bash
flexmeasures add schedule for-process --sensor-id 6 --consumption-price-sensor 1\
--start ${TOMORROW}T00:00:00+02:00 --duration PT24H --process-duration PT4H \
--process-power 0.2MW --process-type SHIFTABLE \
--forbid "{\"start\" : \"${TOMORROW}T14:00:00+02:00\", \"duration\" : \"PT1H\"}"
--forbid "{\"start\" : \"${TOMORROW}T15:00:00+02:00\", \"duration\" : \"PT1H\"}"
Results
---------
The image below show the resulting schedules following each of the three policies. You will see similar results in your `FlexMeasures UI <http://localhost:5000/assets/4/>`_.
.. image:: https://github.com/FlexMeasures/screenshots/raw/main/tut/toy-schedule/asset-view-process.png
:align: center
|
The image above show the schedules following the three policies.
In the first policy, there's no flexibility and it needs to schedule as soon as possible. Meanwhile, in the BREAKABLE policy, the consumption blocks surrounds the time restriction to consume in the cheapest hours. Finally, in the SHIFTABLE policy, the process is shifted to capture the best prices, avoiding the time restrictions.
In the first policy, there's no flexibility and it needs to schedule the process as soon as possible.
Meanwhile, in the BREAKABLE policy, the consumption blocks surrounds the time restriction to consume in the cheapest hours. Among the three polices, the BREAKABLE policy can achieve the best
Finally, in the SHIFTABLE policy, the process is shifted to capture the best prices, avoiding the time restrictions.
Quantitatively, comparing the total cost of running the process under each policy, the BREAKABLE policy achieves the best results. This is because it can fit much more consumption blocks in the cheapest hours.
+-------------------------+------------+-----------+-----------+
| Block | INFLEXIBLE | BREAKABLE | SHIFTABLE |
+=========================+============+===========+===========+
| 1 | 10.00 | 5.00 | 10.00 |
+-------------------------+------------+-----------+-----------+
| 2 | 11.00 | 4.00 | 8.00 |
+-------------------------+------------+-----------+-----------+
| 3 | 12.00 | 5.50 | 5.00 |
+-------------------------+------------+-----------+-----------+
| 4 | 15.00 | 7.00 | 4.00 |
+-------------------------+------------+-----------+-----------+
| Average Price (EUR/MWh) | 12.00 | 5.37 | 6.75 |
+-------------------------+------------+-----------+-----------+
| Total Cost (EUR) | 9.60 | 4.29 | 5.40 |
+-------------------------+------------+-----------+-----------+
59 changes: 40 additions & 19 deletions documentation/tut/toy-example-setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,29 @@ FlexMeasures offers a command to create a toy account with a battery:

.. code-block:: bash
$ flexmeasures add toy-account
$ flexmeasures add toy-account --kind battery
Generic asset type `solar` created successfully.
Generic asset type `wind` created successfully.
Generic asset type `one-way_evse` created successfully.
Generic asset type `two-way_evse` created successfully.
Generic asset type `battery` created successfully.
Generic asset type `building` created successfully.
Generic asset type `process` created successfully.
Creating account Toy Account ...
Toy account Toy Account with user toy-user@flexmeasures.io created successfully. You might want to run `flexmeasures show account --id 1`
The sensor recording battery power is <Sensor 2: discharging, unit: MW res.: 0:15:00>.
The sensor recording day-ahead prices is <Sensor 1: day-ahead prices, unit: EUR/MWh res.: 1:00:00>.
The sensor recording solar forecasts is <Sensor 3: production, unit: MW res.: 0:15:00>.
Adding transmission zone type ...
Adding NL transmission zone ...
Created day-ahead prices
The sensor recording day-ahead prices is day-ahead prices (ID: 1).
Created <GenericAsset None: 'toy-battery' (battery)>
Created discharging
Created <GenericAsset None: 'toy-solar' (solar)>
Created production
The sensor recording battery discharging is discharging (ID: 2).
The sensor recording solar forecasts is production (ID: 3).
And with that, we're done with the structural data for this tutorial!

Expand All @@ -138,17 +156,18 @@ If you want, you can inspect what you created:
Account has no roles.
All users:
Id Name Email Last Login Roles
---- -------- ------------------------ ------------ -------------
1 toy-user toy-user@flexmeasures.io account-admin
ID Name Email Last Login Last Seen Roles
---- -------- ------------------------ ------------ ----------- -------------
1 toy-user toy-user@flexmeasures.io None None account-admin
All assets:
ID Name Type Location
---- ----------- ------- -----------------
2 toy-battery battery (52.374, 4.88969)
3 toy-solar solar (52.374, 4.88969)
ID Name Type Location
---- ------------ -------- -----------------
2 toy-battery battery (52.374, 4.88969)
3 toy-solar solar (52.374, 4.88969)
$ flexmeasures show asset --id 2
Expand All @@ -157,17 +176,18 @@ If you want, you can inspect what you created:
=========================
Type Location Attributes
------- ----------------- ---------------------
------- ----------------- ----------------------------
battery (52.374, 4.88969) capacity_in_mw: 0.5
min_soc_in_mwh: 0.05
max_soc_in_mwh: 0.45
sensors_to_show: [2, [3, 1]]
sensors_to_show: [1, [3, 2]]
All sensors in asset:
ID Name Unit Resolution Timezone Attributes
ID Name Unit Resolution Timezone Attributes
---- ----------- ------ ------------ ---------------- ------------
2 discharging MW 15 minutes Europe/Amsterdam
2 discharging MW 15 minutes Europe/Amsterdam
Yes, that is quite a large battery :)
Expand All @@ -189,7 +209,7 @@ Visit `http://localhost:5000/ <http://localhost:5000/>`_ (username is "toy-user@
Add some price data
---------------------------------------
Now to add price data. First, we'll create the csv file with prices (EUR/MWh, see the setup for sensor 1 above) for tomorrow.
Now to add price data. First, we'll create the CSV file with prices (EUR/MWh, see the setup for sensor 1 above) for tomorrow.
.. code-block:: bash
Expand Down Expand Up @@ -220,7 +240,7 @@ Now to add price data. First, we'll create the csv file with prices (EUR/MWh, se
$ ${TOMORROW}T22:00:00,10
$ ${TOMORROW}T23:00:00,7" > prices-tomorrow.csv
This is time series data, in FlexMeasures we call "beliefs". Beliefs can also be sent to FlexMeasures via API or imported from open data hubs like `ENTSO-E <https://github.com/SeitaBV/flexmeasures-entsoe>`_ or `OpenWeatherMap <https://github.com/SeitaBV/flexmeasures-openweathermap>`_. However, in this tutorial we'll show how you can read data in from a CSV file. Sometimes that's just what you need :)
This is time series data, in FlexMeasures we call *"beliefs"*. Beliefs can also be sent to FlexMeasures via API or imported from open data hubs like `ENTSO-E <https://github.com/SeitaBV/flexmeasures-entsoe>`_ or `OpenWeatherMap <https://github.com/SeitaBV/flexmeasures-openweathermap>`_. However, in this tutorial we'll show how you can read data in from a CSV file. Sometimes that's just what you need :)
.. code-block:: bash
Expand All @@ -236,6 +256,7 @@ Let's look at the price data we just loaded:
.. code-block:: bash
$ flexmeasures show beliefs --sensor-id 1 --start ${TOMORROW}T00:00:00+01:00 --duration PT24H
Beliefs for Sensor 'day-ahead prices' (ID 1).
Data spans a day and starts at 2022-03-03 00:00:00+01:00.
The time resolution (x-axis) is an hour.
Expand Down

0 comments on commit e5444ce

Please sign in to comment.