Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/update documentation #424

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 43 additions & 102 deletions doc/features_in_detail.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ Power flow analysis
In order to analyse voltages and line loadings a non-linear power flow analysis (PF) using pypsa is conducted.
All loads and generators are modelled as PQ nodes. The slack is positioned at the substation's secondary side.

Multi period optimal power flow
---------------------------------

.. warning:: The non-linear optimal power flow is currently not maintained and might not work out of the box!
Optimal power flow
--------------------

.. todo:: Add
.. todo:: Add information. Text from final report of egon can partly be used (chapter 6.5.2.2).
The four options defined through opf_version in pm_optimize need to be described.
Also reference to Maikes master's thesis needs to be added.

.. _grid_expansion_methodology:

Expand Down Expand Up @@ -173,6 +173,7 @@ Reinforce lines due to voltage
After each feeder with voltage problems has been considered, a power flow analysis is conducted and the voltage rechecked. The process of solving voltage issues is repeated until voltage issues are solved
or until the maximum number of allowed iterations is reached.

ToDo: Enhanced reinforcement

Grid expansion costs
^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -188,79 +189,6 @@ The population density is calculated by the population and area of the grid dist
Costs for lines of aggregated loads and generators are not considered in the costs calculation since grids of
aggregated areas are not modeled but aggregated loads and generators are directly connected to the MV busbar.

.. _curtailment_in_detail-label:

Curtailment
-----------

.. warning:: The curtailment methods are not yet adapted to the refactored code and therefore currently do not work.

eDisGo right now provides two curtailment methodologies called 'feedin-proportional' and 'voltage-based', that are implemented in
:py:mod:`~edisgo.flex_opt.curtailment`.
Both methods are intended to take a given curtailment target obtained from an optimization of the EHV and HV grids using
`eTraGo <https://github.com/openego/eTraGo>`_ and allocate it to the generation units in the grids. Curtailment targets can be specified for all
wind and solar generators,
by generator type (solar or wind) or by generator type in a given weather cell.
It is also possible to curtail specific generators internally, though a user friendly implementation is still in the works.

'feedin-proportional'
^^^^^^^^^^^^^^^^^^^^^^^^

The 'feedin-proportional' curtailment is implemented in :py:func:`~edisgo.flex_opt.curtailment.feedin_proportional`.
The curtailment that has to be met in each time step is allocated equally to all generators depending on their share of total
feed-in in that time step.

.. math::
c_{g,t} = \frac{a_{g,t}}{\sum\limits_{g \in gens} a_{g,t}} \times c_{target,t} ~ ~ \forall t\in timesteps

where :math:`c_{g,t}` is the curtailed power of generator :math:`g` in timestep :math:`t`, :math:`a_{g,t}` is the weather-dependent availability
of generator :math:`g` in timestep :math:`t` and :math:`c_{target,t}` is the given curtailment target (power) for timestep :math:`t` to be allocated
to the generators.

'voltage-based'
^^^^^^^^^^^^^^^^^^^^^^^^

The 'voltage-based' curtailment is implemented in :py:func:`~edisgo.flex_opt.curtailment.voltage_based`.
The curtailment that has to be met in each time step is allocated to all generators depending on
the exceedance of the allowed voltage deviation at the nodes of the generators. The higher the exceedance, the higher
the curtailment.

The optional parameter *voltage_threshold* specifies the threshold for the exceedance of the allowed voltage deviation above
which a generator is curtailed. By default it is set to zero, meaning that all generators at nodes with voltage deviations
that exceed the allowed voltage deviation are curtailed. Generators at nodes where the allowed voltage deviation is not
exceeded are not curtailed. In the case that the required
curtailment exceeds the weather-dependent availability of all generators with voltage deviations above the specified threshold,
the voltage threshold is lowered in steps of 0.01 p.u. until the curtailment target can be met.

Above the threshold, the curtailment is proportional to the exceedance of the allowed voltage deviation.

.. math::
\frac{c_{g,t}}{a_{g,t}} = n \cdot (V_{g,t} - V_{threshold, g, t}) + offset

where :math:`c_{g,t}` is the curtailed power of generator :math:`g` in timestep :math:`t`, :math:`a_{g,t}` is the weather-dependent availability
of generator :math:`g` in timestep :math:`t`, :math:`V_{g,t}` is the voltage at generator :math:`g` in timestep :math:`t` and
:math:`V_{threshold, g, t}` is the voltage threshold for generator :math:`g` in timestep :math:`t`. :math:`V_{threshold, g, t}` is calculated as follows:

.. math::
V_{threshold, g, t} = V_{g_{station}, t} + \Delta V_{g_{allowed}} + \Delta V_{offset, t}

where :math:`V_{g_{station}, t}` is the voltage at the station's secondary side, :math:`\Delta V_{g_{allowed}}` is the allowed voltage
deviation in the reverse power flow and :math:`\Delta V_{offset, t}` is the exceedance of the allowed voltage deviation above which generators are curtailed.

:math:`n` and :math:`offset` in the equation above are slope and y-intercept of a linear relation between
the curtailment and the exceedance of the allowed voltage deviation. They are calculated by solving the following linear problem that penalizes the offset
using the python package pyomo:

.. math::
min \left(\sum\limits_{t} offset_t\right)

.. math::
s.t. \sum\limits_{g} c_{g,t} = c_{target,t} ~ \forall g \in (solar, wind) \\
c_{g,t} \leq a_{g,t} \forall g \in (solar, wind),t

where :math:`c_{target,t}` is the given curtailment target (power) for timestep :math:`t` to be allocated
to the generators.

.. _electromobility-integration-label:

Electromobility integration
Expand Down Expand Up @@ -317,31 +245,30 @@ minimum_charging_capacity_factor.
This is an active charging strategy. The cars are charged when the residual load in the MV grid is lowest
(high generation and low consumption). Charging processes with a low flexibility are given priority.

'grid-optimal'
""""""""""""""""""

.. _storage-integration-label:

Storage integration
--------------------

.. warning:: The storage integration methods described below are not yet adapted to the refactored code and therefore currently do not work.

Besides the possibility to connect a storage with a given operation to any node in the
grid, eDisGo provides a methodology that takes
a given storage capacity and allocates it to multiple smaller storage units such that it
reduces line overloading and voltage deviations.
The methodology is implemented in :py:func:`~edisgo.flex_opt.storage_positioning.one_storage_per_feeder`.
As the above described
curtailment allocation methodologies it is intended to be used in combination
with `eTraGo <https://github.com/openego/eTraGo>`_ where
storage capacity and operation is optimized.

For each feeder with load or voltage issues it is checked if integrating a
storage will reduce peaks in the feeder, starting with the feeder with
the highest theoretical grid expansion costs. A heuristic approach is used
to estimate storage sizing and siting while storage operation is carried
over from the given storage operation.

A more thorough documentation will follow soon.
.. todo:: Add information. Text below can be used (probably copied from somewhere, check
if it needs to be referenced). Maybe Maikes master's thesis is
also helpful and the eGon final report. Needs to be pointed out that this is
called through pm_optimize().

the flexibility potential for
controlled charging is mapped using
so-called flexibility bands. These bands comprise an upper and lower power band for
the charging power and an upper and lower energy band for the energy to be recharged
for each charging point in hourly resolution. The lower power band is always zero, as
power can only be drawn but not fed back into the grid. The upper power band describes
the maximum charging power that can be used for charging. This depends on the charging
power of the vehicle or the charging station, whichever is lower, and is zero if no
vehicle is present. The upper energy band describes the energy recharged at the
charging point in the event that the vehicle charges at full power immediately after
arriving at the charging station until it is fully charged. The lower energy band
describes the recharged energy in the event that the vehicle is charged as late as
possible. The charging process can be made more flexible within these bands. If there
are several charging stations at a charging point charging point, the bands are added
together. The flexibility bands are determined for each charging point within the
eDisGo tool and are not part of eGon-data.

Spatial complexity reduction
----------------------------
Expand Down Expand Up @@ -415,6 +342,12 @@ If you want more flexibility in using the complexity reduction, you can also run

For more details see the API documentation or the thesis where the methods were implemented and tested [SCR]_.

Temporal complexity reduction
-------------------------------

.. todo:: Add information on functions get_most_critical_time_steps() and get_most_critical_time_intervals().
Information can be found in final report of eGon project.

References
----------

Expand All @@ -431,3 +364,11 @@ References
.. [HoerschBrown] `Jonas Hörsch, Tom Brown: The role of spatial scale in joint optimisations of
generation and transmission for European highly renewable scenarios
<https://arxiv.org/pdf/1705.07617.pdf>`_

.. [MAMaike] `Master Thesis - Maike Held - Netzdienlich optimaler Einsatz von Flexibilitäten in
radialen Verteilnetzen basierend auf einem AC-Lastflussmodell (written in German)
<https://reiner-lemoine-institut.de/wp-content/uploads/2023/11/2023_MA_Maike_Held_Netzdienlich_optimaler_Einsatz_von_Flexibilitaeten.pdf>`_

.. [egon] `Final report: Ein offenes netzebenen- und sektorenübergreifendes Planungsinstrument zur Bestimmung des optimalen Einsatzes
und Ausbaus von Flexibilitätsoptionen in Deutschland (written in German)
<https://ego-n.org/papers/Endbericht_egon_v2.pdf>`_
20 changes: 9 additions & 11 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,14 @@ The toolbox currently includes:
* Automatic grid reinforcement methodology solving overloading and voltage issues
to determine grid expansion needs and costs based on measures most commonly
taken by German distribution grid operators
* Non-linear optimal power flow based on julia package PowerModels.jl optimizing
flexibility dispatch. Considered flexibilities are controlled charging of electric
vehicles, heat pumps with heat stores, demand side management, battery storage units,
and curtailment of renewables.
* Implementation of different charging strategies of electric vehicles
* Multiperiod optimal power flow based on julia package PowerModels.jl optimizing
storage positioning and/or operation (Currently not maintained)
as well as generator dispatch with regard to minimizing grid expansion costs
* Temporal complexity reduction
* Heuristic for grid-supportive generator curtailment (Currently not maintained)
* Heuristic grid-supportive battery storage integration (Currently not maintained)

Currently, a method to optimize the flexibility that can be provided by electric
vehicles through controlled charging is being implemented.
Prospectively, demand side management and reactive power management will
be included.
Prospectively, reactive power management will be included.

See :ref:`quickstart` for the first steps.
A deeper guide is provided in :ref:`usage-details`.
Expand All @@ -50,11 +46,13 @@ API reference.
eDisGo was initially developed in the
`open_eGo <https://openegoproject.wordpress.com>`_ research project as part of
a grid planning tool that can be used to determine the optimal grid and storage
expansion of the German power grid over all voltage levels and has been used in
two publications of the project:
expansion of the German power grid over all voltage levels. Since then, it has been
used and further developed in other research projects, most notably in the
`eGo^n <https://ego-n.org/>`_ project. For further reading see:

* `Integrated Techno-Economic Power System Planning of Transmission and Distribution Grids <https://www.mdpi.com/1996-1073/12/11/2091>`_
* `Final report of the open_eGo project (in German) <https://www.uni-flensburg.de/fileadmin/content/abteilungen/industrial/dokumente/downloads/veroeffentlichungen/forschungsergebnisse/20190426endbericht-openego-fkz0325881-final.pdf>`_
* `Final report of the eGo^n project (in German) <https://ego-n.org/papers/Endbericht_egon_v2.pdf>`_

Contents
==================
Expand Down
58 changes: 16 additions & 42 deletions doc/usage_details.rst
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,17 @@ Optimised

Use this mode to optimise flexibilities, e.g. charging of electric vehicles or
dispatch of heat pumps with thermal storage units.
It can be invoked as follows:

.. code-block:: python

edisgo.pm_optimize()

.. todo:: Add more details once the optimisation is merged.
Prior to the optimisation, you need to parametrise the flexibility options.

.. todo:: Add information on how flexibility bands for electric vehicle charging,
heat stores for heat pumps and DSM can be added. Maybe information below on
Electromobility and Heat pumps can simply be referenced.

Heuristic
..........
Expand Down Expand Up @@ -587,52 +596,15 @@ a time series for the storage unit needs to be provided.
index=edisgo.timeseries.timeindex)
)

To optimise storage positioning and operation eDisGo provides the options to use a
heuristic (described in section :ref:`storage-integration-label`) or an optimal power
flow approach. However, the storage integration heuristic is not yet adapted to the
refactored code and therefore not available, and the OPF is not maintained and may therefore
not work out of the box.
Following you find an example on how to use the OPF to find the optimal storage
positions in the grid with regard to grid expansion costs. Storage operation
is optimized at the same time. The example uses the same EDisGo instance as
above. A total storage capacity of 10 MW is distributed in the grid. `storage_buses`
can be used to specify certain buses storage units may be connected to.
This does not need to be provided but will speed up the optimization.

.. code-block:: python
Demand side management
------------------------

random_bus = edisgo.topology.buses_df.index[3:13]
edisgo.perform_mp_opf(
timesteps=period,
scenario="storage",
storage_units=True,
storage_buses=busnames,
total_storage_capacity=10.0,
results_path=results_path)
.. todo:: Add information on DSM class

Curtailment
-----------

The curtailment function is used to spatially distribute the power that is to be curtailed.
To optimise which generators should be curtailed eDisGo provides the options to use a
heuristics (heuristics `feedin-proportional` and `voltage-based`, in detail explained
in section :ref:`curtailment_in_detail-label`) or an optimal power
flow approach. However, the heuristics are not yet adapted to the
refactored code and therefore not available, and the OPF is not maintained and may therefore
not work out of the box.

In the following example the optimal power flow is used to find the optimal generator
curtailment with regard to minimizing grid expansion costs for given
curtailment requirements. It uses the EDisGo object from above.

.. code-block:: python

edisgo.perform_mp_opf(
timesteps=period,
scenario='curtailment',
results_path=results_path,
curtailment_requirement=True,
curtailment_requirement_series=[10, 20, 15, 0])
.. todo:: Curtailment can now be optimised as part of pm_optimize().

Plots
----------------
Expand Down Expand Up @@ -682,3 +654,5 @@ Results can be saved to csv files with:
edisgo.results.save('path/to/results/directory/')

See :meth:`~.network.results.Results.save` for more information.

.. todo:: Results of OPF are saved in OPFResults class in EDisGo.opf_results
Loading