Usage details

As eDisGo is designed to serve as a toolbox, it provides several methods to analyze distribution grids for grid issues and to evaluate measures responding these. We provide two examples, an example script and jupyter notebook.

Further, we discuss how different features can be used in detail below.

The fundamental data structure

It’s worth to understand how the fundamental data structure of eDisGo is designed in order to make use of its entire features.

The class EDisGo serves as the top-level API for setting up your scenario, invocation of data import, analysis of hosting capacity, grid reinforcement and flexibility measures.

If you want to set up a scenario to do a worst-case analysis of a ding0 grid (see Prerequisites) you simply have to provide a grid and set the worst_case_analysis parameter. The following example assumes you have a file of a ding0 grid named “ding0_grids__42.pkl” in current working directory.

from edisgo import EDisGo

edisgo = EDisGo(ding0_grid="ding0_grids__42.pkl",
                worst_case_analysis='worst-case-feedin')

You can also provide your own time series for load and feed-in for the analysis.

import pandas as pd

# set up load and feed-in time series
timeindex = pd.date_range('1/1/1970', periods=3, freq='H')
feedin_renewables = pd.DataFrame(data={'solar': [0.1, 0.2, 0.3],
                                       'wind': [0.3, 0.15, 0.15]},
                                 index=timeindex)
feedin_dispatchable = pd.DataFrame(data={'coal': [0.5, 0.1, 0.5],
                                         'other': [0.3, 0.1, 0.7]},
                                   index=timeindex)
load = pd.DataFrame(data={'residential': [0.00001, 0.00002, 0.00002],
                          'retail': [0.00005, 0.00005, 0.00005],
                          'industrial': [0.00002, 0.00003, 0.00002],
                          'agricultural': [0.00001, 0.000015, 0.00001]},
                    index=timeindex)

edisgo = EDisGo(ding0_grid="ding0_grids__42.pkl",
                timeseries_generation_fluctuating=feedin_renewables,
                timeseries_generation_dispatchable=feedin_dispatchable,
                timeseries_load=load)

EDisGo also offers methods to generate load time series and feed-in time series for fluctuating generators (see last A minimum working example). See EDisGo for more information on which options to choose from and what other data can be provided.

All data is stored in the class Network. The network class serves as an overall data container in eDisGo holding the grid data for the MVGrid and LVGrid s, Config data, Results, Timeseries, etc. It is linked from multiple locations and provides hierarchical access to all data. Network itself can be accessed via the EDisGo object.

# Access to Network data container object
edisgo.network

The grid data and results can e.g. be accessed via

# MV grid instance
edisgo.network.mv_grid

# List of LV grid instances
edisgo.network.mv_grid.lv_grids

# Results of network analysis
edisgo.network.results

# MV grid generators
edisgo.network.mv_grid.generators

The grid topology is represented by separate undirected graphs for the MV grid and each of the LV grids. The Graph is subclassed from networkx.Graph and extended by extra-functionality. Lines represent edges in the graph. Other equipment is represented by a node.

Identify grid issues

As detailed in A minimum working example, once you set up your scenario by instantiating an EDisGo object, you are ready for an analysis of grid issues (line overloading or voltage band violations) respectively the hosting capacity of the grid by analyze():

# Do non-linear power flow analysis for MV and LV grid
edisgo.analyze()

The analyze function conducts a non-linear power flow using PyPSA.

The range of time analyzed by the power flow analysis is by default defined by the timeindex given to the EDisGo API but can also be specified by providing the parameter timesteps to analyze.

Grid extension

Grid extension can be invoked by reinforce():

# Reinforce grid due to overloading and overvoltage issues
edisgo.reinforce()

You can further specify e.g. if to conduct a combined analysis for MV and LV (regarding allowed voltage deviations) or if to only calculate grid expansion needs without changing the topology of the graph. See reinforce() for more information.

Costs for the grid extension measures can be obtained as follows:

# Get costs of grid extension
costs = edisgo.network.results.grid_expansion_costs

Further information on the grid reinforcement methodology can be found in section Grid expansion.

Battery storages

Battery storages can be integrated into the grid as alternative to classical grid extension. A battery in eDisGo is represented by the class Storage. Using the method integrate_storage() provides a high-level interface to define the position, size and storage operation, based on user input and predefined rules. A limited set of storage integration rules are implemented. See StorageControl for available storage integration strategies.

Here is a small example on how to integrate a storage:

# define storage parameters
storage_parameters = {'nominal_power': 200}

# add storage instance to the grid
edisgo.integrate_storage(position='hvmv_substation_busbar',
                         timeseries='fifty-fifty',
                         parameters=storage_parameters)

Further information on the storage integration methodology ‘distribute_storages_mv’ can be found in section Storage integration.

Curtailment

The curtailment function is used to spatially distribute the power that is to be curtailed. There are currently two options for doing this distribution:

  • feedin-proportional
    Distributes the curtailed power to all the fluctuating generators depending on their weather-dependent availability.
  • voltage-based
    Distributes the curtailed power depending on the exceedance of the allowed voltage deviation at the nodes of the fluctuating generators.

The input to the curtailment function can be modified to curtail certain technologies or technologies by the weather cell they are in. Opposite to the load and feed-in time series curtailment time series need to be given in kW. Following are examples of the different options of how to specify curtailment requirements:

timeindex = pd.date_range('1/1/1970', periods=3, freq='H')

# curtailment is allocated to all solar and wind generators
curtailment = pd.Series(data=[0.0, 5000.0, 3000.0],
                        index=timeindex)

# curtailment is allocated by generator type
curtailment = pd.DataFrame(data={'wind': [0.0, 5000.0, 3000.0],
                                 'solar': [5500.0, 5400.0, 3200.0]},
                           index=timeindex)

# curtailment is allocated by generator type and weather cell
curtailment = pd.DataFrame(data={('wind', 1): [0.0, 5000.0, 3000.0],
                                 ('wind', 2): [100.0, 2000.0, 300.0],
                                 ('solar', 1): [500.0, 5000.0, 300.0]},
                           index=timeindex)

Set curtailment by calling the method curtail():

edisgo.curtail(curtailment_methodology='feedin-proportional',
               timeseries_curtailment=curtailment)

or with

edisgo.curtail(curtailment_methodology='voltage-based',
               timeseries_curtailment=curtailment)

Plots

EDisGo provides a bunch of predefined plots to e.g. plot the MV grid topology, and line loading and node voltages in the MV grid or as a histogram.

# plot MV grid topology on a map
edisgo.plot_mv_grid_topology()

# plot grid expansion costs for lines in the MV grid and stations on a map
edisgo.plot_mv_grid_expansion_costs()

# plot voltage histogram
edisgo.histogram_voltage()

See EDisGoRemiport class for more plots and plotting options.

Results

Results such as voltage levels and line loading from the power flow analysis and grid extension costs are provided through the Results class and can be accessed the following way:

edisgo.network.results

Get voltage levels at nodes from v_res() and line loading from s_res() or i_res. equipment_changes holds details about measures performed during grid extension. Associated costs are determined by grid_expansion_costs. Flexibility measures may not entirely resolve all issues. These unresolved issues are listed in unresolved_issues.

Results can be saved to csv files with:

edisgo.network.results.save('path/to/results/directory/')

To reimport saved results you can use the EDisGoRemiport class. After instantiating the class you can access results and plots the same way as you would with the EDisGo class.

# import EDisGoReimport class
from edisgo import EDisGoReimport

# instantiate EDisGoReimport class
edisgo = EDisGoReimport('path/to/results/directory/')

# access results
edisgo.network.results.grid_expansion_costs

# plot MV grid topology on a map
edisgo.plot_mv_grid_topology()