DistAIX Scenario Generator
This is the DistAIX Scenario Generator to generate scenarios in the format of the DistAIX simulator. The tool is capable of creating new electrical grids / scenarios based on existing grids, as well as from scratch. Custom topologies (networks of Slack/Trafo/Nodes) can be created and assembled with different types of consumers and producers (Load/CHP/EV/Wind...).
Repo Structure
-
src
folder containing the actual python script and modules of the ScenarioGenerator-
run.py
Main script used to the run the ScenarioGenerator -
scenarioGenerator.py
Module containing the main functions of the ScenarioGenerator -
inputReader.py
Module that realizes reading of user given inputs -
csvReaderWriter.py
Module used to write and read different csv-Files -
componentCreator.py
Module used to attach components to topology grids -
plotter.py
Module used to plot the resulting grid as a graph using pydot
-
-
subtypes
folder contains files including the different subtypes of components and cables needed during grid creation -
generated grids
folder contains the newly generated grids as well as different scenarios which can be used to test the ScenarioGenerator / create new scenarios -
basicgrids
folder contains medium as well as low voltage grids representing rural and urban environments-
1x_lv_rural
folder contains the 1x_lv_rural grid with variable cable lengths -
1x_lv_urban
folder contains a script to create the 1x_lv_urban grid with cariable cable lenghts as well as one version of the grid -
1x_mv_rural
folder contains a script to create the 1x_mv_rural grid with cariable cable lenghts as well as one version of the grid -
1x_mv_urban
folder contains a script to create the 1x_mv_urban grid with cariable cable lenghts as well as one version of the grid
-
Requirements
Due to the use of the pathlib
module, at least Python 3.4.0
has to be used.
When using the integrated plotting functionality to create a graph representing the created grid, the pydot
module has to be installed.
All input and output files are in comma-seperated values (csv) format.
Input files have to follow certain structures to ensure proper compatibility / usage of the ScenarioGenerator.
-
components.csv:
- Nodes: id, type, trafoID,*
- Other: id, type,*
- Arguments marked with * are not used by the ScenarioGenerator and therefore can have arbitrary order and content
-
el_grid.csv:
- id1, id2, cabletype, arg1*, arg2*, arg3*, arg4*, arg5*, arg6*, arg7*
- Arguments marked with * are not used by the ScenarioGenerator and therefore can have arbitrary order and content
-
lv_grids.csv:
(Only needed for-full-random
and-full-fixed
options) Each row includes the relative path of the directories of the low voltage grids, which can be attached to the corresponding medium voltage grid.
By default,../
is added to each path!
-
wished_connections.csv:
(Only needed for-full-fixed
option) Required per LV grid to be connected and has two columns:id_mv
|id_lv
. Theid_mv
column contains the node ID of the MV grid to which the LV grid shall be connected, theid_lv
column contains the ID of the LV node/transformer to which the connection shall be established. The file can contain multiple rows for as many times as a LV grid shall be connected to a given MV grid.
-
autoTopConf.csv:
(Only needed when using-top -auto
| Can have arbitrary name, path has to be given by the user) Each row defines one of the grids to be created. Each row has the following structure: grid_name,voltage_level,number_of_feeders,nodes_per_feeder,transformer_type,cable_type,cable_length
-
wished_nominal_power.csv:
(Optional for-mv
and-lv
) Each row contains a component type (e.g. load, chp, etc.) and a wished nominal power in kWs
-
subtypes_perc.csv:
(Only needed for-mv
and-lv
) Each row has to start with the identifier of the wished component type 'load_lv / chp_mv / ...' Followed by that, a percentage value [0.0,1.0] for each possible subtype has to follow in the same order, the subtypes are arranged in the corresponding subtypes file.
!! It is possible NOT to give percentages for a component type, then the generator distributes the nominal power equally !!
Usage
General
All the different functionalities are accessed by executing the main script run.py
with different parameters.
python3.6 run.py -args
-
-top
starts the creation of a new topology from scratch -
-mv
enables the user to attach medium voltage producers and consumers to a given grid -
-lv
enables the user to attach low voltage producers and consumers to a given grid -
-full
enables the user to attach multiple low voltage grids to given medium voltage topologies
-
-auto
enables automated creation of simple topologies from a given configuration file (has to be used with-top
)
-
-plot
calls the plot function (has to be used with one of the prior parameters) -
-merge-scenarios
merges two scenarios into one by adding components from the second scenario to the grid of the first scenario
Topology Creation
New topologies (feeder based networks of Slack/Trafo/Nodes) can be created using -top
.
python3.6 run.py -top
First, the user is asked for the voltage level of the topology. For this example, a medium voltage grid is going to be created.
>> Voltage level? [mv/lv]:
<< mv
Next, the amount of feeders and a transformer subtype has to be specified.
>> How many feeders should be created?
<< 2
>> Type of transformer?
<< MV_LV_rural
The transformer subtype has to match one of the subtypes defined in subtypes/transformer.csv
.
If the chosen subtype does not match the previously given voltage level, the ScenarioGenerator will notify the user and give him the possibility to change it.
Transformer does not match voltage level... Continue? [y/n]
Next, the desired number of feeders will be created one after another. The recursive nature of this method makes it possible to create as many levels of subfeeders as wished.
>> Number of nodes feeder 1:
<< 2
>> Type of cable?
<< MV_RURAL_CABLE_1
>> Length of cable in km?
<< 1.5
>> Dynamic cable length? [y/n]...
<< y
>> Wished variance in cable length in percentage [0.0-1.0]:
<< 0.2
>> Create subfeeders in feeder 1?
The type of cable has to fit a subtype defined in subtypes/cable.csv
.
If a dynamic cable length is wished, the user can give an additional percentage value between 0.0 and 1.0. Then the ScenarioGenerator will randomly select a length, which can differ from the specified cable length by the given percentage.
If subfeeder creation is used, the creation of subfeeders will only differ from the previous example in one additional dialog.
>> Attach subfeeder at which node?
<< 5
Here, the id of the node, where the subfeeder should be attached to, has to be given.
Medium Voltage Grid Creation
Existing medium voltage topologies can be extended with different producer and consumer components using this method.
<< python3.6 run.py -mv
At first, the relative path to the directory of the medium voltage topology has to be given.
By default ../
is added to the relative path!
>> Medium voltage grid:
<< generatedgrids/gentest_mv_top
In the example, the medium voltage generator testgrid without producer or consumer components was chosen.
If the directory does not include a subtypes_per.csv
file, defining the distribution of nominal power to the different subtypes, the user will be notified and has the chance to change the directory.
>> No subtypes_perc.csv file found...
>> Medium voltage grid:
After reading and evaluating the subtypes_perc.csv
file, the user will be asked if he wishes to create components for the given grid.
>> Medium voltage component creation wished? [y/n]
<< y
Hint: Answering with "n"
, when calling the script with the additional argument -plot
yields an easy way to plot a given grid.
In the following dialog, the user has to decide if the wished nominal powers should be read from a file or given manually.
>> Read wished nominal powers from file? [y/n]
<< y
If the user decides to read in the wished nominal powers from a corresponding csv file, wished_nominal_power.csv
has to exist in the grids directory.
If this file does not exist or the user decides to put in the nominal powers manually, the wished nominal powers for the different component types have to be given to the ScenarioGenerator.
>> Wished number of kilowatts per medium voltage component reqiured...
>> kW - load:
<< 3
>> kW - pv:
<< 2.5
>> kW - chp:
<< 100
>> kW - hp:
<< 23.2
>> kW - compensator:
<< 0
>> kW - biofuel:
<< 100
>> kW - wind:
<< 0.1
>> kW - storage:
<< 2
>> #####################
As it can be seen in the example, int
as well as float
values are valid.
Followed by this, the ScenarioGenerator tries to randomly select subtypes of the different component types, based on the percentages given in subtypers_perc.csv
, until it converges to the desired nominal power.
The given nominal power will not always be met exactly, but the actual created nominal powers will be written to generatedgrids/YYYY-DD-MM_HH-MM-SS/nominal_power.csv
.
>> echo nominal_power.csv
load_mv,750.0
pv_mv,100.0
chp_mv,107.5
hp_mv,18.0
compensator_mv,0.0
biofuel_mv,111.11000000000003
wind_mv,36.0
storage_mv,3.125
In a last step, the user is able to add an additional flag to all existing nodes, indicating if this node should participate in the communication based negotiations.
>> Adding new communication flag feature? This will add another column for nodes! Currently not compatible with Simulator!...[y/n]
If the user decides to add the additional flag, percentage values have to be given for each component type. Each node, connected to a component, will then set its flag with the percentage value given to the connected component types. This allows to realize scenarios like: "23% of Nodes, connected to PV components, should participate in communication procedures".
>> Percentage values with which different component types participate in communication required...
>> Percentage - load:
<< 23
>> Percentage - pv:
<< 100
>> Percentage - chp:
<< 11
>> Percentage - hp:
<< 0
>> Percentage - compensator:
<< 75
>> Percentage - ev:
<< 5
>> Percentage - wind:
<< 62
>> Percentage - storage:
<< 81
Flags will only be flipped to 1
and wont be changed back to 0
, no matter of the percentage values of other connected componentsm, i.e. if a node in the upper example is connected to a PV as well as a HP component, it will always participate in communication procedures.
Automated Topology Creation
For the creation of numerous simple (no bifurcations inside the feeders!) grids, including only one given load component per node, the previously described method can be automated.
<< python3.6 run.py -top -auto
Next, only the path to a previously generated configuration file has to be given to the ScenarioGenerator.
<< Path configuration file:
>> testConfig.csv
In the given example, this configuration file, named testConfig
, is located in the src
folder, but any other path can be given.
All of the created grids will be stored in seperate folders in the the generatedgrids
folder. For a clear identification of the generated grids, additionally the grid_name
, given for each grid in the configuration file, is attached to the folders name (YYYY-DD-MM_HH-MM-SS_grid_name
).
The needed structure of the configuration file has been described in the Requirements
section above.
At each created node, one component will be attached. The favored subtype (and with that the type implicitly) can be defined in subtypes/lv_auto.csv
and subtypes/mv_auto.csv
respectively. Simply copy and paste a given subtype from one of the subtype files into the given csv files. Take care to only have one subtype in those files at a time!!
Low Voltage Grid Creation
Existing low voltage topologies can be extended with different producer and consumer components using this method.
<< python3.6 run.py -lv
Works similar to the Medium Voltage Grid Creation
but only low voltage producer and consumer components will be considered...
Full Grid Creation with random selection of LV grids
The Full Grid Creation enables the user to attach multiple low voltage grids to specified nodes of a medium voltage grid.
<< python3.6 run.py -full-random
At first, the relative path to the medium voltage grid has to be given.
By default ../
is added to the relative path!
>> Medium voltage grid:
<< generatedgrids/gentest_mv_comp
In the example, the medium voltage generator testgrid with attached consumer and producer components was chosen.
Next, the generator will inform the user how many nodes are unoccupied and therefore suited as connection points for the low voltage grids. Based on this information, the user has to give the wished number of low voltage grids he wants to attach.
>> 16 free nodes available...
>> How many LV grids should be created?
<< 16
Followed by that, the ScenarioGenerator will read and evaluate the lv_grids.csv
file, which has to be located in the medium voltage grid directory.
Next, the specified low voltage grids will be chosen randomly and attached to a random unoccupied node, until as many low voltage grids are created as the user desired.
If the number of LV grids to be created is larger than the number of unoccupied nodes, the user is asked if it is ok to connect multiple LV grids to the same node:
>> Can multiple LV grids be connected to one node (y or n)?
<< n
>> Wished number of LV grids is bigger than the number of free nodes!! Only %i low voltage grids will be attached!
or alternatively:
>> Can multiple LV grids be connected to one node (y or n)?
<< y
This feature is especially useful if multiple LV grids shall be connected to the same slack node as MV grid.
Full Grid Creation with fixed connections for LV grids
This feature has been added by Kaying Lee in the course of her Master's Thesis. It allows to connect LV grid to an MV grid with pre-defined fixed positions for the LV grids in the MV grid.
<< python3.6 run.py -full-fixed
>> connect LV grid to a fix MV node...
The function asks the user if the file wished_connections.csv
contained in folders of LV grids shall be used as input:
>> read wished_connections.csv?[y/n]
<< y
Answering with n
results in executing the random variant of the full grid creation (see above).
Similar to the other version, first the MV grid to be used has to be specified:
>> Medium voltage grid:
<< generatedgrids/gentest_mv_comp
The folder of the MV grid should contain a file lv_grids.csv
specifying which LV grids are available for connection.
Based on this list of paths and the wished_connections.csv
file, the LV grids are connected to the respective nodes of the MV grid.
Plotting
The argument -plot
can be used to create a graph representing the created grid.
To use this feature, the pydot
module has to be installed.
Plotting can be used in combination with each of the grid creation variations. In the corresponding graph, the nodes colors indicate the corresponding voltage level / creation method.
-
Green
nodes indicate a created topology -
Red
nodes indicate medium voltage grid nodes -
Blue
nodes indicate low voltage grid nodes
Note: This plotting feature is only recommended for small grids (<150 nodes).
Hint: For simply plotting a given grid without manipulating it, call the script for the corresponding voltage level -lv/-mv
and decline component creation...
<< python3.6 run.py -mv -plot
>> Medium voltage grid:
<< generatedgrids/gentest_mv_top
>> Medium voltage component creation wished? [y/n]
<< n
...
Merging scenarios
In order to merge two scenarios the scenariogenerator has to be started with the -merge-scenarios
argument.
The user is requested to enter the path to the first and the second grid.
../
is added automatically as a prefix to the paths entered by the user.
If the two provided scenarios comprise a different number of nodes, a warning will be displayed.
The entire process is depicted in the listing below.
<< python3.6 run.py -merge-scenarios
>> Scenario merge started..
>> First grid:
<< path/to/first/grid
>> Reading component files...
>> Opening ../path/to/first/grid/components.csv...
>> highestNodeId 0 = 10
>> Reading electrical grid files...
>> Opening ../path/to/first/grid/el_grid.csv...
>> Second grid:
<< path/to/second/grid
>> Reading component files...
>> Opening ../path/to/second/grid/components.csv...
>> highestNodeId 0 = 12
>> Reading electrical grid files...
>> Opening ../path/to/second/grid/el_grid.csv...
>> Warning: The two scenarios have a different number of nodes
The scenariogenerator opens the two scenarios and merges them. For that purpose the first scenario is used as a basis. Components from the second grid are added to the first grid and connected to the nodes, with the same ID as in the second grid. For example, a load connected to node 8 in the second grid will be connected to node 8 in the frist grid. If the second scenario comprises more nodes than the first scenario, all components connected to nodes with a higher ID than the highest node ID in the first scenario will be ignored. In the example above that means that components in the second scenario connected to nodes 11 or 12 will be ignored.
The resulting scenario is stored in the generatedgrids
directory.
Copyright
2019, Institute for Automation of Complex Power Systems, EONERC
License
This project is released under the terms of the GPL version 3.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
For other licensing options please consult Prof. Antonello Monti.
Contact
- Sonja Happ sonja.happ@eonerc.rwth-aachen.de
- Felix Wege felix.wege@eonerc.rwth-aachen.de
Institute for Automation of Complex Power Systems (ACS)
EON Energy Research Center (EONERC)
RWTH University Aachen, Germany